dynamo

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Jan 19, 2024 License: MIT Imports: 21 Imported by: 2

README

Dynamo Package Usage Guide

This guide provides insights on utilizing the Row, MonoLink, DiLink, and TriLink types in the dynamo package. These types, designed for embedding into your structs, grant access to DynamoDB functionalities.

Prerequisites

Before using the dynamo package, ensure these environment variables are set:

  • AWS_REGION: The AWS region of your DynamoDB instance.
  • AWS_PROFILE: The AWS profile for authentication.
  • TABLENAME: The name of the DynamoDB table for interactions.

Row

The Row type represents a DynamoDB row and is the foundational type. Embed it into your struct as follows:

type MyStruct struct {
    dynamo.Row
    // Additional fields
}
Key Methods of Row
  • Keys(gsi int) (partitionKey, sortKey string, err error): Intended to return keys for the Composite Key (gsi0) or a Global Secondary Index (GSI). This method should be implemented in the parent struct. If undefined, the default behavior will assign a random UUID to the Pk and "row" as the sk.
  • Type() string: Returns the record's type, defaulting to "dilink" or the value of UnmarshalledType.
  • MaxShard() int: Every item written is also sharded on a special index. For types that are frequently written, this method may need to return an integer greater than the default of 100.
  • TableName(ctx context.Context) string: Retrieves the DynamoDB table name, defaulting to the "TABLENAME" environment variable.

These methods become part of the parent struct due to Go's embedded struct behavior, allowing for overriding in the parent struct.

The MonoLink type establishes a one-to-one relationship between entities in DynamoDB. Embed it as follows:

type MyStruct struct {
    dynamo.MonoLink[MyEntity]
    // Additional fields
}
  • Get retrieves the monolink from dynamo, if it exists.
  • Put method establishes a connection between entities.
  • Delete method removes the connection.

Example:

func ExampleUsage() {
    myStruct := MyStruct{
        MonoLink: dynamo.NewMonoLink(MyEntity{/* initialize your entity here */}),
        // Additional initialization
    }

    // Linking and unlinking entities
    // Handle errors appropriately
}

DiLink creates a one-to-one relationship between two entities. Embed it as follows:

type MyStruct struct {
    dynamo.DiLink[MyEntity1, MyEntity2]
    // Additional fields
}
  • Link and Unlink methods manage connections between two entities.
  • LoadEntity1 loads the other entity in a DiLink relationship.

Example:

func ExampleUsage() {
    myDiLink := dynamo.CheckDiLink(MyEntity1{/* initialize entity */}, nil)

    // Loading entities and error handling
}

TriLink is for establishing relationships among three entities in DynamoDB. Embed it in your struct:

type MyStruct struct {
    dynamo.TriLink[OtherStruct1, OtherStruct2, OtherStruct3]
    // Additional fields
}

Utilize the Link and Unlink methods to establish or remove connections between these entities.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DeleteItem

func DeleteItem(ctx context.Context, row types.Linkable) (*dynamodb.DeleteItemOutput, error)

DeleteItem deletes a row from DynamoDB. The row must implement the Keyable interface. This method uses the default client. If you need to use a specific client, use DeleteItemWithClient instead, or use the client.SetDefaultClient method.

func DeleteItemPrependType

func DeleteItemPrependType(ctx context.Context, row types.Linkable) (*dynamodb.DeleteItemOutput, error)

func FindLinksByEntity0 added in v0.0.4

func FindLinksByEntity0[T0, CustomLinkType ttypes.Linkable](ctx context.Context, e0 T0, linkType string) ([]CustomLinkType, error)

FindLinksByEntity0 is a generic method to query for a list of links based on the Entity0.

func FindLinksByEntity1 added in v0.0.4

func FindLinksByEntity1[T1, CustomLinkType ttypes.Linkable](ctx context.Context, e1 T1, linkType string) ([]CustomLinkType, error)

FindLinksByEntity1 is a generic method to query for a list of links based on the Entity1.

func FindLinksByEntity2 added in v0.0.4

func FindLinksByEntity2[T2, CustomLinkType ttypes.Linkable](ctx context.Context, e2 T2, linkType string) ([]CustomLinkType, error)

