DCB Interface & Types
This page documents the core types of the dcb package.
Event
The raw unit stored in the event log.
type Event struct {
Type string // Event type name (e.g. "UserCreated")
Tags []string // Tags for scoping and filtering (AND semantics within a query)
Data []byte // JSON-encoded payload
}
Typeidentifies the event kind. It is used to route reads to the correct type index.Tagsattach entity-scoped labels (e.g."list:my-list","user:42"). Tags are sorted alphabetically at write time for consistent indexing.Datais an opaque JSON blob. At the framework layer, this contains the serializedfairway.Eventenvelope (timestamp + user data).
Note
dcb.Event is the low-level representation. At the framework layer, you work with fairway.Event instead, which wraps a user-defined struct and a timestamp.
Versionstamp
A globally unique, monotonically increasing identifier assigned by FoundationDB at commit time.
- Bytes 0–9: 10-byte FDB transaction version (assigned by FDB, globally ordered)
- Bytes 10–11: 2-byte user version (sequence number within a transaction, 0–65535)
Together they form a 12-byte value that is:
- Globally unique across all transactions
- Monotonically increasing — later commits always have larger versionstamps
- Stable — once assigned, never changes
Methods
// Compare returns -1, 0, or +1
func (v Versionstamp) Compare(other Versionstamp) int
// String returns the hex representation
func (v Versionstamp) String() string
StoredEvent
An event as it exists in the store, enriched with its assigned position.
Position is the versionstamp assigned at commit time. Events are always yielded in Position order by Read and ReadAll.
AppendCondition
Controls whether an Append is allowed to proceed.
type AppendCondition struct {
Query Query
After *Versionstamp // Optional: only check events strictly AFTER this position
}
The condition is satisfied — and the append proceeds — only if no events matching Query exist after position After.
- If
Afterisnil, the condition checks the entire event history. - If events matching the query exist after the given versionstamp,
AppendreturnsErrAppendConditionFailed.
This is the DCB optimistic lock: the command declares "I read up to position X, and my decision is only valid if no relevant events have been written since."
How the condition maps to a command lifecycle
- Command calls
ReadEvents(query, handler)— tracks last seen versionstamp. - Command calls
AppendEvents(event)— internally buildsAppendCondition{Query: query, After: lastSeen}. - If another writer appended a matching event between step 1 and step 2,
Appendfails withErrAppendConditionFailed. - The
CommandRunnerretries the entire command from step 1.
ReadOptions
type ReadOptions struct {
Limit int // Maximum events to return (0 = unlimited)
After *Versionstamp // Only return events strictly after this position
}
Used with DcbStore.Read to paginate or resume reading from a known position.
Query and QueryItem
type QueryItem struct {
Types []string // OR: match any of these types
Tags []string // AND: must have all these tags
}
type Query struct {
Items []QueryItem // OR: match any item
}
| Scope | Operator |
|---|---|
| Types within item | OR |
| Tags within item | AND |
| Items within query | OR |
At least one of Types or Tags must be non-empty per QueryItem.
Constructing the Store
Options are applied via StoreOptions:
opts := dcb.StoreOptions{}
store := dcb.NewDcbStore(db, "myapp",
opts.WithLogger(logger),
opts.WithMetrics(metrics),
)
Observability Interfaces
type Logger interface {
// implementation-defined, used internally
}
type Metrics interface {
// implementation-defined, used internally
}
Both default to no-op implementations when not provided.