database

package
v0.11.4 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2021 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// HashMismatch sentinel error
	HashMismatch = i18n.NewError(context.Background(), i18n.MsgHashMismatch)
	// IDMismatch sentinel error
	IDMismatch = i18n.NewError(context.Background(), i18n.MsgIDMismatch)
	// DeleteRecordNotFound sentinel error
	DeleteRecordNotFound = i18n.NewError(context.Background(), i18n.Msg404NotFound)
)
View Source
var BatchQueryFactory = &queryFields{
	"id":         &UUIDField{},
	"namespace":  &StringField{},
	"type":       &StringField{},
	"author":     &StringField{},
	"key":        &StringField{},
	"group":      &Bytes32Field{},
	"hash":       &Bytes32Field{},
	"payloadref": &StringField{},
	"created":    &TimeField{},
	"confirmed":  &TimeField{},
	"tx.type":    &StringField{},
	"tx.id":      &UUIDField{},
	"node":       &UUIDField{},
}

BatchQueryFactory filter fields for batches

View Source
var BlobQueryFactory = &queryFields{
	"hash":       &Bytes32Field{},
	"payloadref": &StringField{},
	"created":    &TimeField{},
}

BlobQueryFactory filter fields for config records

View Source
var ConfigRecordQueryFactory = &queryFields{
	"key":   &StringField{},
	"value": &StringField{},
}

ConfigRecordQueryFactory filter fields for config records

View Source
var DataQueryFactory = &queryFields{
	"id":               &UUIDField{},
	"namespace":        &StringField{},
	"validator":        &StringField{},
	"datatype.name":    &StringField{},
	"datatype.version": &StringField{},
	"hash":             &Bytes32Field{},
	"blob.hash":        &Bytes32Field{},
	"blob.public":      &StringField{},
	"created":          &TimeField{},
}

DataQueryFactory filter fields for data

View Source
var DatatypeQueryFactory = &queryFields{
	"id":        &UUIDField{},
	"message":   &UUIDField{},
	"namespace": &StringField{},
	"validator": &StringField{},
	"name":      &StringField{},
	"version":   &StringField{},
	"created":   &TimeField{},
}

DatatypeQueryFactory filter fields for data definitions

View Source
var EventQueryFactory = &queryFields{
	"id":        &UUIDField{},
	"type":      &StringField{},
	"namespace": &StringField{},
	"reference": &UUIDField{},
	"group":     &Bytes32Field{},
	"sequence":  &Int64Field{},
	"created":   &TimeField{},
}

EventQueryFactory filter fields for data events

View Source
var GroupQueryFactory = &queryFields{
	"hash":        &Bytes32Field{},
	"message":     &UUIDField{},
	"namespace":   &StringField{},
	"description": &StringField{},
	"ledger":      &UUIDField{},
	"created":     &TimeField{},
}

GroupQueryFactory filter fields for nodes

View Source
var MessageQueryFactory = &queryFields{
	"id":        &UUIDField{},
	"cid":       &UUIDField{},
	"namespace": &StringField{},
	"type":      &StringField{},
	"author":    &StringField{},
	"key":       &StringField{},
	"topics":    &FFNameArrayField{},
	"tag":       &StringField{},
	"group":     &Bytes32Field{},
	"created":   &TimeField{},
	"hash":      &Bytes32Field{},
	"pins":      &FFNameArrayField{},
	"state":     &StringField{},
	"confirmed": &TimeField{},
	"sequence":  &Int64Field{},
	"txtype":    &StringField{},
	"batch":     &UUIDField{},
}

MessageQueryFactory filter fields for messages

View Source
var NamespaceQueryFactory = &queryFields{
	"id":          &UUIDField{},
	"message":     &UUIDField{},
	"type":        &StringField{},
	"name":        &StringField{},
	"description": &StringField{},
	"created":     &TimeField{},
	"confirmed":   &TimeField{},
}

NamespaceQueryFactory filter fields for namespaces

View Source
var NextPinQueryFactory = &queryFields{
	"context":  &Bytes32Field{},
	"identity": &StringField{},
	"hash":     &Bytes32Field{},
	"nonce":    &Int64Field{},
}

NextPinQueryFactory filter fields for nodes

View Source
var NodeQueryFactory = &queryFields{
	"id":          &UUIDField{},
	"message":     &UUIDField{},
	"owner":       &StringField{},
	"name":        &StringField{},
	"description": &StringField{},
	"dx.peer":     &StringField{},
	"dx.endpoint": &JSONField{},
	"created":     &TimeField{},
}

NodeQueryFactory filter fields for nodes

