IndexedDB Store Architecture
The IndexedDB store maps Maryk’s ordered key-value storage model to browser-native IndexedDB primitives.
Layers
Section titled “Layers”IndexedDbDataStore
- Implements the Maryk datastore request surface.
- Reuses shared request/update logic where possible.
- Encodes Maryk keys, qualifiers, values, history rows, index rows, and unique rows.
- Chooses table, index, unique, history, or update-history paths per request.
IndexedDbByteStore
- Small common byte-store interface.
- Provides
get,put,delete,scan, andwriteBatch. - Platform implementations live in
jsMainandwasmJsMain. - Tests inject
fake-indexeddb; browser apps use the real browser IndexedDB implementation.
IndexedDbScanBatches
- Pages cursor scans in bounded batches.
- Lets Maryk request limits count matched rows after soft-delete/filter skips.
- Avoids full native range materialization for table/current-index/historic-index paths.
Native IndexedDB Use
Section titled “Native IndexedDB Use”The store uses:
- object stores per Maryk model/family;
IDBKeyRangebounds for start/end keys;- forward and reverse cursors;
- direct object-store
getfor key and unique fast paths; - native
readwritetransactions for write batches.
Keys are stored as numeric arrays because IndexedDB array-key ordering preserves Maryk bytewise ordering. JS values are stored as Int8Array to avoid boxed value arrays.
Mutation Consistency
Section titled “Mutation Consistency”The common Maryk processor suspends between validation, reads, scans, and write planning. Browser IndexedDB transactions become inactive when request queueing pauses across tasks, so the whole logical request is not wrapped in one native transaction.
Instead:
- mutation requests run under an exclusive Web Locks API lock when available;
- browsers without Web Locks use a renewable per-database lease stored atomically in IndexedDB;
- lease release notifications use
BroadcastChannel, with timed retries as a compatibility fallback; - fallback write batches verify the lease in the same native transaction, so an expired owner cannot commit;
- final writes are committed with one native IndexedDB
readwritebatch transaction.
This gives good browser behavior without pretending IndexedDB transactions are long-lived coroutine scopes.
Versioning
Section titled “Versioning”open creates or upgrades all required object stores for the configured models and options. Existing connections close on versionchange, and blocked opens fail clearly instead of hanging.
The meta object store records:
- storage schema version;
- history options;
- model signatures;
- encoded model definitions;
- versioned per-model migration state. A
Runningmarker is stored before each handler call; its phase, attempt, cursor, andPartial/Retry/fatal outcome diagnostics survive reopen. Successful completion removes the state.
Relationship To Other Stores
Section titled “Relationship To Other Stores”IndexedDB follows the same Maryk request semantics as RocksDB/FoundationDB where browser constraints allow it:
- current table/index/unique scans are native cursor scans;
- historic reads use stored snapshots and historic secondary rows;
- update-history scans use an inverted version index when enabled;
- live flow listener state remains in memory, as in the other stores, while initial/refill reads come from IndexedDB.