FindLinksByEntity2 is a generic method to query for a list of links based on the Entity2.

func GetItem

GetItem gets a row from DynamoDB. The row must implement the Keyable interface.

func GetItemWithTablename

func GetItemWithTablename(ctx context.Context, tablename string, row types.Linkable) (*dynamodb.GetItemOutput, error)

func PutItem

PutItem puts a row into DynamoDB. The row must implement the Keyable interface. This method uses the default client. If you need to use a specific client, use PutItemWithClient instead, or use the client.SetDefaultClient method.

func UpdateItem

UpdateItem updates a row in DynamoDB. The row must implement the DynamoUpdater interface. Consider embedding your type into a wrapper that implements DynamoUpdater in order to issue the desired update behavior.

This method uses the default client. If you need to use a specific client, use UpdateItemWithClient instead, or use the client.SetDefaultClient method.

func UpdateItemWithClient

func UpdateItemWithClient(ctx context.Context, client *clients.Client, row types.DynamoUpdater) (*dynamodb.UpdateItemOutput, error)

UpdateItemWithClient updates a row in DynamoDB. The row must implement the DynamoUpdater interface. Consider embedding your type into a wrapper that implements DynamoUpdater in order to issue a specific update behavior.

Types

type DBManager

type DBManager struct {
	// Tablename is a field you can set at runtime that will change the
	// name of the DynamoDB table that is used for operations.
	// It is ephemeral and will not be persisted to DynamoDB.
	Tablename        string
	GetItemOutput    *dynamodb.GetItemOutput    `dynamodbav:"-" json:"-"`
	PutItemOutput    *dynamodb.PutItemOutput    `dynamodbav:"-" json:"-"`
	DeleteItemOutput *dynamodb.DeleteItemOutput `dynamodbav:"-" json:"-"`

	// RowData is a map of data retrieved from DynamoDB during the last
	// GetItem operation. This is useful for comparing the old values
	// with the new values after a PutItem operation.
	RowData map[string]awstypes.AttributeValue `dynamodbav:"-" json:"-"`
}

DBManager is a struct that implements the DBManager interface. It is intended to be embedded into other types to provide them with DynamoDB operations.

func (*DBManager) BatchDelete

func (d *DBManager) BatchDelete(ctx context.Context, rows []types.Linkable) <-chan Result

BatchDelete deletes multiple rows from DynamoDB concurrently. The rows must implement the Keyable interface.

func (*DBManager) BatchGet

func (d *DBManager) BatchGet(ctx context.Context, rows []types.Linkable) <-chan Result

BatchGet gets multiple rows from DynamoDB concurrently. The rows must implement the Keyable interface.

func (*DBManager) BatchLoadFromMessage

func (d *DBManager) BatchLoadFromMessage(ctx context.Context, messages []sqstypes.Message, rows []types.Linkable) <-chan Result

BatchLoadFromMessage unmarshals multiple SQS messages into Rows and then loads the full items from DynamoDB concurrently.

func (*DBManager) BatchPut

func (d *DBManager) BatchPut(ctx context.Context, rows []types.Linkable) <-chan Result

BatchPut puts multiple rows into DynamoDB concurrently. The rows must implement the Linkable interface.

func (*DBManager) Delete

func (d *DBManager) Delete(ctx context.Context, row types.Linkable) (err error)

Delete deletes a row from DynamoDB. The row must implement the Keyable interface. The DeleteItemOutput response will be stored in the DeleteItemOutput field: d.DeleteItemOutput

func (*DBManager) Get

func (d *DBManager) Get(ctx context.Context, row types.Linkable) (loaded bool, err error)

Get gets a row from DynamoDB. The row must implement the Keyable interface. The GetItemOutput response will be stored in the GetItemOutput field: d.GetItemOutput

func (*DBManager) LoadFromMessage

func (d *DBManager) LoadFromMessage(ctx context.Context, message sqstypes.Message, row types.Linkable) (bool, error)

LoadFromMessage unmarshals an SQS message into a Row and then loads the full item from DynamoDB.

func (*DBManager) OldDeleteValues

func (d *DBManager) OldDeleteValues() map[string]awstypes.AttributeValue

OldDeleteValues returns the old values from the last successful DeleteItem operation.

