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
| Op | Meaning |
|---|---|
(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
| Store | Host | Namespace / ctor |
|---|---|---|
| mem | all | (store/mem-store) |
| layered | all | (store/layered-store [fast … durable]) — read-through, write-through |
| LRU | all | (dacite.store.lru/lru-store n) |
| file | JVM, babashka | (dacite.store.file/file-store path) — {base}/aa/bb/{hex}.edn |
| file | nbb | (dacite.store.nbb/file-store path) |
| LMDB | JVM | (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:
| Op | Role |
|---|---|
(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)
| Module | Role |
|---|---|
dacite.store.client-cache | Local mem + flush reachable on CAS / explicit flush |
dacite.store.pack | Soft budget packing, flush-from!, apply-chunk!, literals |
dacite.store.rate-limit | Throttle send path (outermost IChunkTransport wins). Server inbound admit is dacite.service.throttle (429), not this wrapper. |
dacite.store.stats | Bandwidth accounting for store-protocol bodies |
dacite.store.remote | JVM HTTP client (:binary true default for packs); watch-root is GET /events |
dacite.store.browser | Browser 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
| Context | Format |
|---|---|
Pack chunk GET /node/{hex} | wire-v1 chunk (application/vnd.dacite.chunk.v1) |
Pack chunk POST /nodes | wire-v1 chunk |
Novelty PUT body, /root, CAS | EDN |
| LMDB content values | wire-v1 node payload only (no chunk/literal framing) |
| File store on disk | EDN (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