View Source
var NonceQueryFactory = &queryFields{
	"context": &StringField{},
	"nonce":   &Int64Field{},
	"group":   &Bytes32Field{},
	"topic":   &StringField{},
}

NonceQueryFactory filter fields for nodes

View Source
var OffsetQueryFactory = &queryFields{
	"name":    &StringField{},
	"type":    &StringField{},
	"current": &Int64Field{},
}

OffsetQueryFactory filter fields for data offsets

View Source
var OperationQueryFactory = &queryFields{
	"id":        &UUIDField{},
	"tx":        &UUIDField{},
	"type":      &StringField{},
	"namespace": &StringField{},
	"status":    &StringField{},
	"error":     &StringField{},
	"plugin":    &StringField{},
	"input":     &JSONField{},
	"output":    &JSONField{},
	"backendid": &StringField{},
	"created":   &TimeField{},
	"updated":   &TimeField{},
}

OperationQueryFactory filter fields for data operations

View Source
var OrganizationQueryFactory = &queryFields{
	"id":          &UUIDField{},
	"message":     &UUIDField{},
	"parent":      &StringField{},
	"identity":    &StringField{},
	"description": &StringField{},
	"profile":     &JSONField{},
	"created":     &TimeField{},
}

OrganizationQueryFactory filter fields for organizations

View Source
var PinQueryFactory = &queryFields{
	"sequence":   &Int64Field{},
	"masked":     &BoolField{},
	"hash":       &Bytes32Field{},
	"batch":      &UUIDField{},
	"index":      &Int64Field{},
	"dispatched": &BoolField{},
	"created":    &TimeField{},
}

PinQueryFactory filter fields for parked contexts

View Source
var SubscriptionQueryFactory = &queryFields{
	"id":            &UUIDField{},
	"namespace":     &StringField{},
	"name":          &StringField{},
	"transport":     &StringField{},
	"events":        &StringField{},
	"filter.topics": &StringField{},
	"filter.tag":    &StringField{},
	"filter.group":  &StringField{},
	"options":       &StringField{},
	"created":       &TimeField{},
}

SubscriptionQueryFactory filter fields for data subscriptions

View Source
var TokenBalanceQueryFactory = &queryFields{
	"pool":       &UUIDField{},
	"tokenindex": &StringField{},
	"uri":        &StringField{},
	"connector":  &StringField{},
	"namespace":  &StringField{},
	"key":        &StringField{},
	"balance":    &Int64Field{},
	"updated":    &TimeField{},
}

TokenBalanceQueryFactory filter fields for token accounts

View Source
var TokenPoolQueryFactory = &queryFields{
	"id":         &UUIDField{},
	"type":       &StringField{},
	"namespace":  &StringField{},
	"name":       &StringField{},
	"standard":   &StringField{},
	"protocolid": &StringField{},
	"key":        &StringField{},
	"symbol":     &StringField{},
	"message":    &UUIDField{},
	"state":      &StringField{},
	"created":    &TimeField{},
	"connector":  &StringField{},
}

TokenPoolQueryFactory filter fields for token pools

View Source
var TokenTransferQueryFactory = &queryFields{
	"localid":     &StringField{},
	"pool":        &UUIDField{},
	"tokenindex":  &StringField{},
	"uri":         &StringField{},
	"connector":   &StringField{},
	"namespace":   &StringField{},
	"key":         &StringField{},
	"from":        &StringField{},
	"to":          &StringField{},
	"amount":      &Int64Field{},
	"protocolid":  &StringField{},
	"message":     &UUIDField{},
	"messagehash": &Bytes32Field{},
	"created":     &TimeField{},
}

TokenTransferQueryFactory filter fields for token transfers

View Source
var TransactionQueryFactory = &queryFields{
	"id":         &UUIDField{},
	"type":       &StringField{},
	"signer":     &StringField{},
	"status":     &StringField{},
	"reference":  &UUIDField{},
	"protocolid": &StringField{},
	"created":    &TimeField{},
	"sequence":   &Int64Field{},
	"info":       &JSONField{},
	"namespace":  &StringField{},
}

TransactionQueryFactory filter fields for transactions

Functions

This section is empty.

Types

type AndFilter

type AndFilter interface{ MultiConditionFilter }

type BoolField

type BoolField struct{}

type Bytes32Field

type Bytes32Field struct{}

type Callbacks