func (*DBManager) OldPutValues

func (d *DBManager) OldPutValues() map[string]awstypes.AttributeValue

OldPutValues returns the old values from the last successful PutItem operation.

func (*DBManager) Put

func (d *DBManager) Put(ctx context.Context, row types.Linkable) (err error)

Put puts a row into DynamoDB. The row must implement the Linkable interface. The PutItemOutput response will be stored in the PutItemOutput field: d.PutItemOutput

func (*DBManager) TableName

func (d *DBManager) TableName(ctx context.Context) string

TableName returns the name of the DynamoDB table. By default, this is the value of the TABLENAME environment variable. If you need to override this, implement this method on the parent type.

func (*DBManager) WasGetSuccessful

func (d *DBManager) WasGetSuccessful() bool

WasGetSuccessful returns true if the last GetItem operation was successful.

func (*DBManager) WasPutSuccessful

func (d *DBManager) WasPutSuccessful() bool

type DBManagerInterface

type DBManagerInterface interface {
	TableName(ctx context.Context) string
	Get(ctx context.Context, row types.Linkable) (loaded bool, err error)
	WasGetSuccessful() bool
	Put(ctx context.Context, row types.Linkable) (err error)
	OldPutValues() map[string]awstypes.AttributeValue
	Delete(ctx context.Context, row types.Linkable) (err error)
	OldDeleteValues() map[string]awstypes.AttributeValue
	LoadFromMessage(ctx context.Context, message sqstypes.Message, row types.Linkable) (bool, error)
}

DBManagerInterface defines the interface for DynamoDB operations. An interface is used to allow for mocking in unit tests, as well as to limit the scope of the methods that are exposed to the parent type.

func NewDBManager

func NewDBManager(tableName string) DBManagerInterface

NewDBManager creates a new instance of DBManager and returns it as a DBManagerInterface.

type DiLink[T0 types.Linkable, T1 types.Linkable] struct {
	MonoLink[T0] // Embedding the MonoLink type for DynamoDB requirements

	E1pk string `dynamodbav:"e1pk" json:"e1pk,omitempty"`
	E1sk string `dynamodbav:"e1sk" json:"e1sk,omitempty"`

	Entity1 T1 `dynamodbav:"-" json:"entity1,omitempty"`
}

DiLink is a generic type that can link two entities together in dynamo. By Default the DiLink will establish a one-to-one relationship between the two entities using the primary keys. If you need to save or modify fields in the linked record, you will need to override this method.

func NewDiLink[T0, T1 types.Linkable](entity0 T0, entity1 T1) *DiLink[T0, T1]

NewDiLink creates a new DiLink instance.

func (link *DiLink[T0, T1]) CheckLink(ctx context.Context, linkWrapper types.Linkable, entity0 T0, entity1 T1) (linkExists bool, err error)

CheckLink accepts both entities and attempts to load the link from dynamo. It does not attempt to load the entities themselves, only the link.

func (*DiLink[T0, T1]) ExtractE1Keys

func (m *DiLink[T0, T1]) ExtractE1Keys() (string, string, error)

func (*DiLink[T0, T1]) GenerateDiLinkKeys

func (m *DiLink[T0, T1]) GenerateDiLinkKeys() (string, string, error)

func (*DiLink[T0, T1]) Keys

func (m *DiLink[T0, T1]) Keys(gsi int) (string, string, error)
func (m *DiLink[T0, T1]) Link(ctx context.Context, row types.Linkable) error

Link is a generic method to establish a connection between the two entities. Any two entities that embed the Row type can be linked together while maintaining primary key entropy equal to the sum of the two entities.

func (*DiLink[T0, T1]) LoadEntities

func (m *DiLink[T0, T1]) LoadEntities(ctx context.Context) (e0Loaded bool, e1Loaded bool, err error)

func (*DiLink[T0, T1]) LoadEntity0s

func (m *DiLink[T0, T1]) LoadEntity0s(ctx context.Context, linkWrapper ttypes.Linkable) ([]T0, error)

func (*DiLink[T0, T1]) LoadEntity1

func (m *DiLink[T0, T1]) LoadEntity1(ctx context.Context) (bool, error)

