ddb

package
v3.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2024 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Set Global Secondary Index for the session
	WithGlobalSecondaryIndex = opts.ForName[Options, string]("index")

	// Configure the custom name for HashKey, default one is "prefix"
	WithHashKey = opts.ForName[Options, string]("hashKey")

	// Configure the custom name for SortKey, default one is "suffix"
	WithSortKey = opts.ForName[Options, string]("sortKey")

	// Configure CURIE prefixes, does nothing for DynamoDB
	WithPrefixes = opts.FMap(func(*Options, curie.Prefixes) error { return nil })

	// Enables strict serialization of the type, the I/O would fails
	// if type attributes does not match the storage schema.
	// It demand that storage schema "knows" all type attributes.
	WithStrictType = opts.ForName[Options, bool]("useStrictType")

	// Set DynamoDB client for the client
	WithService = opts.ForType[Options, DynamoDB]()

	// Set DynamoDB client for the client
	WithDynamoDB = opts.ForType[Options, DynamoDB]()

	// Configure client's DynamoDB to use provided the aws.Config
	WithConfig = opts.FMap(optsFromConfig)

	// Use default aws.Config for all DynamoDB clients
	WithDefaultDDB = opts.From(optsDefaultDDB)
)

Functions

func AllOf added in v3.0.5

func AllOf[T any](seq ...interface{ WriterOpt(T) }) interface{ WriterOpt(T) }

AllOf joins multiple constraint into higher-order constraint that is true when all of defined is true (aka AND logical expression)

func Decode

func Decode(av types.AttributeValue, val interface{}, coder ...Coder) (err error)

Decode is a helper function to decode core domain types from Dynamo DB format. The helper ensures compact URI de-serialization from DynamoDB schema.

  type MyType struct {
    ID   MyComplexType
    Name MyComplexType
  }
  var ID, Name = dynamo.Codec2[MyType, MyDynamoType, MyDynamoType]("ID", "Name")

  func (x *MyType) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error {
    type tStruct *MyType
    return dynamo.Decode(av, tStruct(x),
      ID.Decode((*MyDynamoType)(&x.ID)),
			Name.Decode((*MyDynamoType)(&x.Name)),
    )
  }

func Encode

func Encode(val interface{}, coder ...Coder) (types.AttributeValue, error)

Encode is a helper function to encode core domain types into struct. The helper ensures compact URI serialization into DynamoDB schema.

  type MyType struct {
    ID   MyComplexType
    Name MyComplexType
  }
  var ID, Name = dynamo.Codec2[MyType, MyDynamoType, MyDynamoType]("ID", "Name")

  func (x MyType) MarshalDynamoDBAttributeValue() (types.AttributeValue, error) {
    type tStruct MyType
    return dynamo.Encode(av, tStruct(x),
      ID.Encode(MyDynamoType(x.ID)),
			Name.Encode(MyDynamoType(x.Name)),
    )
  }

func OneOf added in v3.0.5

func OneOf[T any](seq ...interface{ WriterOpt(T) }) interface{ WriterOpt(T) }

OneOf joins multiple constraint into higher-order constraint that is true when one of defined is true (aka OR logical expression)

Types

type CodecOf

type CodecOf[T dynamo.Thing, A any] interface {
	Decode(*A) Coder
	Encode(A) Coder
}

CodecOf for struct fields, the type implement Encode/Decode primitives. Codec helps to implement semi-automated encoding/decoding algebraic data type into the format compatible with storage.

Let's consider scenario were application uses complex types that skips implementation of marshal/unmarshal protocols. Here the type MyComplexType needs to be casted to MyDynamoType that knows how to marshal/unmarshal the type.

type MyType struct {
  ID   MyComplexType
  Name MyComplexType
}
var (
  ID   = dynamo.Codec[MyType, MyDynamoType]("ID")
  Name = dynamo.Codec[MyType, MyDynamoType]("Name")
)

func (t MyType) MarshalDynamoDBAttributeValue() (*dynamodb.AttributeValue, error) {
  type tStruct MyType
  return dynamo.Encode(tStruct(p),
    ID.Encode(MyDynamoType(t.ID)),
    Name.Encode(MyDynamoType(t.Name)),
  )
}

func Codec

func Codec[T dynamo.Thing, A any](a string) CodecOf[T, A]

Build field codec for attribute

type Coder

Coder is a function, applies transformation of generic dynamodb AttributeValue

type ConditionExpression

type ConditionExpression[T dynamo.Thing, A any] struct {
	// contains filtered or unexported fields
}

func ClauseFor

func ClauseFor[T dynamo.Thing, A any](attr ...string) ConditionExpression[T, A]

See DynamoDB Conditional Expressions

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html

Schema declares type descriptor to express Storage I/O Constrains.