type Callbacks interface {
	// OrderedUUIDCollectionNSEvent emits the sequence on insert, but it will be -1 on update
	OrderedUUIDCollectionNSEvent(resType OrderedUUIDCollectionNS, eventType fftypes.ChangeEventType, ns string, id *fftypes.UUID, sequence int64)
	OrderedCollectionEvent(resType OrderedCollection, eventType fftypes.ChangeEventType, sequence int64)
	UUIDCollectionNSEvent(resType UUIDCollectionNS, eventType fftypes.ChangeEventType, ns string, id *fftypes.UUID)
	UUIDCollectionEvent(resType UUIDCollection, eventType fftypes.ChangeEventType, id *fftypes.UUID)
	HashCollectionNSEvent(resType HashCollectionNS, eventType fftypes.ChangeEventType, ns string, hash *fftypes.Bytes32)
}

Callbacks are the methods for passing data from plugin to core

If Capabilities returns ClusterEvents=true then these should be broadcast to every instance within a cluster that is connected to the database.

If Capabilities returns ClusterEvents=false then these events can be simply coupled in-process to update activities.

The system does not rely on these events exclusively for data/transaction integrity, but if an event is missed/delayed it might result in slower processing. For example, the batch interface will initiate a batch as soon as an event is triggered, but it will use a subsequent database query as the source of truth of the latest set/order of data, and it will periodically check for new messages even if it does not receive any events.

Events are emitted locally to the individual FireFly core process. However, a WebSocket interface is available for remote listening to these events. That allows the UI to listen to the events, as well as providing a building block for a cluster of FireFly servers to directly propgate events to each other.

type Capabilities

type Capabilities struct {
	ClusterEvents bool
}

Capabilities defines the capabilities a plugin can report as implementing or not

type CollectionName

type CollectionName string

CollectionName represents all collections

type FFNameArrayField

type FFNameArrayField struct{}

type Field

type Field interface {
	// contains filtered or unexported methods
}

type FieldSerialization

type FieldSerialization interface {
	driver.Valuer
	sql.Scanner // Implementations can assume the value is ALWAYS a string
}

FieldSerialization - we stand on the shoulders of the well adopted SQL serialization interface here to help us define what string<->value looks like, even though this plugin interface is not tightly coupled to SQL.

type Filter

type Filter interface {
	// Sort adds a set of sort conditions (all in a single sort order)
	Sort(...string) Filter

	// Ascending sort order
	Ascending() Filter

	// Descending sort order
	Descending() Filter

	// Skip for pagination
	Skip(uint64) Filter

	// Limit for pagination
	Limit(uint64) Filter

	// Request a count to be returned on the total number that match the query
	Count(c bool) Filter

	// Finalize completes the filter, and for the plugin to validated output structure to convert
	Finalize() (*FilterInfo, error)

	// Builder returns the builder that made it
	Builder() FilterBuilder
}

Filter is the output of the builder

type FilterBuilder

type FilterBuilder interface {
	// Fields is the list of available fields
	Fields() []string
	// And requires all sub-filters to match
	And(and ...Filter) AndFilter
	// Or requires any of the sub-filters to match
	Or(and ...Filter) OrFilter
	// Eq equal
	Eq(name string, value driver.Value) Filter
	// Neq not equal
	Neq(name string, value driver.Value) Filter
	// In one of an array of values
	In(name string, value []driver.Value) Filter
	// NotIn not one of an array of values
	NotIn(name string, value []driver.Value) Filter
	// Lt less than
	Lt(name string, value driver.Value) Filter
	// Gt greater than
	Gt(name string, value driver.Value) Filter
	// Gte greater than or equal
	Gte(name string, value driver.Value) Filter
	// Lte less than or equal
	Lte(name string, value driver.Value) Filter
	// Contains allows the string anywhere - case sensitive
	Contains(name string, value driver.Value) Filter
	// NotContains disallows the string anywhere - case sensitive
	NotContains(name string, value driver.Value) Filter
	// IContains allows the string anywhere - case sensitive
	IContains(name string, value driver.Value) Filter
	// INotContains disallows the string anywhere - case sensitive
	NotIContains(name string, value driver.Value) Filter
}

FilterBuilder is the syntax used to build the filter, where And() and Or() can be nested

type FilterInfo

type FilterInfo struct {
	Sort      []*SortField
	Skip      uint64
	Limit     uint64
	Count     bool
	CountExpr string
	Field     string
	Op        FilterOp
	Values    []FieldSerialization
	Value     FieldSerialization
	Children  []*FilterInfo
}

FilterInfo is the structure returned by Finalize to the plugin, to serialize this filter into the underlying database mechanism's filter language

func (*FilterInfo) String

func (f *FilterInfo) String() string

type FilterOp

type FilterOp string