func (*DiLink[T0, T1]) LoadEntity1s

func (m *DiLink[T0, T1]) LoadEntity1s(ctx context.Context, linkWrapper ttypes.Typeable) ([]T1, error)

func (*DiLink[T0, T1]) Type

func (r *DiLink[T0, T1]) Type() string

Type returns the type of the record.

func (m *DiLink[T0, T1]) Unlink(ctx context.Context, row types.Linkable) error

Unlink method removes the connection between the two entities by deleting the link record.

type EntityGSI

type EntityGSI string

EntityGSI is the name of the GSI used to contain the composite key of the entity at the provided index.

const (
	// Entity0GSI is the name of the GSI used to contain the primary composite
	// key of the 0th entity.
	Entity0GSI EntityGSI = "e0pk-e0sk-index"
)
const (
	// Entity1GSI is the name of the GSI used to contain the primary composite
	// key of the 1st entity.
	Entity1GSI EntityGSI = "e1pk-e1sk-index"
)
const (
	// Entity2GSI is the name of the GSI used to contain the primary composite
	// key of the 2nd entity.
	Entity2GSI EntityGSI = "e2pk-e2sk-index"
)

func (EntityGSI) String

func (g EntityGSI) String() string

String

type ErrCouldNotValidateLink[T types.Typeable] struct {
	LinkType T
}

ErrCouldNotValidateLink is an error type for when a link's row data cannot be validated.

func (ErrCouldNotValidateLink[T]) Error

func (e ErrCouldNotValidateLink[T]) Error() string

type ErrEntityNotFound

type ErrEntityNotFound[T types.Typeable] struct {
	Entity T
}

ErrEntityNotFound is an error type for when a new membership cannot be created.

func (ErrEntityNotFound[T]) Error

func (e ErrEntityNotFound[T]) Error() string

type ErrInvalidGSI

type ErrInvalidGSI struct {
	GSI int
}

func (ErrInvalidGSI) Error

func (e ErrInvalidGSI) Error() string

type ErrInvalidKeySegment

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

func (ErrInvalidKeySegment) Error

func (e ErrInvalidKeySegment) Error() string

type ErrItemNotFound

type ErrItemNotFound struct {
	Row types.Linkable
}

func (ErrItemNotFound) Error

func (e ErrItemNotFound) Error() string

Error implements the error interface and will return the row type and keys.

type ErrLinkNotFound

type ErrLinkNotFound struct{}

ErrLinkNotFound is an error type for when a new membership cannot be created.

func (ErrLinkNotFound) Error

func (e ErrLinkNotFound) Error() string

type ErrLinkTypeMismatch

type ErrLinkTypeMismatch[T types.Typeable] struct {
	DynamoType string
	LinkType   T
}

ErrLinkTypeMismatch is an error type for when a new link should not be created due to a type mismatch between the dynamo row and the expected link type.

func (ErrLinkTypeMismatch[T]) Error

func (e ErrLinkTypeMismatch[T]) Error() string

type ErrSQSMessageEmpty

type ErrSQSMessageEmpty struct {
	Message sqstypes.Message
}

func (ErrSQSMessageEmpty) Error

func (e ErrSQSMessageEmpty) Error() string

type GSIName

type GSIName string

GSIName is a list of consts that represent the names of the GSIs that should be available on a dynamodb table.

const (
	// GSI1 is the name of the first GSI
	GSI1 GSIName = "pk1-sk1-index"
	// GSI2 is the name of the second GSI
	GSI2 GSIName = "pk2-sk2-index"
	// GSI3 is the name of the third GSI
	GSI3 GSIName = "pk3-sk3-index"
	// GSI4 is the name of the fourth GSI
	GSI4 GSIName = "pk4-sk4-index"
	// GSI5 is the name of the fifth GSI
	GSI5 GSIName = "pk5-sk5-index"
	// GSI6 is the name of the sixth GSI
	GSI6 GSIName = "pk6-sk6-index"
)

func (GSIName) String

func (g GSIName) String() string

String returns the name of the GSI