Let's consider a following example:

type Person struct {
  curie.ID
  Name    string `dynamodbav:"anothername,omitempty"`
}

How to define a condition expression on the field Name? Golang struct defines and refers the field by `Name` but DynamoDB stores it under the attribute `anothername`. Struct field dynamodbav tag specifies serialization rules. Golang does not support a typesafe approach to build a correspondence between `Name` ⟷ `anothername`. Developers have to utilize dynamodb attribute name(s) in conditional expression and Golang struct name in rest of the code. It becomes confusing and hard to maintain.

The Schema is helpers to declare builders for conditional expressions. Just declare a global variables next to type definition and use them across the application.

var (
	name = dynamo.ClauseFor[Person, string]("Name")
	addr = dynamo.ClauseFor[Person, Address]()
)

name.Eq("Joe Doe")
name.NotExists()

func (ConditionExpression[T, A]) Between

func (ce ConditionExpression[T, A]) Between(a, b A) interface{ WriterOpt(T) }

Between attribute condition

name.Between(a, b) ⟼ Field BETWEEN :a AND :b

func (ConditionExpression[T, A]) Contains

func (ce ConditionExpression[T, A]) Contains(val A) interface{ WriterOpt(T) }

Contains attribute condition

name.Contains(x) ⟼ contains(Field, :value)

func (ConditionExpression[T, A]) Eq

func (ce ConditionExpression[T, A]) Eq(val A) interface{ WriterOpt(T) }

Eq is equal condition

name.Eq(x) ⟼ Field = :value

func (ConditionExpression[T, A]) Exists

func (ce ConditionExpression[T, A]) Exists() interface{ WriterOpt(T) }

Exists attribute constrain

name.Exists(x) ⟼ attribute_exists(name)

func (ConditionExpression[T, A]) Ge

func (ce ConditionExpression[T, A]) Ge(val A) interface{ WriterOpt(T) }

Ge is greater or equal constrain

name.Le(x) ⟼ Field >= :value

func (ConditionExpression[T, A]) Gt

func (ce ConditionExpression[T, A]) Gt(val A) interface{ WriterOpt(T) }

Gt is greater than constrain

name.Le(x) ⟼ Field > :value

func (ConditionExpression[T, A]) HasPrefix

func (ce ConditionExpression[T, A]) HasPrefix(val A) interface{ WriterOpt(T) }

HasPrefix attribute condition

name.HasPrefix(x) ⟼ begins_with(Field, :value)

func (ConditionExpression[T, A]) In

func (ce ConditionExpression[T, A]) In(seq ...A) interface{ WriterOpt(T) }

In attribute condition

name.Between(a, b, c) ⟼ Field IN (:a, :b, :c)

func (ConditionExpression[T, A]) Is

func (ce ConditionExpression[T, A]) Is(val string) interface{ WriterOpt(T) }

Is matches either Eq or NotExists if value is not defined

func (ConditionExpression[T, A]) Le

func (ce ConditionExpression[T, A]) Le(val A) interface{ WriterOpt(T) }

Le is less or equal constain

name.Le(x) ⟼ Field <= :value

func (ConditionExpression[T, A]) Lt

func (ce ConditionExpression[T, A]) Lt(val A) interface{ WriterOpt(T) }

Lt is less than constraint

name.Lt(x) ⟼ Field < :value

func (ConditionExpression[T, A]) Ne

func (ce ConditionExpression[T, A]) Ne(val A) interface{ WriterOpt(T) }

Ne is non equal condition

name.Ne(x) ⟼ Field <> :value

func (ConditionExpression[T, A]) NotExists

func (ce ConditionExpression[T, A]) NotExists() interface{ WriterOpt(T) }

NotExists attribute constrain

name.NotExists(x) ⟼ attribute_not_exists(name)

func (ConditionExpression[T, A]) Optimistic added in v3.0.5

func (ce ConditionExpression[T, A]) Optimistic(val A) interface{ WriterOpt(T) }

Optimistic defines optimistic concurrency control (aka optimistic lock) condition.

name.Optimistic(x) ⟼ (Field = :value) or (attribute_not_exists(name))

type DynamoDB

DynamoDB declares interface of original AWS DynamoDB API used by the library

type Option

type Option = opts.Option[Options]

Option type to configure the S3

type Options

type Options struct {
	// contains filtered or unexported fields
}

Config Options

type Storage

type Storage[T dynamo.Thing] struct {
	Options
	// contains filtered or unexported fields
}

Storage type

func Must

func Must[T dynamo.Thing](keyval *Storage[T], err error) *Storage[T]

func New

func New[T dynamo.Thing](table string, opt ...Option) (*Storage[T], error)

New creates instance of DynamoDB api

func (*Storage[T]) BatchGet

