Documentation
¶
Overview ¶
Package storage defines five neutral storage primitives — Ledger (an append-only, CAS-sequenced record log), Leaser (a single-writer epoch lease), KV (revision-CAS metadata), Blobs (content-addressed immutable bytes), and OrderedIndex (durable records with immutable acceptance order and current ranked and due views) — plus a typed error taxonomy, ValidateName, and the AppendDefinite ambiguity resolver.
Names and keys are canonical by construction (see ValidateName), so no two valid names alias one backend location. Every backend must accept ledger payloads and KV values up to 1 MiB; larger payloads are the engine's responsibility to offload to Blobs.
Index ¶
- Constants
- func AppendDefinite(ctx context.Context, l Ledger, name string, expected uint64, payload []byte) error
- func ValidateDue(due Due) error
- func ValidateName(name string) error
- func ValidateOrderedID(id OrderedID) error
- func ValidateOrderedLimit(limit int) error
- func ValidateOrderedRecord(record OrderedRecord) error
- func ValidateOrderedValue(value []byte) error
- func ValidateStableKey(key StableKey) error
- type AmbiguousError
- type AppendVerifyError
- type BlobConflictError
- type BlobNotFoundError
- type BlobReaderLifecycle
- type Blobs
- type Composite
- type ConflictError
- type Cursor
- type Due
- type DueCursor
- type DuePage
- type DueState
- type IncompleteCompositeError
- type InvalidDueError
- type InvalidNameError
- type InvalidOrderedCursorError
- type InvalidOrderedLimitError
- type InvalidOrderedRecordError
- type InvalidStableKeyError
- type KV
- type KeyNotFoundError
- type Lease
- type LeaseHeldError
- type LeaseLostError
- type Leaser
- type Ledger
- type OrderedAmbiguousError
- type OrderedCursorKind
- type OrderedCursorRule
- type OrderedDeletedError
- type OrderedID
- type OrderedIndex
- type OrderedOperation
- type OrderedPage
- type OrderedRecord
- type OrderedRecordNotFoundError
- type OrderedRevisionConflictError
- type OrderedRevisionExhaustedError
- type OrderedValueTooLargeError
- type PathReporter
- type Rank
- type RankedCursor
- type RankedPage
- type Record
- type RecordNotFoundError
- type StableKey
Constants ¶
const MaxOrderedPageLimit = 1000
MaxOrderedPageLimit is the inclusive maximum number of records a single OrderedIndex listing may request.
const MaxOrderedValueBytes = 1 << 20
MaxOrderedValueBytes is the largest value an OrderedIndex implementation must accept. Callers that need larger values must store the bulk content in Blobs and keep a reference in Value.
const MaxStableKeyBytes = 256
MaxStableKeyBytes is the inclusive maximum length, in UTF-8 bytes, of an OrderedID StableKey.
Variables ¶
This section is empty.
Functions ¶
func AppendDefinite ¶
func AppendDefinite(ctx context.Context, l Ledger, name string, expected uint64, payload []byte) error
AppendDefinite turns any Append into a definite outcome. On AmbiguousError it retries the identical append once; on conflict (from either attempt) it reads the record at expected+1 and byte-compares: equal payload means the original landed (success); a foreign payload means this writer has been fenced (ConflictError). A second ambiguous outcome surfaces AmbiguousError unresolved.
func ValidateDue ¶ added in v0.5.0
ValidateDue validates Due's discriminated state and its canonical NotDue representation.
func ValidateName ¶
ValidateName returns a non-nil *InvalidNameError if name violates the storage name grammar, or nil if it is valid. The grammar is canonical by construction: empty, ".", and ".." segments are unrepresentable, so no two valid names alias one backend location.
A valid name is 1..512 bytes of one or more segments joined by single '/', with no leading, trailing, or doubled '/'. Each segment starts with a byte in [a-z0-9] and continues with bytes in [a-z0-9_.-].
func ValidateOrderedID ¶ added in v0.5.0
ValidateOrderedID validates the storage-name components of id and its opaque StableKey. Namespace and OrderingScope deliberately retain ValidateName's canonical path grammar; StableKey deliberately does not.
func ValidateOrderedLimit ¶ added in v0.5.0
ValidateOrderedLimit reports whether limit is a valid OrderedIndex page limit.
func ValidateOrderedRecord ¶ added in v0.5.0
func ValidateOrderedRecord(record OrderedRecord) error
ValidateOrderedRecord validates an OrderedRecord's externally observable representation. Providers use it when constructing a record snapshot and callers may use it before asserting a returned record in their own code.
func ValidateOrderedValue ¶ added in v0.5.0
ValidateOrderedValue reports whether value falls within OrderedIndex's required value capacity. Nil and empty values are valid.
func ValidateStableKey ¶ added in v0.5.0
ValidateStableKey reports whether key is a valid opaque StableKey.
Types ¶
type AmbiguousError ¶
AmbiguousError reports a ledger append whose acknowledgement was lost or timed out: the record may or may not have been committed at Expected. Cause carries the underlying transport/timeout error and may be nil.
func (*AmbiguousError) Error ¶
func (e *AmbiguousError) Error() string
func (*AmbiguousError) Unwrap ¶
func (e *AmbiguousError) Unwrap() error
Unwrap returns the underlying cause (possibly nil).
type AppendVerifyError ¶
AppendVerifyError reports that AppendDefinite could not read the record at Seq to resolve an ambiguous/conflicting append. Fail closed: the caller must treat the append outcome as unknown. Cause carries the underlying read failure (the Read error or the cursor's non-EOF Next error) and is exposed via Unwrap.
func (*AppendVerifyError) Error ¶
func (e *AppendVerifyError) Error() string
func (*AppendVerifyError) Unwrap ¶
func (e *AppendVerifyError) Unwrap() error
Unwrap returns the underlying read failure so callers can errors.Is/As it.
type BlobConflictError ¶
type BlobConflictError struct {
Key string
}
BlobConflictError reports a blob Put where Key already exists with different content (blob writes are content-addressed and immutable per key).
func (*BlobConflictError) Error ¶
func (e *BlobConflictError) Error() string
type BlobNotFoundError ¶
type BlobNotFoundError struct {
Key string
}
BlobNotFoundError reports that a blob is absent at Key.
func (*BlobNotFoundError) Error ¶
func (e *BlobNotFoundError) Error() string
type BlobReaderLifecycle ¶ added in v0.6.0
BlobReaderLifecycle is an optional Blobs capability for providers whose Get readers support bounded shutdown. BlobReaderCloseBound returns a positive, documented upper bound for Close itself and for any active provider-controlled Read to return after Close begins. A successful Get returns a usable, concrete non-nil reader. Its Read and Close methods are safe to call concurrently. Close is idempotent with a stable success/failure classification: repeated calls either both succeed, or their errors are equivalent under errors.Is. After Close returns, every Read returns zero bytes and a non-nil error other than io.EOF; that terminal error is provider-specific.
type Blobs ¶
type Blobs interface {
Put(ctx context.Context, key string, r io.Reader) error
Get(ctx context.Context, key string) (io.ReadCloser, error)
Delete(ctx context.Context, key string) error
List(ctx context.Context, prefix string) ([]string, error)
}
Blobs holds bulk immutable bytes (large-record offload; workspace snapshots). Put streams; keys are content-addressed by callers. Existing byte-identical content is a success/no-op; existing different content returns *BlobConflictError and leaves the original object unchanged. Delete is idempotent: deleting an absent key succeeds.
type Composite ¶
type Composite struct {
Ledger
Leaser
KV
Blobs
OrderedIndex OrderedIndex
}
Composite holds the storage primitives assembled where dependencies are wired, never inside engines. OrderedIndex remains a named field rather than an embedded primitive because Ledger, KV, and Blobs already have colliding method names when promoted together. OrderedIndex is the one field that may be nil — NewComposite leaves it so — which is what RequireOrderedIndex is for.
func NewComposite ¶
NewComposite assembles the legacy four-primitive Composite, rejecting any nil primitive up front so a partially-wired backend fails at the composition root rather than at first use. It intentionally leaves OrderedIndex nil for backwards compatibility: existing callers do not need to change. SessionStore (and any other component that requires ordered records) is responsible for rejecting a Composite whose OrderedIndex is nil at its own composition boundary.
func NewCompositeWithOrderedIndex ¶ added in v0.5.0
func NewCompositeWithOrderedIndex(l Ledger, le Leaser, kv KV, bl Blobs, oi OrderedIndex) (*Composite, error)
NewCompositeWithOrderedIndex assembles all five storage primitives. Unlike NewComposite, it requires OrderedIndex so a component whose contract uses ordered records can fail during wiring rather than on its first operation.
func (*Composite) RequireOrderedIndex ¶ added in v0.5.0
func (c *Composite) RequireOrderedIndex() (OrderedIndex, error)
RequireOrderedIndex returns the composite's OrderedIndex, or *IncompleteCompositeError naming it as missing. NewComposite deliberately leaves the field nil, so any consumer that needs ordered records has to check; this gives that check one typed, non-panicking form instead of an ad-hoc nil comparison at each use site. A nil *Composite is treated as a composite that has no ordered index rather than dereferenced.
type ConflictError ¶
ConflictError reports a ledger compare-and-swap that failed because the caller appended at the wrong expected sequence (the head had moved).
func (*ConflictError) Error ¶
func (e *ConflictError) Error() string
type DueCursor ¶ added in v0.5.0
type DueCursor string
DueCursor is a provider-issued, opaque, versioned continuation token for ListDue. A nonempty token is valid only for the exact namespace, due bound, and due query that issued it. ListDue must return *InvalidOrderedCursorError with Kind DueCursorKind for a malformed token, an unknown token version, a token issued for another cursor kind, or a query mismatch. A cursor conveys position, not authority: a provider re-checks the namespace and due bound against the live request and never trusts them from the token.
type DuePage ¶ added in v0.5.0
type DuePage struct {
Records []OrderedRecord
NextCursor DueCursor
}
DuePage is a page from ListDue. An empty NextCursor denotes an exhausted result set.
type DueState ¶ added in v0.5.0
type DueState uint8
DueState records whether an OrderedRecord participates in due-time listings.
const ( // NotDue means a record is absent from ListDue results. Its UnixMillis must // be zero, which gives the non-due state one canonical representation. NotDue DueState = iota // DueAt means UnixMillis is an absolute UTC Unix timestamp in milliseconds // and the record participates in ListDue results. DueAt )
type IncompleteCompositeError ¶
type IncompleteCompositeError struct {
Missing []string
}
IncompleteCompositeError reports that NewComposite or NewCompositeWithOrderedIndex was handed one or more nil primitives. Missing names them in field order (Ledger, Leaser, KV, Blobs, OrderedIndex) so the assembly site knows exactly which providers were not wired.
func (*IncompleteCompositeError) Error ¶
func (e *IncompleteCompositeError) Error() string
type InvalidDueError ¶ added in v0.5.0
InvalidDueError reports a Due state that is not canonical or uses an unknown discriminator.
func (*InvalidDueError) Error ¶ added in v0.5.0
func (e *InvalidDueError) Error() string
type InvalidNameError ¶
InvalidNameError reports a name that violates the storage grammar: one or more segments joined by single '/', each segment matching [a-z0-9][a-z0-9_.-]*, no leading/trailing '/', at most 512 bytes total.
func (*InvalidNameError) Error ¶
func (e *InvalidNameError) Error() string
type InvalidOrderedCursorError ¶ added in v0.5.0
type InvalidOrderedCursorError struct {
Kind OrderedCursorKind
Rule OrderedCursorRule
CursorLength uint16
}
InvalidOrderedCursorError reports a malformed, unknown-version, wrong-kind, or cross-query opaque OrderedIndex continuation cursor. Kind identifies the listing operation that rejected it. Rule is a safe classification. CursorLength is the raw token's bounded byte length; neither it nor Error exposes raw opaque cursor contents.
func NewInvalidOrderedCursorError ¶ added in v0.5.0
func NewInvalidOrderedCursorError(kind OrderedCursorKind, cursor string, rule OrderedCursorRule) *InvalidOrderedCursorError
NewInvalidOrderedCursorError constructs an error for cursor while retaining only its safe, bounded byte length. Providers must use it rather than placing raw cursor contents in an error or log message.
func (*InvalidOrderedCursorError) Error ¶ added in v0.5.0
func (e *InvalidOrderedCursorError) Error() string
type InvalidOrderedLimitError ¶ added in v0.5.0
InvalidOrderedLimitError reports a List* limit outside the inclusive range 1..Max.
func (*InvalidOrderedLimitError) Error ¶ added in v0.5.0
func (e *InvalidOrderedLimitError) Error() string
type InvalidOrderedRecordError ¶ added in v0.5.0
InvalidOrderedRecordError reports an OrderedRecord that violates an invariant that crosses multiple fields.
func (*InvalidOrderedRecordError) Error ¶ added in v0.5.0
func (e *InvalidOrderedRecordError) Error() string
type InvalidStableKeyError ¶ added in v0.5.0
InvalidStableKeyError reports an OrderedID StableKey that is empty, too long, or not valid UTF-8. Stable keys are opaque and are not constrained by the storage name grammar. StableKeyLength is the input's byte length capped at 65,535; the error never retains or renders the raw key.
func (*InvalidStableKeyError) Error ¶ added in v0.5.0
func (e *InvalidStableKeyError) Error() string
type KV ¶
type KV interface {
Get(ctx context.Context, key string) (val []byte, rev uint64, err error)
Put(ctx context.Context, key string, expectedRev uint64, val []byte) (rev uint64, err error)
Keys(ctx context.Context, prefix string) ([]string, error)
Delete(ctx context.Context, key string) error
}
KV holds small CAS'd metadata (the session catalog). Revisions are per-key, strictly increasing; Put with expectedRev 0 requires the key to be absent.
type KeyNotFoundError ¶
type KeyNotFoundError struct {
Key string
}
KeyNotFoundError reports that a KV key is absent.
func (*KeyNotFoundError) Error ¶
func (e *KeyNotFoundError) Error() string
type LeaseHeldError ¶
LeaseHeldError reports an Acquire that was refused because another holder owns the lease at HolderEpoch.
func (*LeaseHeldError) Error ¶
func (e *LeaseHeldError) Error() string
type LeaseLostError ¶
LeaseLostError reports a write attempted after the caller's lease at Epoch was lost or expired (fenced by a newer holder).
func (*LeaseLostError) Error ¶
func (e *LeaseLostError) Error() string
type Leaser ¶
Leaser grants renewable, exclusive, epoch-fenced ownership of a name. A provider maintains and renews a live grant by its native mechanism; Lease.Lost closes when it can no longer safely assert ownership, including Release, expiry, or takeover. Acquire fails with *LeaseHeldError while a live holder exists, and a later grant of the same name has a strictly greater epoch. Acquire and Release must remain correct across independent calls: no grant may depend on retaining one connection or session. Release is idempotent, including after loss, and cannot free a later holder.
type Ledger ¶
type Ledger interface {
Append(ctx context.Context, name string, expected uint64, payload []byte) error
Read(ctx context.Context, name string, from uint64) (Cursor, error)
Tip(ctx context.Context, name string) (uint64, error)
Delete(ctx context.Context, name string) error
}
Ledger addresses many ledgers by name. Append commits payload as the record immediately after sequence `expected` (CAS on the tip; expected == 0 means the ledger must be empty). The committed record's seq is expected+1 by definition, so Append returns no sequence. Sequences are 1-based, contiguous, immutable.
Append outcomes are a tri-state:
- nil — committed, definitely.
- *ConflictError — something already occupies expected+1. Definite: the record did not land.
- *AmbiguousError — the outcome is unknown (lost ack / lost COMMIT response). Only networked backends may return this; fs and memory never do.
Any other error is a definite failure (fail closed, tip unadvanced).
Edge semantics:
- Absent == empty. A never-written (or deleted) ledger behaves as empty: Tip returns 0; Read yields an immediately-drained cursor; Append with expected 0 creates it implicitly; Delete of an absent ledger is a no-op success (idempotent).
- Reads beyond the tip are empty, not errors. Any from > tip (including tip+1) yields a drained cursor. Cursors are bounded: they observe the tip as of Read and never tail later appends.
- Payloads are caller-owned. A backend must not reuse or mutate Record.Payload after Next returns. Zero-length payloads are legal.
- Listings are canonical: KV.Keys and Blobs.List return lexicographically ascending, duplicate-free results.
type OrderedAmbiguousError ¶ added in v0.5.0
type OrderedAmbiguousError struct {
Operation OrderedOperation
ID OrderedID
Cause error
}
OrderedAmbiguousError reports a networked OrderedIndex mutation whose acknowledgement was lost or timed out, so the mutation may or may not have committed. Cause carries the underlying transport error and may be nil.
func (*OrderedAmbiguousError) Error ¶ added in v0.5.0
func (e *OrderedAmbiguousError) Error() string
func (*OrderedAmbiguousError) Unwrap ¶ added in v0.5.0
func (e *OrderedAmbiguousError) Unwrap() error
Unwrap returns the underlying cause (possibly nil).
type OrderedCursorKind ¶ added in v0.5.0
type OrderedCursorKind string
OrderedCursorKind identifies the query family that rejected a cursor.
const ( // RankedCursorKind identifies a ListRanked continuation cursor. RankedCursorKind OrderedCursorKind = "ranked" // DueCursorKind identifies a ListDue continuation cursor. DueCursorKind OrderedCursorKind = "due" )
func (OrderedCursorKind) String ¶ added in v0.5.0
func (k OrderedCursorKind) String() string
type OrderedCursorRule ¶ added in v0.5.0
type OrderedCursorRule uint8
OrderedCursorRule classifies why a provider rejected an opaque cursor. Its String form is fixed so error rendering never relies on provider-supplied token text.
const ( // OrderedCursorMalformed reports a syntactically malformed token. OrderedCursorMalformed OrderedCursorRule = iota + 1 // OrderedCursorUnknownVersion reports an unsupported token version. OrderedCursorUnknownVersion // OrderedCursorWrongKind reports a token issued for another cursor family. OrderedCursorWrongKind // OrderedCursorQueryMismatch reports a token bound to another query. OrderedCursorQueryMismatch )
func (OrderedCursorRule) String ¶ added in v0.5.0
func (r OrderedCursorRule) String() string
type OrderedDeletedError ¶ added in v0.5.0
type OrderedDeletedError struct {
ID OrderedID
}
OrderedDeletedError reports an Update attempted against a logical tombstone. Tombstones cannot be resurrected through OrderedIndex.
func (*OrderedDeletedError) Error ¶ added in v0.5.0
func (e *OrderedDeletedError) Error() string
type OrderedID ¶ added in v0.5.0
OrderedID identifies an ordered record. The (Namespace, OrderingScope) pair is the order scope: the unit within which Order strictly increases and is never reused. The same OrderingScope in another Namespace is a separate order scope with its own independent stream, though a provider may serve every scope from one shared underlying sequence, so order values are not comparable across scopes.
type OrderedIndex ¶ added in v0.5.0
type OrderedIndex interface {
// Get validates id first, then returns the current record, including a
// logical tombstone. An identity that has never been created returns
// *OrderedRecordNotFoundError.
Get(ctx context.Context, id OrderedID) (OrderedRecord, error)
// Create validates id first and then atomically inspects that identity. If
// it already exists, including as a tombstone, Create returns its canonical
// stored record with created == false without validating the candidate
// rankingScope, value, rank, or due state. Only when the identity is absent
// does Create validate those candidate fields, assign revision 1, and
// allocate a nonzero immutable order strictly greater than every order the
// scope has allocated before. It need not be the next integer: allocation
// may be sparse.
Create(ctx context.Context, id OrderedID, rankingScope string, value []byte, rank Rank, due Due) (record OrderedRecord, created bool, err error)
// Update validates id first. An absent record returns
// *OrderedRecordNotFoundError and a tombstone returns *OrderedDeletedError,
// in both cases regardless of expectedRevision. For a live record, Update
// validates candidate Value, Rank, and Due before comparing expectedRevision:
// an invalid candidate returns its validation error, while a valid stale
// revision returns *OrderedRevisionConflictError. A valid match replaces
// only Value, Rank, and Due and advances Revision exactly once. It cannot
// change identity, ranking scope, or immutable order. If Revision cannot
// advance, it returns *OrderedRevisionExhaustedError unchanged.
Update(ctx context.Context, id OrderedID, expectedRevision uint64, value []byte, rank Rank, due Due) (OrderedRecord, error)
// Delete validates id first. An absent record returns
// *OrderedRecordNotFoundError. A tombstone returns its canonical existing
// state regardless of expectedRevision, including a retry with the
// pre-delete revision. For a live record, a stale expectedRevision returns
// *OrderedRevisionConflictError; a matching revision advances exactly once,
// sets Deleted, clears Rank to Rank{} and Due to Due{State: NotDue,
// UnixMillis: 0}, and preserves Value, RankingScope, identity, and immutable
// Order. If Revision cannot advance, it returns
// *OrderedRevisionExhaustedError unchanged.
Delete(ctx context.Context, id OrderedID, expectedRevision uint64) (OrderedRecord, error)
// ListOrdered returns the immutable acceptance-order stream, including
// tombstones, in ascending Order after the exclusive numeric afterOrder.
// Passing zero starts at the beginning of the (Namespace, OrderingScope)
// stream.
ListOrdered(ctx context.Context, namespace string, orderingScope string, afterOrder uint64, limit int) (OrderedPage, error)
// ListRanked returns current, nondeleted ranked records in descending
// (rank, stable_key, ordering_scope) order. OrderingScope is consulted only
// after the frozen (rank, stable_key) pair ties, making pagination total
// without narrowing valid identities. after is a provider-issued opaque,
// versioned, query-bound token. A malformed, unknown-version, wrong-kind,
// or query-mismatched token returns *InvalidOrderedCursorError with Kind
// RankedCursorKind.
//
// Pagination resumes from the frozen (rank, stable_key, ordering_scope)
// tuple the cursor names, not from a snapshot of the result set. A record
// whose rank changes between two pages therefore moves relative to that
// frozen position: it is skipped if it moves to an already-passed position
// and returned twice if it moves ahead of one. This is inherent to
// keyset pagination over a live view; a sweep that must see every record
// exactly once has to reconcile by identity, not by page.
ListRanked(ctx context.Context, namespace string, rankingScope string, after RankedCursor, limit int) (RankedPage, error)
// ListDue returns current, nondeleted DueAt records with UnixMillis no later
// than dueAtOrBefore in ascending (due_at, stable_key, ordering_scope)
// order. OrderingScope is consulted only after the frozen (due_at,
// stable_key) pair ties. after is opaque and bound to namespace, the fixed
// due bound, and this exact due query. A malformed, unknown-version,
// wrong-kind, or query-mismatched token returns *InvalidOrderedCursorError
// with Kind DueCursorKind.
//
// Like ListRanked, ListDue resumes from the frozen (due_at, stable_key,
// ordering_scope) tuple the cursor names, so a record whose due time moves
// across that position between pages is skipped or returned twice.
ListDue(ctx context.Context, namespace string, dueAtOrBefore int64, after DueCursor, limit int) (DuePage, error)
}
OrderedIndex provides a durable record collection with immutable acceptance order plus current ranked and due views. Implementations validate relevant inputs at their public boundary using the validators below. Each method's validation, lookup, and CAS precedence is authoritative; this overview does not impose an order beyond those method-specific rules. Every method that accepts an OrderedID (Get, Create, Update, and Delete) validates it first with ValidateOrderedID before inspecting or mutating a record. A canceled context may return its ordinary context error. A networked mutation with an indeterminate outcome returns *OrderedAmbiguousError; local implementations never do. Nonempty ranked and due cursors are provider-issued opaque versioned tokens; implementations must fail closed with *InvalidOrderedCursorError of the matching cursor Kind if one is malformed, has an unknown version, has the wrong cursor kind, or does not bind to the exact request query.
All returned Records and their Value slices are snapshots owned by the caller. Implementations must copy caller Value before retaining it and must copy Value before returning records.
type OrderedOperation ¶ added in v0.5.0
type OrderedOperation string
OrderedOperation identifies a mutation whose outcome could be ambiguous.
const ( // OrderedCreateOperation identifies Create. OrderedCreateOperation OrderedOperation = "create" // OrderedUpdateOperation identifies Update. OrderedUpdateOperation OrderedOperation = "update" // OrderedDeleteOperation identifies Delete. OrderedDeleteOperation OrderedOperation = "delete" )
type OrderedPage ¶ added in v0.5.0
type OrderedPage struct {
Records []OrderedRecord
NextAfterOrder uint64
}
OrderedPage is a page from ListOrdered. NextAfterOrder is zero when no rows were returned; otherwise it is the final immutable order in Records and may be passed as afterOrder to resume the acceptance-order stream.
type OrderedRecord ¶ added in v0.5.0
type OrderedRecord struct {
ID OrderedID
RankingScope string
Revision uint64
Order uint64
Due Due
Rank Rank
Value []byte
Deleted bool
}
OrderedRecord is the complete state of one ordered index row. Revision and Order are provider-assigned: Revision is always nonzero; Create assigns 1, and every successful Update or live Delete advances it exactly once. Revision never wraps to zero: if a provider cannot advance the maximal uint64 it returns *OrderedRevisionExhaustedError without changing state. Order is nonzero, immutable, strictly increasing within its order scope, and never reused there — including after a tombstone. It is deliberately NOT required to be contiguous or 1-based: a provider may allocate order from a JetStream stream sequence or a shared SQL sequence, so orders may be sparse and may be shared across order scopes. Callers resume from an exclusive order cursor, for which density buys nothing, and must never infer a position, a count, or a scope from an order value. Callers own Value after it is returned; implementations must not retain or later mutate caller-owned Value slices.
type OrderedRecordNotFoundError ¶ added in v0.5.0
type OrderedRecordNotFoundError struct {
ID OrderedID
}
OrderedRecordNotFoundError reports an ordered identity that has never been created. Tombstoned records are distinct from absent records.
func (*OrderedRecordNotFoundError) Error ¶ added in v0.5.0
func (e *OrderedRecordNotFoundError) Error() string
type OrderedRevisionConflictError ¶ added in v0.5.0
type OrderedRevisionConflictError struct {
ID OrderedID
ExpectedRevision uint64
ActualRevision uint64
}
OrderedRevisionConflictError reports an OrderedIndex compare-and-swap whose current revision did not equal ExpectedRevision. ActualRevision is the current revision observed by a backend when it can determine it; a backend that cannot safely disclose it leaves it zero.
func (*OrderedRevisionConflictError) Error ¶ added in v0.5.0
func (e *OrderedRevisionConflictError) Error() string
type OrderedRevisionExhaustedError ¶ added in v0.5.0
OrderedRevisionExhaustedError reports a mutation that cannot advance a live OrderedRecord revision without overflowing uint64. The provider leaves the record unchanged.
func (*OrderedRevisionExhaustedError) Error ¶ added in v0.5.0
func (e *OrderedRevisionExhaustedError) Error() string
type OrderedValueTooLargeError ¶ added in v0.5.0
OrderedValueTooLargeError reports an OrderedIndex value over the supported maximum size in bytes.
func (*OrderedValueTooLargeError) Error ¶ added in v0.5.0
func (e *OrderedValueTooLargeError) Error() string
type PathReporter ¶
type PathReporter interface {
StoragePaths() []string
}
PathReporter is an optional capability implemented by providers that persist data on the local filesystem. StoragePaths returns the provider's canonical local roots in a caller-owned slice. Remote and in-memory providers need not implement it.
type Rank ¶ added in v0.5.0
Rank is the mutable rank state of an ordered record. A record with Ranked false is absent from ListRanked results.
type RankedCursor ¶ added in v0.5.0
type RankedCursor string
RankedCursor is a provider-issued, opaque, versioned continuation token for ListRanked. A nonempty token is valid only for the exact namespace, ranking scope, and ranked query that issued it. ListRanked must return *InvalidOrderedCursorError with Kind RankedCursorKind for a malformed token, an unknown token version, a token issued for another cursor kind, or a query mismatch. A cursor conveys position, not authority: a provider re-checks the namespace and ranking scope against the live request and never trusts them from the token.
type RankedPage ¶ added in v0.5.0
type RankedPage struct {
Records []OrderedRecord
NextCursor RankedCursor
}
RankedPage is a page from ListRanked. An empty NextCursor denotes an exhausted result set.
type RecordNotFoundError ¶
RecordNotFoundError reports that a ledger has no record at the requested Seq.
func (*RecordNotFoundError) Error ¶
func (e *RecordNotFoundError) Error() string
type StableKey ¶ added in v0.5.0
type StableKey string
StableKey is the opaque, stable identity component of an ordered record. It is deliberately not a storage name or path: any valid UTF-8 value from 1 through MaxStableKeyBytes bytes is accepted, including slashes, uppercase letters, punctuation, and Unicode.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package memstore is the in-memory reference backend for storage's five primitives.
|
Package memstore is the in-memory reference backend for storage's five primitives. |
|
Package storetest provides backend-conformance suites for the five storage primitives — Ledger, Leaser, KV, Blobs, and OrderedIndex.
|
Package storetest provides backend-conformance suites for the five storage primitives — Ledger, Leaser, KV, Blobs, and OrderedIndex. |