FilterOp enum of filter operations that must be implemented by plugins - the string value is used in the core string formatting method (for logging etc.)

const (
	// FilterOpAnd and
	FilterOpAnd FilterOp = "&&"
	// FilterOpOr or
	FilterOpOr FilterOp = "||"
	// FilterOpEq equal
	FilterOpEq FilterOp = "=="
	// FilterOpNe not equal
	FilterOpNe FilterOp = "!="
	// FilterOpIn in list of values
	FilterOpIn FilterOp = "IN"
	// FilterOpNotIn not in list of values
	FilterOpNotIn FilterOp = "NI"
	// FilterOpGt greater than
	FilterOpGt FilterOp = ">"
	// FilterOpLt less than
	FilterOpLt FilterOp = "<"
	// FilterOpGte greater than or equal
	FilterOpGte FilterOp = ">="
	// FilterOpLte less than or equal
	FilterOpLte FilterOp = "<="
	// FilterOpCont contains the specified text, case sensitive
	FilterOpCont FilterOp = "%="
	// FilterOpNotCont does not contain the specified text, case sensitive
	FilterOpNotCont FilterOp = "%!"
	// FilterOpICont contains the specified text, case insensitive
	FilterOpICont FilterOp = "^="
	// FilterOpNotICont does not contain the specified text, case insensitive
	FilterOpNotICont FilterOp = "^!"
)

type FilterResult

type FilterResult struct {
	TotalCount *int64
}

FilterResult is has additional info if requested on the query - currently only the total count

type HashCollectionNS

type HashCollectionNS CollectionName

HashCollectionNS is a collection where the primary key is a hash, such that it can by identifed by any member of the network at any time, without it first having been broadcast.

const (
	CollectionGroups HashCollectionNS = "groups"
)

type Int64Field

type Int64Field struct{}

type JSONField

type JSONField struct{}

type MultiConditionFilter

type MultiConditionFilter interface {
	Filter
	// Add adds filters to the condition
	Condition(...Filter) MultiConditionFilter
}

MultiConditionFilter gives convenience methods to add conditions

type NullBehavior added in v0.11.0

type NullBehavior int

NullBehavior specifies whether to sort nulls first or last in a query

const (
	NullsDefault NullBehavior = iota
	NullsFirst
	NullsLast
)

type OrFilter

type OrFilter interface{ MultiConditionFilter }

type OrderedCollection

type OrderedCollection CollectionName

OrderedCollection is a collection that is ordered, and that sequence is the only key

const (
	CollectionPins OrderedCollection = "pins"
)

type OrderedUUIDCollectionNS

type OrderedUUIDCollectionNS CollectionName

OrderedUUIDCollectionNS collections have a strong order that includes a sequence integer that uniquely identifies the entry in a sequence. The sequence is LOCAL to this FireFly node. We try to minimize adding new collections of this type, as they have implementation complexity in some databases (such as NoSQL databases)

const (
	CollectionMessages OrderedUUIDCollectionNS = "messages"
	CollectionEvents   OrderedUUIDCollectionNS = "events"
)

type OtherCollection

type OtherCollection CollectionName

OtherCollection are odd balls, that don't fit any of the categories above. These collections do not support change events, and generally their creation is coordinated with creation of another object that does support change events. Mainly they are entries that require lookup by compound IDs.

const (
	CollectionConfigrecords OtherCollection = "configrecords"
	CollectionBlobs         OtherCollection = "blobs"
	CollectionNextpins      OtherCollection = "nextpins"
	CollectionNonces        OtherCollection = "nonces"
	CollectionOffsets       OtherCollection = "offsets"
	CollectionTokenBalances OtherCollection = "tokenbalances"
)

type PeristenceInterface

type PeristenceInterface interface {
	fftypes.Named

	// RunAsGroup instructs the database plugin that all database operations performed within the context
	// function can be grouped into a single transaction (if supported).
	// Requirements:
	// - Firefly must not depend on this to guarantee ACID properties (it is only a suggestion/optimization)
	// - The database implementation must support nested RunAsGroup calls (ie by reusing a transaction if one exists)
	// - The caller is responsible for passing the supplied context to all database operations within the callback function
	RunAsGroup(ctx context.Context, fn func(ctx context.Context) error) error
	// contains filtered or unexported methods
}

PeristenceInterface are the operations that must be implemented by a database interfavce plugin. The database mechanism of Firefly is designed to provide the balance between being able to query the data a member of the network has transferred/received via Firefly efficiently, while not trying to become the core database of the application (where full deeply nested rich query is needed).

