Recoverable Local Store
Problem
Design RecoverableLocalStore to serve string key-value reads from memory while preserving every completed write through an injected DurableStorage. A new store constructed with retained durable data must rebuild the same completed state. All calls are sequential.
Requirements
- Read current values.
getreturns the current string value for a key, including an empty string, ornullwhen the key has never been successfully written. - Complete durable writes.
putreplaces any prior value, returns only afterDurableStorageatomically commits the pair, and makes the new value immediately visible toget. - Recover completed data. Construction loads the complete durable snapshot, so a fresh store returns the latest value for every completed write represented in that snapshot.
API
| Signature | Returns | Behavior |
|---|---|---|
RecoverableLocalStore(storage: DurableStorage) | Not applicable | Loads storage.loadAll() as the initial in-memory mapping. Raises InvalidArgumentError for null storage. |
put(key: string, value: string) | void | Durably and visibly replaces the key's value. Raises InvalidArgumentError for an empty key or null value before changing local or durable state. |
get(key: string) | string or null | Returns the current value or null when absent. Raises InvalidArgumentError for an empty key. |
DurableStorage is a provided collaborator with loadAll() -> object<string, string> and write(key: string, value: string) -> void. Its contents outlive local-store objects. loadAll returns a copy of all completed pairs, and write atomically replaces one pair before returning. Implement RecoverableLocalStore, not the storage collaborator.
Examples
| Step | Operation | Result |
|---|---|---|
| 1 | Construct with empty durable storage. | The local store is empty. |
| 2 | put("mode", "draft") | get("mode") returns "draft"; durable storage contains the same pair. |
| 3 | put("mode", "ready") | get("mode") returns "ready"; the durable value is replaced. |
| 4 | get("missing") | Returns null. |
| 5 | Construct a fresh store from retained {"mode":"ready","region":"west"}. | Reads return "ready" and "west". |
Constraints
- Keys are nonempty strings containing at most 200 Unicode scalar values.
- Values are non-null strings, may be empty, and contain at most 10,000 Unicode scalar values.
- At most 10,000 distinct keys and 100,000 method calls occur per testcase.
- Durable snapshots contain only valid keys and non-null string values.
- One active store owns its provided storage, which changes only through that store.
Notes
A simulated crash or reboot is represented by constructing a testcase's single store from a retained durable snapshot containing only completed writes. Storage failures, deletion, checkpoints, logs, replay, public restart operations, and concurrent calls are out of scope.