ddb

package
v3.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 27, 2024 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

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)),
    )
  }

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)

type DynamoDB

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

type Option

type Option func(*Options)

Option type to configure the S3

func WithGlobalSecondaryIndex

func WithGlobalSecondaryIndex(index string) Option

WithTable defines dynamodb table

func WithHashKey

func WithHashKey(hashKey string) Option

WithHashKey defines custom name of HashKey, default one is "prefix"

func WithPrefixes

func WithPrefixes(prefixes curie.Prefixes) Option

WithPrefixes defines prefixes for CURIEs

func WithService

func WithService(service DynamoDB) Option

Configure AWS Service for broker instance

func WithSortKey

func WithSortKey(sortKey string) Option

WithHashKey defines custom name of SortKey, default one is "suffix"

func WithStrictType

func WithStrictType(strict bool) Option

WithTypeSchema demand that storage schema "knows" all type attributes

func WithTable

func WithTable(table string) Option

WithTable defines dynamodb table

type Options

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

Config Options

type Storage

type Storage[T dynamo.Thing] struct {
	// 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](opts ...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]) 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