type MonoLink[T0 types.Linkable] struct {
	Row // Embedding the Row type for DynamoDB requirements

	E0pk string `dynamodbav:"e0pk" json:"e0pk,omitempty"`
	E0sk string `dynamodbav:"e0sk" json:"e0sk,omitempty"`

	Entity0 T0 `dynamodbav:"-" json:"entity0,omitempty"`
}

MonoLink is a generic type that can link two entities together in dynamo. By Default the MonoLink will establish a one-to-one relationship between the two entities using the primary keys. If you need to save or modify fields in the linked record, you will need to override this method.

func NewMonoLink[T0 types.Linkable](entity0 T0) *MonoLink[T0]

NewMonoLink creates a new MonoLink instance.

func (link *MonoLink[T0]) CheckLink(ctx context.Context, linkWrapper types.Linkable, entity0 T0) (linkLoaded bool, err error)

CheckLink accepts both entities and attempts to load the link from dynamo. It does not attempt to load the entity itself, only the link.

func (*MonoLink[T0]) ExtractE0Keys

func (m *MonoLink[T0]) ExtractE0Keys() (string, string, error)

ExtractE0Keys extracts the pk and sk values for the 0th entity from the primary composite key.

func (*MonoLink[T0]) GenerateMonoLinkKeys

func (m *MonoLink[T0]) GenerateMonoLinkKeys() (string, string, error)

GenerateMonoLinkKeys generates the composite key for the monolink.

func (*MonoLink[T0]) Keys

func (m *MonoLink[T0]) Keys(gsi int) (string, string, error)

func (*MonoLink[T0]) LoadEntity0

func (m *MonoLink[T0]) LoadEntity0(ctx context.Context) (bool, error)

LoadEntity0 attempts to load the Entity0 from DynamoDB. If the Entity0 field is already populated, it will generate the keys and attempt to load the Entity0 from DynamoDB.

If the Entity0 field is not populated, it will attempt to extract the keys from the Pk and Sk fields and then load the Entity0 from DynamoDB.

type Result

type Result struct {
	Index  int
	Loaded bool
	Error  error
}

type Row

type Row struct {
	// Type string `dynamodbav:"type,omitempty" json:"type,omitempty"`
	Pk  string `dynamodbav:"pk,omitempty" json:"pk,omitempty"`
	Sk  string `dynamodbav:"sk,omitempty" json:"sk,omitempty"`
	Pk1 string `dynamodbav:"pk1,omitempty" json:"pk1,omitempty"`
	Sk1 string `dynamodbav:"sk1,omitempty" json:"sk1,omitempty"`
	Pk2 string `dynamodbav:"pk2,omitempty" json:"pk2,omitempty"`
	Sk2 string `dynamodbav:"sk2,omitempty" json:"sk2,omitempty"`
	Pk3 string `dynamodbav:"pk3,omitempty" json:"pk3,omitempty"`
	Sk3 string `dynamodbav:"sk3,omitempty" json:"sk3,omitempty"`
	Pk4 string `dynamodbav:"pk4,omitempty" json:"pk4,omitempty"`
	Sk4 string `dynamodbav:"sk4,omitempty" json:"sk4,omitempty"`
	Pk5 string `dynamodbav:"pk5,omitempty" json:"pk5,omitempty"`
	Sk5 string `dynamodbav:"sk5,omitempty" json:"sk5,omitempty"`
	Pk6 string `dynamodbav:"pk6,omitempty" json:"pk6,omitempty"`
	Sk6 string `dynamodbav:"sk6,omitempty" json:"sk6,omitempty"`

	// TTL is the UTC time that this record will expire.
	TTL *UnixTime `dynamodbav:"ttl,omitempty" json:"ttl,omitempty"`

	// PkShard is a field that is used
	PkShard string `dynamodbav:"pkshard,omitempty" json:"pkshard,omitempty"`
	// Type is the type of the row.
	UnmarshalledType string `dynamodbav:"type" json:"type,omitempty"`
	DBManager        `dynamodbav:"-" json:"-"`
}

Row is a sample Keyable implementation. It is not intended to be used by itself, but rather to be embedded into other types. After embedding, you should implement the TableName and Keys methods on the parent type.

func (*Row) Keys

func (r *Row) Keys(gsi int) (string, string, error)

func (*Row) MaxShard

func (r *Row) MaxShard() int

func (*Row) SetTTL

func (r *Row) SetTTL(t time.Time) *UnixTime

func (*Row) Type

func (r *Row) Type() string

Type returns the type of the record.

type TriLink[T0, T1, T2 types.Linkable] struct {
	DiLink[T0, T1] // Embedding the DiLink type for DynamoDB requirements

	E2pk string `dynamodbav:"e2pk" json:"e1pk,omitempty"`
	E2sk string `dynamodbav:"e2sk" json:"e1sk,omitempty"`

	Entity2 T2 `dynamodbav:"-" json:"entity1,omitempty"`
}

TriLink is a generic type that can link two entities together in dynamo. By Default the TriLink will establish a one-to-one relationship between the two entities using the primary keys. If you need to save or modify fields in the linked record, you will need to override this method.

func NewTriLink[T0, T1, T2 types.Linkable](entity0 T0, entity1 T1, entity2 T2) *TriLink[T0, T1, T2]

NewTriLink creates a new TriLink instance.

func (link *TriLink[T0, T1, T2]) CheckLink(ctx context.Context, linkWrapper types.Linkable, entity0 T0, entity1 T1, entity2 T2) (linkExists bool, err error)

CheckLink accepts all entities and attempts to load the link from dynamo. It does not attempt to load the entities themselves, only the link.

func (*TriLink[T0, T1, T2]) ExtractE2Keys

func (m *TriLink[T0, T1, T2]) ExtractE2Keys() (string, string, error)

func (*TriLink[T0, T1, T2]) GenerateTriLinkCompositeKey

func (m *TriLink[T0, T1, T2]) GenerateTriLinkCompositeKey() (string, string, error)

func (*TriLink[T0, T1, T2]) Keys

func (m *TriLink[T0, T1, T2]) Keys(gsi int) (string, string, error)
func (m *TriLink[T0, T1, T2]) Link(ctx context.Context, row types.Linkable) error

Link is a generic method to establish a connection between the two entities. By default it will establish a one-to-one relationship between the two entities using the primary keys. If the relation is set to OneToMany, then it will establish a one-to-many relationship between the two entities where Entity0 is the "one" and Entity1 is the "many".

func (*TriLink[T0, T1, T2]) LoadEntities

func (m *TriLink[T0, T1, T2]) LoadEntities(ctx context.Context) (e0Loaded, e1Loaded, e2Loaded bool, err error)

func (*TriLink[T0, T1, T2]) LoadEntity2

func (m *TriLink[T0, T1, T2]) LoadEntity2(ctx context.Context) (bool, error)

func (*TriLink[T0, T1, T2]) Type

func (r *TriLink[T0, T1, T2]) Type() string

Type returns the type of the record.

func (m *TriLink[T0, T1, T2]) Unlink(ctx context.Context, row types.Linkable) error

Unlink method to remove the connection between the two entities.

type UnixTime

type UnixTime struct {
	time.Time
}

UnixTime represents a Unix timestamp in seconds.

func (UnixTime) Add

func (t UnixTime) Add(duration time.Duration) UnixTime

AddTTL adds a duration to the UnixTime value. Negative durations are allowed, and will subtract from the UnixTime value.

func (UnixTime) MarshalDynamoDBAttributeValue

func (t UnixTime) MarshalDynamoDBAttributeValue() (types.AttributeValue, error)

MarshalDynamoDBAttributeValue implements the dynamodbattribute.Marshaler interface.

func (UnixTime) MarshalJSON

func (t UnixTime) MarshalJSON() ([]byte, error)

MarshalJSON converts UnixTime to a JSON representation.

func (*UnixTime) UnmarshalDynamoDBAttributeValue

func (t *UnixTime) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error

UnmarshalDynamoDBAttributeValue implements the dynamodbattribute.Unmarshaler interface.

func (*UnixTime) UnmarshalJSON

func (t *UnixTime) UnmarshalJSON(data []byte) error

UnmarshalJSON converts a JSON representation to UnixTime.

func (*UnixTime) UpdateTTL

func (t *UnixTime) UpdateTTL(newTime time.Time)

UpdateTTL updates the UnixTime value to the given time.

Jump to

Keyboard shortcuts

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