Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Stores API reference (0.1 alpha)

Practical API for content stores and client composition in the reference implementation. App wiring: Anatomy and Same domain, local or HTTP. Internals: Content Stores, Rooted Stores.

IStore protocol

Namespace: dacite.store

OpMeaning
(s-get st h)Node at hash, or nil
(s-put st h value)Store entry; returns store
(s-has? st h)Presence
(s-delete st h)Remove entry
(s-snapshot st)Bulk map of contents (implementation-defined keys)
(s-merge st m)Merge map of hash→value
(s-reset st)Clear

Hashes are 4-word vectors ([w0 w1 w2 w3]). Helpers:

(store/hash->hex h)
(store/hex->hash "…64 hex chars…")

Dynamic binding:

store/*store*          ; current store
(store/with-store [st (store/mem-store)] …)
(store/set-store! st)
(store/reset-store!)

Built-in stores

StoreHostNamespace / ctor
memall(store/mem-store)
layeredall(store/layered-store [fast … durable]) — read-through, write-through
LRUall(dacite.store.lru/lru-store n)
fileJVM, babashka(dacite.store.file/file-store path){base}/aa/bb/{hex}.edn
filenbb(dacite.store.nbb/file-store path)
LMDBJVM(dacite.store.jvm/lmdb-store path) — content values = wire-v1 node payload only; keys = 32-byte hash; root meta = 32-byte hash

Rooted stores

A content store holds immutable nodes. A root cell holds one mutable root hash for application state (compare-and-set, watches, GC). Hash-level ops are re-exported on dacite.store:

OpRole
(store/rooted-store content)Wrap content with ephemeral root
(store/rooted-store content cell)Wrap with durable root cell
(store/file-root-cell path)Hex in {base}/ROOT
(store/root rs) / (store/cas-root! …) / (store/set-root! …)Hash-level root
(store/remote-rooted-store url)HTTP content + server root (IRoot; JVM)
(store/collect-garbage! rs)Drop unreachable content
(store/sync-reachable! src dest root-h)Copy the reachable subgraph (pack flush to remotes)

Application value code should wrap the rooted store once and work with values, not hashes:

;; local file
(def r (v/root-ref (store/rooted-store (store/file-store path)
                                       (store/file-root-cell path))))

;; same value API over HTTP (JVM)
(def r (v/root-ref (store/remote-rooted-store "http://127.0.0.1:8080")))

(v/ref-swap! r domain-update)

set-root! / ref-reset! throw on a remote rooted store. Seed with ref-cas! from nil; update with ref-swap!.

See Values — root reference and Rooted Stores chapter.

Host ctors on dacite.store (JVM): (store/file-store path), (store/lmdb-store path), (store/lmdb-root-cell lmdb). On nbb, use (dacite.store.nbb/file-store path) (SCI cannot re-export circular host backends cleanly). Optional nbb LMDB (same data.mdb layout as JVM, wire-v1 nodes): (dacite.store.nbb.lmdb/lmdb-store path) after LMDB_DATA_V1=true npm rebuild lmdb (prebuilt lmdb is format v2 and will not open a lmdbjava env).


Client composition (remote / sync)

Interactive clients usually stack:

application Values
    ↓
write-back cache     (dacite.store.client-cache/wrap … :write-back)
    ↓
pack / chunk transport   (IChunkTransport + pack/flush-from!)
    ↓
optional rate-limit      (dacite.store.rate-limit)
    ↓
remote HTTP store        (dacite.store.remote | dacite.store.browser)
ModuleRole
dacite.store.client-cacheLocal mem + flush reachable on CAS / explicit flush
dacite.store.packSoft budget packing, flush-from!, apply-chunk!, literals
dacite.store.rate-limitThrottle send path (outermost IChunkTransport wins). Server inbound admit is dacite.service.throttle (429), not this wrapper.
dacite.store.statsBandwidth accounting for store-protocol bodies
dacite.store.remoteJVM HTTP client (:binary true default for packs); watch-root is GET /events
dacite.store.browserBrowser sync XHR demo client (:binary true default)

pack/flush-from! finds the outermost IChunkTransport and sends budgeted chunks (default soft budget 1024 bytes).


Wire: EDN vs wire-v1

ContextFormat
Pack chunk GET /node/{hex}wire-v1 chunk (application/vnd.dacite.chunk.v1)
Pack chunk POST /nodeswire-v1 chunk
Novelty PUT body, /root, CASEDN
LMDB content valueswire-v1 node payload only (no chunk/literal framing)
File store on diskEDN (host-local; not multi-lang interop)
  • Spec: wire-v1 (repo) / book Serialization appendix
  • Codec: dacite.wire.binary (portable .cljc — JVM + CLJS/nbb)
  • EDN helpers: dacite.wire (read-edn / write-edn)
  • Opt out: {:binary false} on remote/browser store constructors

Service dual-stack: dacite.service honors Content-Type / Accept.


Alpha quality notes

  • HTTP service and remotes are experimental but usable for demos and tests
  • Browser remote is sync XHR (main-thread blocking) — not production networking
  • APIs may change before 1.0; see CHANGELOG