data

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2024 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// PathDelim separates key components.
	PathDelim = "/"
	// TypeIDDelim separates the item type from the item ID.
	TypeIDDelim = "-"
)
View Source
const (

	// AppendIDAssignmentSequence will assign the item a monotonically increasing, contiguous ID
	// that is unique *within the parent path and item type*. This is only valid
	// for non-root items and when atomic = true (or within a transaction).
	AppendIDAssignmentSequence

	// AppendIDAssignmentUUID will assign the item a globally unique 128-bit UUID. This will be
	// encoded in the item key path as a binary ID. This is usable anywhere, in
	// any store config.
	AppendIDAssignmentUUID

	// AppendIDAssignmentRand53 will assign the item a random 53-bit numeric ID that
	// is unique *within the parent path and item type*, but is not globally
	// unique. This is usable anywhere, in any store config. We use 53 bits
	// instead of 64 because 53 bits is still a lot of bits, and it's the largest
	// integer that can be represented exactly in JavaScript.
	AppendIDAssignmentRand53
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AllowStale

type AllowStale bool

AllowStale - If true, you're okay with getting a slightly stale item - that is, if you had just changed an item and then call get or list on it, you might get the old version of the item. This can result in improved performance, availability, and cost.

type AppendBatchRequest

type AppendBatchRequest struct {
	// AppendRequests allows you to set
	AppendRequests []*AppendRequest
	// (option) Atomic indicates that all deletes must succeed or none will (i.e. that they
	// are applied in a transaction), and that other operations will be serialized
	// ahead or behind this operation.
	Atomic IsAtomic
	// ParentPath is the path all these items share.
	// Example: [/state-washington/city-seattle]/[person]-<id> the first group is the ParentPath, and the second is the ItemType
	ParentPath string
}

AppendBatchRequest allows you to specify more than 1 item you wish to append to any group.

type AppendBatchResponse

type AppendBatchResponse struct {
	RawItem *RawItem
	Error   error
}

AppendBatchResponse is a tuple of *RawItem[T] OR error. If there's an error, RawItem will be nil with a description of why.

type AppendIDAssignment

type AppendIDAssignment int

AppendIDAssignment specifies the ID assignment strategy when Appending an Item.

func NewAppendIDAssignment

func NewAppendIDAssignment(s string) AppendIDAssignment

NewAppendIDAssignment converts from a name to a AppendIDAssignment type. An invalid value will return 0.

type AppendRequest

type AppendRequest struct {
	// ItemType "is the item path without the "id" part because we're appending it.
	// Example: "person-<id>" you would omit the "-<id>" for "person"
	ItemType string
	// You JSON or proto data to append.
	Data any
	// IDAssignment allows per item append id assignment. Read AppendIDAssignment for more choices.
	IDAssignment AppendIDAssignment
}

AppendRequest allows you to set the appendID strategy per item.

type Changed

type Changed struct {
	Item *RawItem
}

Changed is a SyncResponse that indicates that the item was changed.

func (*Changed) IsSyncResponse

func (r *Changed) IsSyncResponse()

IsSyncResponse is a marker method to indicate that a type is a SyncResponse.

type Client

type Client interface {
	// GetBatch retrieves one or more Items by their full key paths. This will return any
	// of the Items that exist. It will fail if not all of the GetItem requests are
	// under the same root item path, or if the caller does not have permission to
	// read Items. Use Query if you want to retrieve multiple items but don't
	// already know the full key paths of the items you want to get.
	GetBatch(ctx context.Context, request GetRequest) ([]*RawItem, error)

	// Get retrieves one Item by their full key paths. It will fail if the caller does
	// not have permission to read Items. Use Query if you want to retrieve multiple
	// items but don't already know the full key paths of the items you want to get.
	// Use GetBatch if you want to retrieve multiple items by their full key paths.
	Get(ctx context.Context, itemPath string, options ...GetOptions) (*RawItem, error)

	// PutBatch adds one or more Items to the Store, or replaces the Items if they
	// already exist at that path.
	//
	// This will fail if
	//   - not all the PutData requests are under the same root item path.
	//   - any of the PutData requests' write conditions fails.
	//   - the caller does not have permission to create Items.
	//
	// Additional Notes:
	// All puts in the request are applied atomically - there are no partial
	// successes. Data can be provided as either JSON, or as a proto encoded by a
	// previously agreed upon schema, or by some combination of the two.
	PutBatch(ctx context.Context, request PutBatchRequest) ([]*PutBatchResponse, error)

	// Put adds one Item to the Store, or replaces the Item if it
	// already exists at that path.
	//
	// This will fail if:
	//   - The caller does not have permission to create Items.
	//
	// Additional Notes:
	// The PutData is applied atomically - there are no partial
	// successes. Data can be provided as a struct that can be
	// marshalled/unmarshalled as JSON, or a struct that can be
	// serialized/deserialized as a proto.
	Put(ctx context.Context, path string, value any) (*RawItem, error)

	// AppendBatch adds one or more new Items to a parent path, automatically assigning
	// IDs via one of several selectable ID generation strategies (not all
	// strategies may be available to all store configurations or path types).
	// The new item is guaranteed not to overwrite an existing Item because the ID
	// is generated by the server. This differs from Put specifically because
	// of this ID assignment behavior, and it is recommended over Put for new
	// items where you do not want to assign IDs yourself. The assigned IDs will
	// be returned in the response. This operation will fail if the caller does
	// not have permission to create Items.
	AppendBatch(ctx context.Context, request AppendBatchRequest) ([]*AppendBatchResponse, error)

	// Append one new Items to a parent path, automatically assigning
	// an ID via one of several selectable ID generation strategies (not all
	// strategies may be available to all store configurations or path types).
	// The new item is guaranteed not to overwrite an existing Item because the ID
	// is generated by the server. This differs from Put specifically because
	// of this ID assignment behavior, and it is recommended over Put for new
	// items where you do not want to assign IDs yourself. The assigned ID will
	// be returned in the response. This operation will fail if the caller does
	// not have permission to create Items.
	Append(
		ctx context.Context,
		parentPath, itemType string,
		idAssignment AppendIDAssignment,
		data any,
	) (*RawItem, error)

	// DeleteBatch removes one or more Items from the Store by their full key paths. This
	// will fail if any Item does not exist, if not all of the DeleteItem requests
	// are under the same root item path, or if the caller does not have permission
	// to delete Items. Tombstones will be left for deleted items for some
	// predetermined time (TBD tombstone behavior). All deletes in the request are
	// applied atomically - there are no partial successes.
	DeleteBatch(ctx context.Context, request DeleteRequest) ([]*DeleteResponse, error)

	// Delete removes one Item from the Store by their full key paths. This
	// will fail if the Item does not exist, or if the caller does not have permission
	// to delete Items. Tombstones will be left for deleted items for some
	// predetermined time (TBD tombstone behavior).
	Delete(ctx context.Context, itemPath string) error

	// BeginList loads Items that start with a specified key path, subject to
	// additional filtering. The prefix must minimally contain a Group Key (an
	// item type and an item ID). BeginList will return an empty result set if
	// there are no items matching that key prefix. A token is returned from this
	// API that you can then pass to ContinueList to expand the result set, or to
	// SyncList to get updates within the result set. This can fail if the caller
	// does not have permission to read Items.
	BeginList(ctx context.Context, keyPath string, opts ...ListOptions) (ListResponse[*RawItem], error)

	// ContinueList takes the token from a BeginList call and returns the next
	// "page" of results based on the original query parameters and pagination
	// options. It has few options because it is a continuation of a previous list
	// operation. It will return a new  token which can be used for another
	// ContinueList call, and so on. The  token is the same one used by SyncList -
	// each time you call either ContinueList or SyncList, you should pass the
	// latest version of the token, and then use the new token from the result in
	// subsequent calls. You may interleave ContinueList and SyncList calls
	// however you like, but it does not make sense to make both calls in
	// parallel. Calls to ContinueList are tied to the authorization of the
	// original BeginList call, so if the original BeginList call was allowed,
	// ContinueList with its token should also be allowed.
	ContinueList(ctx context.Context, token []byte) (ListResponse[*RawItem], error)

	// NewTransaction starts a new transaction on a stream, and calls the handler with a Transaction object.
	// The handler can then interact with the transaction by calling Get, Put, Append, Delete, and List.
	// The transaction is committed when the handler returns, and the results are returned.
	NewTransaction(ctx context.Context, handler TransactionHandler) (*TransactionResults, error)

	// SyncList returns an iterator for a sync operation.
	SyncList(ctx context.Context, token []byte) (ListResponse[SyncResponse], error)
}

Client is a stately data client that interacts with the given store.

func NewClient

func NewClient(appCtx context.Context, storeID client.StoreID, options ...*client.Options) (Client, error)

NewClient creates a new client with the given store and options.

type ContinueOptions

type ContinueOptions struct {
	// SortDirection is the direction to sort by. Default is Forward.
	SortDirection SortDirection
}

ContinueOptions are optional parameters for Continue.

type DeleteRequest

type DeleteRequest struct {
	ItemPaths []string
	// (option) Atomic indicates that all deletes must succeed or none will (i.e. that they
	// are applied in a transaction), and that other operations will be serialized
	// ahead or behind this operation.
	Atomic IsAtomic
}

DeleteRequest one or more items to from the Group.

func NewDeleteRequest

func NewDeleteRequest(itemPaths ...string) DeleteRequest

NewDeleteRequest is a convenience method to construct DeleteRequest with single or more items vs vanilla golang: DeleteRequest{ItemPaths: []KeyPath{}{"/message-1"}}.

type DeleteResponse

type DeleteResponse struct {
	KeyPath string
	Error   error
}

DeleteResponse indicates if a specific KeyPath failed to delete along with an error indicating why.

type Deleted

type Deleted struct {
	KeyPath string
}

Deleted is a SyncResponse that indicates that the item was deleted.

func (*Deleted) IsSyncResponse

func (r *Deleted) IsSyncResponse()

IsSyncResponse is a marker method to indicate that a type is a SyncResponse.

type GetOptions

type GetOptions struct {
	// (option) AllowStale  indicates that you're okay with getting a slightly stale item,
	// that is, if you had just changed an item and then call GetItem, you might
	// get the old version of the item. This can result in improved performance,
	// availability, and cost.
	AllowStale AllowStale
}

GetOptions is a struct that can be passed to Get. Default handling is to not allow stale items.

type GetRequest

type GetRequest struct {
	// ItemPaths is an array of the full path(s) to the item(s).
	ItemPaths []string
	// (option) AllowStale  indicates that you're okay with getting a slightly stale item,
	// that is, if you had just changed an item and then call GetItem, you might
	// get the old version of the item. This can result in improved performance,
	// availability, and cost.
	AllowStale AllowStale
	// (optional) Atomic indicates that all gets in this request should be executed
	// atomically relative to other requests - that is, it will retrieve the items
	// as they were at the same point in time. If this is false (the default),
	// then each get will be executed independently, meaning each get may be
	// interleaved with modifications by other requests.
	Atomic IsAtomic
}

GetRequest will fetch all specified keys and return any found.

func NewGetRequest

func NewGetRequest(itemPaths ...string) GetRequest

NewGetRequest is a convenience method in golang to allow simple construction of GetRequests via NewGetRequest("/message-1") vs GetRequest{ ItemPaths: []KeyPath{}{"/message-1"} }\ You can then additionally set the "AllowStale" or "Atomic" fields.

type IsAtomic

type IsAtomic bool

IsAtomic indicates that all operations must succeed or none will (i.e. that they are applied in a transaction), and that other operations will be serialized ahead or behind this operation.

type Item

type Item[T any] struct {
	*RawItem
	Data T
}

Item represents a parsed RawItem.

func UnmarshalItem

func UnmarshalItem[T any](itemType string, rawItem *RawItem) (*Item[T], error)

UnmarshalItem is a helper function to unmarshal a list of items of a specific type. The type of your object is the string representation of the type, e.g. "user", "todo", etc. Example: /list-todo/task-4 your type is "task".

func UnmarshalItemList

func UnmarshalItemList[T any](itemType string, rawItems ...*RawItem) ([]*Item[T], error)

UnmarshalItemList is a helper function to unmarshal a list of items of a specific type. The type of your object is the string representation of the type, e.g. "user", "todo", etc. Example: /list-todo/task-4 your type is "task". If you want to unmarshal all items, pass "*" as the itemType.

type ItemKey

type ItemKey []*ItemKeyComponent

ItemKey is a complete item key consisting of one (the root) and any more key components. The root component is special as you MUST always specify the `ID` associated with `type` of on the root, while other components only require type. Example: /conversation-foo/message and /conversation-foo/message-1 are valid ItemKey(s), while /conversation is not because it lacks the ID `-foo` of the segment. The key path must be at least 1 element long.

func (ItemKey) KeyPath

func (k ItemKey) KeyPath() string

KeyPath converts an ItemKey structure to a customer-facing string path, e.g. "/users-123/posts-a-fun-recipe". It is assumed that the ItemKey was validated when it was first converted from a string, so no validation is done in this direction.

type ItemKeyComponent

type ItemKeyComponent struct {
	// ItemType identifies the type of this item, which:
	//  1. Associates it with a type in schema (TBD)
	//  2. Determines which version counter / ID sequence to use for these items,
	//     for both ID assignment and change tracking.
	//
	// TODO: In the future we could represent this as an ordinal into a schema,
	// for more compact storage.
	ItemType string

	// ItemID is an optional, unique value that identifies this item among other
	// items of the same item type within its containing item type. The ID may be
	// omitted in cases where the item is a singleton. This ID may be
	// user-provided, or assigned automatically by append.
	//
	// Types that are assignable to ItemId:
	//
	//	*KeyValueUint
	//	*KeyValueString
	//	*KeyValueBinary
	ItemID KeyValue
}

ItemKeyComponent identifies a segment of an ItemKey, representing a tuple of an item type and an optional ID.

func (ItemKeyComponent) String

func (c ItemKeyComponent) String() string

type ItemMetadata

type ItemMetadata struct {
	CreatedAt             time.Time
	LastModifiedAt        time.Time
	CreatedAtVersion      uint64
	LastModifiedAtVersion uint64
}

ItemMetadata describes autopopulated fields about every item in your Stately store. This removes the need to add very common attributes like item creation timestamp or last modified timestamp.

type KeyValue

type KeyValue interface {
	fmt.Stringer
}

KeyValue represents a key in an item path. It can be a uint64, string, or bytes.

type KeyValueBinary

type KeyValueBinary struct {
	// binary_value allows users to supply arbitrary binary value keys, which is
	// good for things like UUIDs.
	Value []byte
}

KeyValueBinary is a byte slice key value.

func (*KeyValueBinary) String

func (kv *KeyValueBinary) String() string

type KeyValueInt

type KeyValueInt struct {
	// Value is the int64 value of the key.
	Value int64
}

KeyValueInt is a int64 key value. This is currently only used for LSIs; it is not a part of primary keys.

func (*KeyValueInt) String

func (kv *KeyValueInt) String() string

type KeyValueString

type KeyValueString struct {
	// string_value allows users to supply arbitrary keys as a string.
	Value string
}

KeyValueString is a string key value.

func (*KeyValueString) String

func (kv *KeyValueString) String() string

type KeyValueUint

type KeyValueUint struct {
	// uint_value is the common case of an unsigned 64-bit integer as an ID.
	// This is a great default for most IDs and is what AppendItem automatically
	// uses when assigning IDs.
	Value uint64
}

KeyValueUint is a uint64 key value.

func (*KeyValueUint) String

func (kv *KeyValueUint) String() string

type ListOptions

type ListOptions struct {
	// Limit is the maximum number of items to return. If 0, the server will default to unlimited.
	Limit uint32
	// SortableProperty is the property to sort by. Default is SortByKeyPath.
	SortableProperty SortableProperty
	// SortDirection is the direction to sort by. Default is Forward.
	SortDirection SortDirection
	// AllowStale indicates that you're okay with getting slightly stale items
	// that is, if you had just changed an item and then call a List operation,
	// you might get the old version of the item. This can result in improved
	// performance, availability, and cost.
	AllowStale AllowStale
}

ListOptions are optional parameters for List.

func (*ListOptions) Merge

func (lo *ListOptions) Merge(other *ListOptions) *ListOptions

Merge combines two ListOptions into one. "other" takes precedence over "this". Nils will overwrite non-nil values.

type ListRequest

type ListRequest struct {
	// KeyPathPrefix must be at least the root component but optionally contain any number of path components to narrow
	// your list result. Example: [/state-washington]/city - the first segment is the root component, this would return
	// all cities in washington. Separately, you could issue a list request with just `/state-washington` which would
	// return the item at "/state-washington"
	KeyPathPrefix string
}

ListRequest starts a list operation.

type ListResponse

type ListResponse[T any] interface {
	// Next reads an item of the stream, and populates Value() with the current item.
	Next() bool
	// Token returns the current token OR any error that occurred during iteration.
	Token() (*ListToken, error)
	// Value returns the current item in the iteration.
	Value() T
}

ListResponse allows you to write idiomatic Go code to iterate over a list of value. for example, to iterate over a list of items:

 for listResponse.Next() {
	 value := listResponse.Value()
	 // do something with item
 }
 err, token := listResponse.Token();
 // handle error and token

type ListToken

type ListToken struct {
	// token will never be nil
	Data []byte
	// can continue indicates if there are more results to fetch using ContinueList
	CanContinue bool
	// can sync indicates that you could call SyncList with this token later to
	// get updated items. This is determined by the type of store you're listing
	// from.
	CanSync bool
}

ListToken is a stateless token that acts like an iterator on a list of results efficiently fetching the next window. To fetch additional results, use the "next" token produced by Continue.

type PutBatchRequest

type PutBatchRequest struct {
	PutData []*PutData
	// (option) Atomic indicates that all puts must succeed or none will (i.e. that they
	// are applied in a transaction), and that other operations will be serialized
	// ahead or behind this operation.
	Atomic IsAtomic
}

PutBatchRequest allows you to specify items to put either atomically or non-atomic. Atomic operations are more expensive in terms of io/latency/cost.

func NewPutBatchRequest

func NewPutBatchRequest[T any](putRequests ...*PutData) PutBatchRequest

NewPutBatchRequest is a convenience method to generate a new PutBatchRequest.

type PutBatchResponse

type PutBatchResponse struct {
	*RawItem
	Error error
}

PutBatchResponse is a simple tuple of either RawItem or Error.

type PutData

type PutData struct {
	KeyPath string
	Data    any
}

PutData allows you to fill in any type of data at a desired KeyPath.

type RawItem

type RawItem struct {
	Key           ItemKey
	ItemType      string
	ParentKeyPath ItemKey
	JSONData      json.RawMessage
	ID            KeyValue
	Metadata      ItemMetadata
}

RawItem represents an Item in StatelyDB.

func (*RawItem) KeyPath

func (i *RawItem) KeyPath() string

KeyPath is a convenience function.

type Reset

type Reset struct{}

Reset is a SyncResponse that indicates that the sync operation should be reset.

func (*Reset) IsSyncResponse

func (r *Reset) IsSyncResponse()

IsSyncResponse is a marker method to indicate that a type is a SyncResponse.

type SortDirection

type SortDirection int

SortDirection is the direction to sort by.

const (
	// Forward is the default sort direction.
	Forward SortDirection = iota
	// Backward is the reverse sort direction.
	Backward
)

type SortableProperty

type SortableProperty int

SortableProperty is the property to sort by.

const (
	// SortByKeyPath sorts by the key path.
	SortByKeyPath SortableProperty = iota
	// SortByLastModifiedVersion sorts by the last time the item was modified.
	SortByLastModifiedVersion
)

type SyncResponse

type SyncResponse interface {
	// IsSyncResponse is a marker method to indicate that a type is a SyncResponse.
	IsSyncResponse()
}

SyncResponse is a response from a sync operation.

type Transaction

type Transaction interface {
	// Get one RawItem by its full key path.
	Get(item string) (*RawItem, error)

	// GetBatch one or more Items by their full key paths.
	GetBatch(items ...string) ([]*RawItem, error)

	// Put is a convenience method for adding a single Item to the Store, or replacing the RawItem if it exists at that path.
	Put(keyPath string, data any) error

	// PutBatch adds one or more Items to the Store, or replaces the Items if they exist at that path.
	// The metadata (create time/version + modified time/version)  for each PutData is returned only at the end of the transaction.
	PutBatch(items ...*PutData) error

	// Append adds one Item to a parent path, automatically assigning an ID.
	Append(prefix, itemType string, data any, idAssignment AppendIDAssignment) (string, error)

	// AppendBatch adds one or more new Items to a parent path, automatically assigning IDs.
	// The metadata (create time/version + modified time/version) for each AppendRequest is returned only at the end of the transaction.
	AppendBatch(prefix string, items ...*AppendRequest) ([]string, error)

	// Delete removes one or more Items from the Store by their full key paths.
	Delete(items ...string) error

	// BeginList loads Items that start with a specified key path, subject to additional filtering.
	// The returned ListResponse can be used to iterate over the stream of results for example:
	//	iter, err := txn.BeginList("/path/to/items")
	//	// handle err
	//	for iter.Continue() {
	//		item := iter.Item()
	//		// do something with item
	//	}
	//	err, token := iter.Token();
	//	// handle err and token
	BeginList(prefix string, options ...*ListOptions) (ListResponse[*RawItem], error)

	// ContinueList picks back up where this token left off. As with BeginList, you use the ListResponse to iterate over
	// the stream of results.
	ContinueList(token *ListToken) (ListResponse[*RawItem], error)
}

Transaction represents a single transaction.

type TransactionHandler

type TransactionHandler func(Transaction) error

TransactionHandler operates on a single transaction.

The Transaction argument is passed to the handler function to allow the handler to interact with the transaction. This handler is not thread safe and should not be shared between goroutines. Additionally, do not share state outside the transaction handler. e.g. don't use a closure that captures variables from the outer scope.

If you wish to cancel/abort the transaction, simply return an error from the handler and we'll take care of cleaning up the transaction.

type TransactionResults

type TransactionResults struct {
	// PutResponse contains the full result of each Put operation. This only comes
	// back with the transaction is finished message because full metadata isn't
	// available until then.
	PutResponse []*PutBatchResponse

	// AppendResponse contains the full result of each Append operation. This only
	// comes back with the TransactionFinished message because full metadata isn't
	// available until then.
	AppendResponse []*AppendBatchResponse

	// DeleteResponse contains the full result of each Delete operation. This only
	// comes back with the TransactionFinished message because full metadata isn't
	// available until then.
	DeleteResponse []*DeleteResponse

	// Did the commit finish (the alternative is that it was aborted/rolled back)
	Committed bool
}

TransactionResults holds all the results of a transaction after a commit.

type UpdateOutsideOfWindow

type UpdateOutsideOfWindow struct {
	KeyPath string
}

UpdateOutsideOfWindow is a SyncResponse that indicates that the item was updated outside of the window.

func (*UpdateOutsideOfWindow) IsSyncResponse

func (r *UpdateOutsideOfWindow) IsSyncResponse()

IsSyncResponse is a marker method to indicate that a type is a SyncResponse.

Jump to

Keyboard shortcuts

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