func (db *Storage[T]) BatchGet(ctx context.Context, keys []T, opts ...interface{ GetterOpt(T) }) ([]T, error)

func (*Storage[T]) BatchPut added in v3.0.6

func (db *Storage[T]) BatchPut(ctx context.Context, entities []T, opts ...interface{ WriterOpt(T) }) ([]T, error)

Put multiple items at once

func (*Storage[T]) BatchRemove added in v3.0.6

func (db *Storage[T]) BatchRemove(ctx context.Context, keys []T, opts ...interface{ WriterOpt(T) }) ([]T, error)

Remove multiple items at once

func (*Storage[T]) Get

func (db *Storage[T]) Get(ctx context.Context, key T, opts ...interface{ GetterOpt(T) }) (T, error)

Get item from storage

func (*Storage[T]) Match

func (db *Storage[T]) Match(ctx context.Context, key T, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ MatcherOpt(T) }, error)

Match applies a pattern matching to elements in the table

func (*Storage[T]) MatchKey

func (db *Storage[T]) MatchKey(ctx context.Context, key dynamo.Thing, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ MatcherOpt(T) }, error)

Match applies a pattern matching to elements in the table

func (*Storage[T]) Put

func (db *Storage[T]) Put(ctx context.Context, entity T, opts ...interface{ WriterOpt(T) }) error

Put writes entity

func (*Storage[T]) Remove

func (db *Storage[T]) Remove(ctx context.Context, key T, opts ...interface{ WriterOpt(T) }) (T, error)

Remove discards the entity from the table

func (*Storage[T]) Update

func (db *Storage[T]) Update(ctx context.Context, entity T, opts ...interface{ WriterOpt(T) }) (T, error)

Update applies a partial patch to entity and returns new values

func (*Storage[T]) UpdateWith

func (db *Storage[T]) UpdateWith(ctx context.Context, expression UpdateItemExpression[T], opts ...interface{ WriterOpt(T) }) (T, error)

Update applies a partial patch to entity using update expression abstraction

type UpdateExpression

type UpdateExpression[T dynamo.Thing, A any] struct {
	// contains filtered or unexported fields
}

func UpdateFor

func UpdateFor[T dynamo.Thing, A any](attr ...string) UpdateExpression[T, A]

func (UpdateExpression[T, A]) Add

func (ue UpdateExpression[T, A]) Add(val A) interface{ UpdateExpression(T) }

Add new attribute and increment value

name.Add(x) ⟼ ADD Field :value

func (UpdateExpression[T, A]) Append

func (ue UpdateExpression[T, A]) Append(val A) interface{ UpdateExpression(T) }

Append element to list

name.Inc(x) ⟼ SET Field = list_append (Field, :value)

func (UpdateExpression[T, A]) Dec

func (ue UpdateExpression[T, A]) Dec(val A) interface{ UpdateExpression(T) }

Decrement attribute

name.Inc(x) ⟼ SET Field = Field - :value

func (UpdateExpression[T, A]) Inc

func (ue UpdateExpression[T, A]) Inc(val A) interface{ UpdateExpression(T) }

Increment attribute

name.Inc(x) ⟼ SET Field = Field + :value

func (UpdateExpression[T, A]) Minus

func (ue UpdateExpression[T, A]) Minus(val A) interface{ UpdateExpression(T) }

Delete elements from set

name.Minus(x) ⟼ ADD Field :value

func (UpdateExpression[T, A]) Prepend

func (ue UpdateExpression[T, A]) Prepend(val A) interface{ UpdateExpression(T) }

Prepend element to list

name.Inc(x) ⟼ SET Field = list_append (:value, Field)

func (UpdateExpression[T, A]) Remove

func (ue UpdateExpression[T, A]) Remove() interface{ UpdateExpression(T) }

Remove attribute

name.Remove() ⟼ REMOVE Field

func (UpdateExpression[T, A]) Set

func (ue UpdateExpression[T, A]) Set(val A) interface{ UpdateExpression(T) }

Set attribute

name.Inc(x) ⟼ SET Field = :value

func (UpdateExpression[T, A]) SetNotExists

func (ue UpdateExpression[T, A]) SetNotExists(val A) interface{ UpdateExpression(T) }

Set attribute if not exists

name.Inc(x) ⟼ SET Field = if_not_exists(Field, :value)

func (UpdateExpression[T, A]) Union

func (ue UpdateExpression[T, A]) Union(val A) interface{ UpdateExpression(T) }

Add elements to set

name.Union(x) ⟼ ADD Field :value

type UpdateItemExpression

type UpdateItemExpression[T dynamo.Thing] struct {
	// contains filtered or unexported fields
}

func Updater

func Updater[T dynamo.Thing](entity T, opts ...interface{ UpdateExpression(T) }) UpdateItemExpression[T]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL