Maryk IndexedDB Store
Persistent browser store for Maryk JS and WasmJS apps.
Targets:
- JS browser
- WasmJS browser
The store uses real IndexedDB object stores, keys, key ranges, transactions, and cursor scans. It does not execute requests by loading data into InMemoryDataStore.
Open the store with the data models used by the app:
suspend fun openStore() = IndexedDbDataStore.open( databaseName = "my-maryk-store", dataModelsById = mapOf(1u to Person), keepAllVersions = true, keepUpdateHistoryIndex = true,)Enable history only when the app needs toVersion, getChanges, scanChanges, or scanUpdateHistory semantics. History adds extra IndexedDB rows for snapshots, indexes, uniques, changes, and update-history scans.
Documentation
Section titled “Documentation”Main Capabilities
Section titled “Main Capabilities”- Current
add,change,delete,get,scan,getUpdates,scanUpdates. - Table scans over IndexedDB key cursors.
- Index scans over Maryk-encoded secondary index rows.
- Unique lookups over direct IndexedDB gets.
- Historic
toVersionget/table/index/unique reads whenkeepAllVersionsis enabled. getChanges,scanChanges, andscanUpdateHistoryover durable history rows.- Sensitive value encryption through the shared Maryk field encryption provider API.
- Browser-native WebCrypto AES-GCM/HMAC-SHA256 provider for JS and WasmJS.
- Metadata-backed startup migration with safe-add handling, index backfill, and
persisted
Partial/Retryresume state across database reopens. - JS and WasmJS test coverage through
fake-indexeddb.
Important Limits
Section titled “Important Limits”- IndexedDB transactions cannot safely wrap the whole suspend common request processor. Mutations are serialized with Web Locks when available, then written through native batched
readwritetransactions. - Without Web Locks, mutations use a renewable lease stored atomically in IndexedDB.
BroadcastChannelwakes waiting tabs promptly; timed retries cover browsers without it. Every write batch checks the lease in its native transaction, fencing out expired owners. - A migration returning
Partialpauses the open after persisting phase, attempt, cursor, versions, and message. The next open resumes that phase throughMigrationContext.previousState. - Historic index scans process IndexedDB cursor pages, but still keep latest visible state per indexed row to handle historic tombstones correctly.
- Browser quota, eviction, private browsing behavior, and blocked upgrades are browser operational concerns.
Focused checks:
./gradlew :store:indexeddb:jsNodeTest./gradlew :store:indexeddb:wasmJsNodeTestBrowser checks when available:
./gradlew :store:indexeddb:jsBrowserTest./gradlew :store:indexeddb:wasmJsBrowserTest