Documentation
¶
Overview ¶
Package datorium is a smart Go client for DatoriumDB's HTTP API v1.
It caches establishment configuration, routes access-language commands to the correct shard members, retries wrongMachine responses, and helps resolve document references.
Index ¶
- Constants
- func AppendCachedRefOp(arrayField, collection, id string) map[string]any
- func BuildCommand(word, target, parm string, detail any) (string, error)
- func BuildCommandOrdered(word, target, parm string, detail ojson.JSONValue) (string, error)
- func IsAppCode(err error, code string) bool
- func JoinErrors(errs ...error) error
- func NewDocumentID() string
- func NewOperationID() string
- func PatchDetailAppendingCachedRef(schemaMarker, version, arrayField, refCollection, refID string) map[string]any
- type APIError
- type AppError
- type CatalogError
- type CatalogMismatch
- type CatalogMismatchCode
- type Client
- func (c *Client) CachedEstablishment() *Establishment
- func (c *Client) Close() error
- func (c *Client) Command(ctx context.Context, baseURL, line string) (Result, error)
- func (c *Client) Create(ctx context.Context, collection, id string, content map[string]any) (WriteResult, error)
- func (c *Client) Delete(ctx context.Context, collection, id string, detail map[string]any) (WriteResult, error)
- func (c *Client) Establish(ctx context.Context, cols ...CollectionRef) error
- func (c *Client) Health(ctx context.Context) (Result, error)
- func (c *Client) Patch(ctx context.Context, collection, id string, detail map[string]any) (WriteResult, error)
- func (c *Client) PatchWithVersionRetry(ctx context.Context, collection, id string, ...) (WriteResult, error)
- func (c *Client) Read(ctx context.Context, collection, id string, opts *ReadOptions) (ReadResult, error)
- func (c *Client) Ready(ctx context.Context) (Result, error)
- func (c *Client) ResolveDirectRef(ctx context.Context, ref string, opts *ReadOptions) (ReadResult, error)
- func (c *Client) ResolveRefsInSOT(ctx context.Context, sot ojson.JSONValue, maxDepth int) (map[string]ReadResult, error)
- func (c *Client) Schema(ctx context.Context, collection string, version int) (Result, error)
- func (c *Client) Search(ctx context.Context, collection, searchName string, vars map[string]any, ...) (SearchResult, error)
- type Collection
- type CollectionClient
- func (cc CollectionClient[T]) Client() *Client
- func (cc CollectionClient[T]) Collection() Collection[T]
- func (cc CollectionClient[T]) CompiledSchema() ojson.JSONSchema
- func (cc CollectionClient[T]) CreateDoc(ctx context.Context, id *string, doc T) (WriteResult, error)
- func (cc CollectionClient[T]) CreatePatch(item CollectionItem[T], patch ojson.Patch) (CollectionPatch[T], error)
- func (cc CollectionClient[T]) CreatePatchFromChanges(item CollectionItem[T]) (CollectionPatch[T], error)
- func (cc CollectionClient[T]) DeleteDoc(ctx context.Context, item CollectionItem[T]) (WriteResult, error)
- func (cc CollectionClient[T]) GetDoc(ctx context.Context, id string) (CollectionItem[T], error)
- func (cc CollectionClient[T]) GetDocOpts(ctx context.Context, id string, opts *ReadOptions) (CollectionItem[T], error)
- func (cc CollectionClient[T]) PatchDoc(ctx context.Context, patch CollectionPatch[T]) (WriteResult, error)
- type CollectionItem
- type CollectionPatch
- type CollectionRef
- type Config
- type DocMeta
- type Establishment
- type GeneralConfig
- type ReadOptions
- type ReadResult
- type Result
- type Route
- type RouteKind
- type SchemaEntry
- type SearchResult
- type ServerEntry
- type ShardAssignment
- type StaticToken
- type TokenSource
- type TransportError
- type WriteResult
Examples ¶
Constants ¶
const ( CodeWrongMachine = "wrongMachine" CodeVersionMismatch = "versionMismatch" CodeDocumentNotFound = "documentNotFound" CodeDocumentExists = "documentExists" CodeUnauthenticated = "unauthenticated" CodeInvalidToken = "invalidToken" CodeTokenExpired = "tokenExpired" CodeDocumentStale = "documentStale" CodeReadMemberStale = "readMemberStale" CodeSearchNotFound = "searchNotFound" )
Common stable application error codes from DatoriumDB.
Variables ¶
This section is empty.
Functions ¶
func AppendCachedRefOp ¶
AppendCachedRefOp returns an RFC6902 "add" operation that appends a @@__collection__id value to a document array field (e.g. Users.todoLists). Path uses JSON Pointer array-append ("/-").
This returns a map for use with the raw Patch escape hatch. Prefer CollectionClient.CreatePatch / PatchDoc for new code.
func BuildCommand ¶
BuildCommand formats an access-language command with a strict-JSON detail object.
func BuildCommandOrdered ¶
BuildCommandOrdered formats an access-language command whose detail object is serialized with ojson field order preserved. detail must be an object (or Void/missing, treated as {}).
func JoinErrors ¶
JoinErrors joins multiple errors for reporting (Go 1.20+).
func NewDocumentID ¶
func NewDocumentID() string
NewDocumentID returns a new ULID string suitable for client-supplied create IDs. The server never generates document IDs; callers should mint before create (Create / CollectionClient.CreateDoc do this when the id is empty / nil).
func NewOperationID ¶
func NewOperationID() string
NewOperationID returns a new ULID string suitable for write operationId fields.
func PatchDetailAppendingCachedRef ¶
func PatchDetailAppendingCachedRef(schemaMarker, version, arrayField, refCollection, refID string) map[string]any
PatchDetailAppendingCachedRef builds a patch detail object for appending one cached ref to an array field. schemaMarker and version come from a prior read.
Types ¶
type APIError ¶
type APIError struct {
Code string
Path string
Message string
Expected ojson.JSONValue
Actual ojson.JSONValue
}
APIError is one application-level error entry from a DatoriumDB envelope.
type AppError ¶
type AppError struct {
Code string
Message string
Errors []APIError
Result Result
// ConfigVersion is diagnostic-only on wrongMachine: what the refusing
// server believes. It is never authoritative establishment version.
ConfigVersion int
Collection string
ID string
Command string
// Deprecated bounce hint fields. Servers no longer emit these; kept
// only so older envelopes still parse without becoming routing inputs.
ShardSlot string
CorrectServer string
BaseURL string
}
AppError is an application-level failure (HTTP often still 200).
type CatalogError ¶
type CatalogError struct {
Mismatches []CatalogMismatch
}
CatalogError is returned by Establish when the app catalog does not match the live establishment schemas.
func (*CatalogError) Error ¶
func (e *CatalogError) Error() string
type CatalogMismatch ¶
type CatalogMismatch struct {
Collection string
Code CatalogMismatchCode
Expected int // declared schema version
Actual int // live schema version; -1 when collection is missing
}
CatalogMismatch is one declared collection that does not match the live establishment document.
type CatalogMismatchCode ¶
type CatalogMismatchCode string
CatalogMismatchCode identifies one catalog validation failure.
const ( CatalogCollectionNotFound CatalogMismatchCode = "collectionNotFound" CatalogSchemaVersionMismatch CatalogMismatchCode = "schemaVersionMismatch" )
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a smart DatoriumDB client.
func (*Client) CachedEstablishment ¶
func (c *Client) CachedEstablishment() *Establishment
CachedEstablishment returns the last fetched establishment document, if any.
func (*Client) Command ¶
Command posts a raw access-language command line to the given base URL (or the establishment URL when baseURL is empty), without smart routing.
func (*Client) Create ¶
func (c *Client) Create(ctx context.Context, collection, id string, content map[string]any) (WriteResult, error)
Create creates a document. The server never assigns create IDs: an empty id is replaced with a client-minted ULID (NewDocumentID) before the command is sent. The access-language line is marshaled once so retries cannot reshuffle map key order. Ambiguous failures (documentExists, transport errors) may be resolved with a follow-up read — see Config.CreateAmbiguousVerifyDelay.
Prefer CollectionClient.CreateDoc for order-safe document bodies.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
datorium "github.com/JohnAD/datorium-client-go"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /datoriumdb/v1/establish", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{
"ok":true,
"general":{"name":"demo","establishmentServer":"server1","version":1},
"servers":{"server1":{"baseURL":%q}},
"shardMap":{"default":{"00-FF":{"SHARD_SOT_MEMBER":"server1","SHARD_READ_MEMBER":["server1"],"PROXY_READ_MEMBER":[]}}},
"schemas":{},"searches":{},"auth":{}
}`, "http://"+r.Host)
})
mux.HandleFunc("POST /datoriumdb/v1/command", func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprint(w, `{"ok":true,"command":"create","collection":"Todos","id":"t1","$":"Todos:0","#":"v1","operationId":"op1"}`)
})
ts := httptest.NewServer(mux)
defer ts.Close()
client, err := datorium.New(datorium.Config{
EstablishmentURL: ts.URL,
Token: "demo-token",
})
if err != nil {
panic(err)
}
wr, err := client.Create(context.Background(), "Todos", "t1", map[string]any{
"$": "Todos:0", "title": "demo", "status": "open",
})
if err != nil {
panic(err)
}
fmt.Println(wr.ID, wr.Version)
}
Output: t1 v1
func (*Client) Delete ¶
func (c *Client) Delete(ctx context.Context, collection, id string, detail map[string]any) (WriteResult, error)
Delete deletes a document. detail must include "#"; "$" is recommended.
func (*Client) Establish ¶
func (c *Client) Establish(ctx context.Context, cols ...CollectionRef) error
Establish fetches and caches establishment config from the establishment server. When cols are provided, each declared collection name and schema version is validated against the live establishment schemas (CatalogError on mismatch). Extra server collections not listed in cols are ignored.
func (*Client) Health ¶
Health calls GET /datoriumdb/v1/health on the establishment URL (or override).
func (*Client) Patch ¶
func (c *Client) Patch(ctx context.Context, collection, id string, detail map[string]any) (WriteResult, error)
Patch applies RFC6902 operations to a document. detail must include "$", "#", and usually "RFC6902". operationId is filled if missing.
func (*Client) PatchWithVersionRetry ¶
func (c *Client) PatchWithVersionRetry(ctx context.Context, collection, id string, build func(sot ojson.JSONValue) (map[string]any, error)) (WriteResult, error)
PatchWithVersionRetry re-reads on versionMismatch and retries patch once. build receives the ordered SOT document and returns a raw patch detail map (escape hatch); prefer CollectionClient.PatchDoc for new code.
func (*Client) Read ¶
func (c *Client) Read(ctx context.Context, collection, id string, opts *ReadOptions) (ReadResult, error)
Read reads a document by id.
func (*Client) ResolveDirectRef ¶
func (c *Client) ResolveDirectRef(ctx context.Context, ref string, opts *ReadOptions) (ReadResult, error)
ResolveDirectRef reads the document targeted by a @__Collection__id string.
func (*Client) ResolveRefsInSOT ¶
func (c *Client) ResolveRefsInSOT(ctx context.Context, sot ojson.JSONValue, maxDepth int) (map[string]ReadResult, error)
ResolveRefsInSOT walks top-level SOT string fields and resolves direct refs up to maxDepth (1 = only the provided document's direct fields).
func (*Client) Search ¶
func (c *Client) Search(ctx context.Context, collection, searchName string, vars map[string]any, pathSegments []string) (SearchResult, error)
Search runs a precompiled search. For simple equals-string clauses, pass pathSegments via searchpath.EqualsStringSegments so the client can route to the correct search shard. If pathSegments is nil, the command is sent to PreferServer / establishment and relies on wrongMachine bounce.
type Collection ¶
Collection is a compile-time binding of a document content type T to a collection name and schema version. Declare once in application code, pass to Establish for catalog validation, then Bind to obtain a CollectionClient:
var Todos = datorium.MustCollection[Todo]("Todos", 0)
todos, err := Todos.Bind(client)
func MustCollection ¶
func MustCollection[T any](name string, schemaVersion int) Collection[T]
MustCollection returns a Collection[T]. It panics if name is empty or schemaVersion is negative.
func (Collection[T]) Bind ¶
func (col Collection[T]) Bind(c *Client) (CollectionClient[T], error)
Bind attaches this collection descriptor to an established client. It verifies the live schema name/version and compiles the ojson schema.
func (Collection[T]) CollectionName ¶
func (c Collection[T]) CollectionName() string
CollectionName implements CollectionRef.
func (Collection[T]) SchemaMarker ¶
func (c Collection[T]) SchemaMarker() string
SchemaMarker returns the "$" value "Name:version".
func (Collection[T]) SchemaVersion ¶
func (c Collection[T]) SchemaVersion() int
SchemaVersion implements CollectionRef.
type CollectionClient ¶
type CollectionClient[T any] struct { // contains filtered or unexported fields }
CollectionClient is a typed, collection-scoped view of a Client. Obtain one with Collection[T].Bind after Establish.
func (CollectionClient[T]) Client ¶
func (cc CollectionClient[T]) Client() *Client
Client returns the underlying smart client.
func (CollectionClient[T]) Collection ¶
func (cc CollectionClient[T]) Collection() Collection[T]
Collection returns the catalog descriptor used to bind this client.
func (CollectionClient[T]) CompiledSchema ¶
func (cc CollectionClient[T]) CompiledSchema() ojson.JSONSchema
CompiledSchema returns the ojson schema compiled at Bind time.
func (CollectionClient[T]) CreateDoc ¶
func (cc CollectionClient[T]) CreateDoc(ctx context.Context, id *string, doc T) (WriteResult, error)
CreateDoc creates a document from the typed content struct doc. Pass id nil to mint a ULID locally, or a non-empty *string for an explicit id. Empty strings are rejected. The server never assigns create IDs.
"$" is taken from the collection (error if doc already set a disagreeing "$"). Content is serialized to ordered JSON once before any network attempt so retries keep the same id and bytes.
func (CollectionClient[T]) CreatePatch ¶
func (cc CollectionClient[T]) CreatePatch(item CollectionItem[T], patch ojson.Patch) (CollectionPatch[T], error)
CreatePatch validates a hand-built ojson.Patch against the item's original content and bound schema, then wraps it with the item's id and version.
func (CollectionClient[T]) CreatePatchFromChanges ¶
func (cc CollectionClient[T]) CreatePatchFromChanges(item CollectionItem[T]) (CollectionPatch[T], error)
CreatePatchFromChanges diffs the item's immutable original content against the current Doc using the bound schema. The resulting patch carries the item's id and version.
func (CollectionClient[T]) DeleteDoc ¶
func (cc CollectionClient[T]) DeleteDoc(ctx context.Context, item CollectionItem[T]) (WriteResult, error)
DeleteDoc deletes the document represented by item (optimistic concurrency).
func (CollectionClient[T]) GetDoc ¶
func (cc CollectionClient[T]) GetDoc(ctx context.Context, id string) (CollectionItem[T], error)
GetDoc reads a document by id (no extra fields / cache summaries).
func (CollectionClient[T]) GetDocOpts ¶
func (cc CollectionClient[T]) GetDocOpts(ctx context.Context, id string, opts *ReadOptions) (CollectionItem[T], error)
GetDocOpts reads a document by id with optional extra fields / cache summaries.
func (CollectionClient[T]) PatchDoc ¶
func (cc CollectionClient[T]) PatchDoc(ctx context.Context, patch CollectionPatch[T]) (WriteResult, error)
PatchDoc applies a CollectionPatch created by this collection client.
type CollectionItem ¶
type CollectionItem[T any] struct { Doc T OriginalDoc T Meta DocMeta ExtraFields ojson.JSONValue CacheSummaries ojson.JSONValue Result Result // contains filtered or unexported fields }
CollectionItem is a document snapshot owned by a CollectionClient. Mutate Doc, then CreatePatchFromChanges (or CreatePatch with hand-built ops). OriginalDoc is an independently decoded copy of the content at read time; the private original ojson baseline is what patch creation diffs against.
type CollectionPatch ¶
CollectionPatch is a schema-checked patch ready to send for one document. ID and Version come from the item used to create it.
func (CollectionPatch[T]) ID ¶
func (p CollectionPatch[T]) ID() string
ID returns the document id the patch targets.
func (CollectionPatch[T]) Version ¶
func (p CollectionPatch[T]) Version() string
Version returns the optimistic concurrency version (#) the patch targets.
type CollectionRef ¶
CollectionRef identifies a collection and expected schema version for Establish catalog validation. Collection[T] implements this interface.
type Config ¶
type Config struct {
// EstablishmentURL is the base URL of the establishment server
// (scheme + host[:port], no path). Required.
EstablishmentURL string
// Token is a static bearer token. Ignored if TokenSource is set.
Token string
// TokenSource provides tokens dynamically.
TokenSource TokenSource
// HTTPClient overrides the default HTTP client.
HTTPClient *http.Client
// BaseURLRewrite maps establishment server baseURLs (or server names)
// to host-reachable base URLs. Useful for Docker Compose from the host.
// Keys may be Docker URLs ("http://server1:8080") or server names ("server1").
BaseURLRewrite map[string]string
// PreferServer, when dual-role eligible, is preferred for local routing.
PreferServer string
// WrongMachineRetries bounds wrongMachine bounce loops (default 3).
WrongMachineRetries int
// TransportRetries bounds retries on transport failures (default 0).
TransportRetries int
// CreateAmbiguousVerifyDelay is how long to wait before a follow-up read
// when create fails with a transport error (response may have been lost
// after a successful commit). Zero means the default (3s). Negative
// disables the follow-up read.
CreateAmbiguousVerifyDelay time.Duration
// UserAgent sets the User-Agent header.
UserAgent string
}
Config configures a Client.
type Establishment ¶
type Establishment struct {
General GeneralConfig
Servers map[string]ServerEntry
ShardMap map[string]ShardAssignment
Schemas map[string]SchemaEntry
Searches ojson.JSONValue
Auth ojson.JSONValue
// Env is the full establish envelope object (ordered).
Env ojson.JSONValue
}
Establishment is the cached establish document (without the ok envelope).
func (*Establishment) AssignmentForSlot ¶
func (e *Establishment) AssignmentForSlot(slot byte) (ShardAssignment, bool)
AssignmentForSlot returns the shard assignment covering slot.
func (*Establishment) ServerBaseURL ¶
func (e *Establishment) ServerBaseURL(name string) string
ServerBaseURL returns the configured base URL for a server name.
type GeneralConfig ¶
type GeneralConfig struct {
Name string `json:"name"`
EstablishmentServer string `json:"establishmentServer"`
Version int `json:"version"`
ReadMemberCheckinSeconds int `json:"readMemberCheckinSeconds"`
CacheUpdateCheckinSeconds int `json:"cacheUpdateCheckinSeconds"`
ReadMemberFailedCheckinsBeforeStale int `json:"readMemberFailedCheckinsBeforeStale"`
}
GeneralConfig is the establishment general block.
type ReadOptions ¶
ReadOptions controls optional read-scope fields.
type ReadResult ¶
type ReadResult struct {
Result Result
Collection string
ID string
SOT ojson.JSONValue
ExtraFields ojson.JSONValue
CacheSummaries ojson.JSONValue
}
ReadResult is a successful read summary.
func (ReadResult) SummariesForArrayField ¶
func (rr ReadResult) SummariesForArrayField(arrayField string) ([]ojson.JSONValue, error)
SummariesForArrayField returns cache summary objects for @@ refs stored in sot[arrayField], in array order. Missing or unresolved summaries are skipped.
type Result ¶
type Result struct {
OK bool
Errors []APIError
// Env is the full response object parsed with ojson (ordered).
Env ojson.JSONValue
// Body is the original response bytes.
Body []byte
}
Result is a decoded DatoriumDB response envelope.
func DecodeResult ¶
DecodeResult parses a JSON envelope body with ojson.
func (Result) FirstErrorCode ¶
FirstErrorCode returns the first application error code, or "".
func (Result) StringField ¶
StringField returns a top-level string (or stringified number) field.
type SchemaEntry ¶
type SchemaEntry struct {
Version int
// Doc is the ordered schema object (ojson). Never round-trip via map[string]any.
Doc ojson.JSONValue
}
SchemaEntry is one collection schema from establish.
type SearchResult ¶
SearchResult is a successful search response.
type ServerEntry ¶
type ServerEntry struct {
BaseURL string `json:"baseURL"`
}
ServerEntry is one establishment servers map entry.
type ShardAssignment ¶
type ShardAssignment struct {
ShardSOTMember string `json:"SHARD_SOT_MEMBER"`
ShardReadMember []string `json:"SHARD_READ_MEMBER"`
ProxyReadMember []string `json:"PROXY_READ_MEMBER"`
}
ShardAssignment is one shard-map range assignment.
type StaticToken ¶
type StaticToken string
StaticToken is a TokenSource that always returns the same token.
type TokenSource ¶
TokenSource supplies a bearer token (without the "Bearer " prefix).
type TransportError ¶
TransportError wraps non-application HTTP/transport failures.
func (*TransportError) Error ¶
func (e *TransportError) Error() string
func (*TransportError) Unwrap ¶
func (e *TransportError) Unwrap() error
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
mint-token
command
Command mint-token issues a development-only client JWT for integration tests.
|
Command mint-token issues a development-only client JWT for integration tests. |
|
todo-integration
command
Command todo-integration exercises the smart client against a live two-shard Todo establishment started by start_integration_test.sh.
|
Command todo-integration exercises the smart client against a live two-shard Todo establishment started by start_integration_test.sh. |
|
internal
|
|
|
testtoken
Package testtoken mints development-only EdDSA client JWTs matching DatoriumDB fixture __auth.json + signing key material.
|
Package testtoken mints development-only EdDSA client JWTs matching DatoriumDB fixture __auth.json + signing key material. |
|
Package refs parses DatoriumDB document reference strings.
|
Package refs parses DatoriumDB document reference strings. |
|
Package searchpath encodes precompiled search result path segments and computes their shard slots, matching DatoriumDB SEARCHING.md.
|
Package searchpath encodes precompiled search result path segments and computes their shard slots, matching DatoriumDB SEARCHING.md. |
|
Package shard ports DatoriumDB document sharding helpers (CRC32 of the sharding prefix → 8-bit slot).
|
Package shard ports DatoriumDB document sharding helpers (CRC32 of the sharding prefix → 8-bit slot). |