This means that we treat business data as opaque within the stroage, only verifying it against a data definition within the Firefly core runtime itself. The data types, indexes and relationships are designed to be simple, and map closely to the REST semantics of the Firefly API itself.

As a result, the database interface could be implemented efficiently by most database technologies. Including both Relational/SQL and Document/NoSQL database technologies.

As such we suggest the factors in choosing your database should be non-functional, such as: - Which provides you with the HA/DR capabilities you require - Which is most familiar within your existing devops pipeline for the application - Whether you can consolidate the HA/DR and server infrastructure for your app DB with the Firefly DB

Each database does need an update to the core codebase, to provide a plugin that implements this interface. For SQL databases the process of adding a new database is simplified via the common SQL layer. For NoSQL databases, the code should be straight forward to map the collections, indexes, and operations.

type Plugin

type Plugin interface {
	PeristenceInterface // Split out to aid pluggability the next level down (SQL provider etc.)

	// InitPrefix initializes the set of configuration options that are valid, with defaults. Called on all plugins.
	InitPrefix(prefix config.Prefix)

	// Init initializes the plugin, with configuration
	// Returns the supported featureset of the interface
	Init(ctx context.Context, prefix config.Prefix, callbacks Callbacks) error

	// Capabilities returns capabilities - not called until after Init
	Capabilities() *Capabilities
}

Plugin is the interface implemented by each plugin

type QueryFactory

type QueryFactory interface {
	NewFilter(ctx context.Context) FilterBuilder
	NewFilterLimit(ctx context.Context, defLimit uint64) FilterBuilder
	NewUpdate(ctx context.Context) UpdateBuilder
}

QueryFactory creates a filter builder in the given context, and contains the rules on which fields can be used by the builder (and how they are serialized)

type SetOperation

type SetOperation struct {
	Field string
	Value FieldSerialization
}

SetOperation is an individual update action to perform

type SortField

type SortField struct {
	Field      string
	Descending bool
	Nulls      NullBehavior
}

SortField is field+direction for sorting

type StringField

type StringField struct{}

type TimeField

type TimeField struct{}

type UUIDCollection

type UUIDCollection CollectionName

UUIDCollection is like UUIDCollectionNS, but for objects that do not reside within a namespace

const (
	CollectionNamespaces     UUIDCollection = "namespaces"
	CollectionNodes          UUIDCollection = "nodes"
	CollectionOrganizations  UUIDCollection = "organizations"
	CollectionTokenTransfers UUIDCollection = "tokentransfers"
)

type UUIDCollectionNS

type UUIDCollectionNS CollectionName

UUIDCollectionNS is the most common type of collection - each entry has a UUID that is globally unique, and used externally by apps to address entries in the collection. Objects in these collections are all namespaced,.

const (
	CollectionBatches       UUIDCollectionNS = "batches"
	CollectionData          UUIDCollectionNS = "data"
	CollectionDataTypes     UUIDCollectionNS = "datatypes"
	CollectionOperations    UUIDCollectionNS = "operations"
	CollectionSubscriptions UUIDCollectionNS = "subscriptions"
	CollectionTransactions  UUIDCollectionNS = "transactions"
	CollectionTokenPools    UUIDCollectionNS = "tokenpools"
)

type UUIDField

type UUIDField struct{}

type Update

type Update interface {
	// Set adds a set condition to the update
	Set(field string, value interface{}) Update

	// IsEmpty
	IsEmpty() bool

	// Finalize completes the update, and for the plugin to validated output structure to convert
	Finalize() (*UpdateInfo, error)
}

type UpdateBuilder

type UpdateBuilder interface {
	// Set starts creation of a set operation
	Set(field string, value interface{}) Update

	// S starts an update that doesn't have any fields
	S() Update

	// Fields returns the available fields on the update
	Fields() []string
}

UpdateBuilder is the output of the builder

type UpdateFactory

type UpdateFactory interface {
	New(ctx context.Context) UpdateBuilder
}

UpdateFactory creates a update builder in the given context, and contains the rules on which fields can be used by the builder (and how they are serialized)

type UpdateInfo

type UpdateInfo struct {
	SetOperations []*SetOperation
}

UpdateInfo is the structure returned by Finalize to the plugin, to serialize this uilter into the underlying database mechanism's uilter language

func (*UpdateInfo) String

func (u *UpdateInfo) String() string

type UpsertOptimization added in v0.11.0

type UpsertOptimization int
const (
	UpsertOptimizationSkip UpsertOptimization = iota
	UpsertOptimizationNew
	UpsertOptimizationExisting
)

Jump to

Keyboard shortcuts

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