Optional ReadonlyGetPresent only when the inner provider has it: LocalCacheManager chooses its lookup path by
whether the method exists, so the wrapper must not add one the real provider lacks.
Optional ReadonlyReleasePresent only when the inner provider has it, for the same reason as GetIndexGroupKeys.
Optional ReadonlyTryPresent only when the inner provider has it, for the same reason as GetIndexGroupKeys.
Optional ReadonlyWithPresent only when the inner provider has it, for the same reason as GetIndexGroupKeys.
Delegated, like SharesReferences: sharing is a property of the inner store.
Delegated — this wrapper only counts calls; the isolation semantics are entirely the inner provider's. See ILocalStorageProvider.SharesReferences.
undefined passes through deliberately: if the inner provider does not declare its
semantics, this wrapper must not invent them either, and LocalCacheManager's probe then
measures straight through these delegating methods into the real store.
Delegated for the same reason as SharesReferences: this wrapper stores nothing of its own, so whether what it holds outlives the process is a property of the inner store. See ILocalStorageProvider.SupportsCrossProcessPersistence.
Clears all items in a specific category. If no category is specified, clears the default category only.
The category to clear
Gets all keys in a specific category.
The category to list keys from
Per-category counters — IMPORTANT for assertions: LocalCacheManager also persists its registry index asynchronously (a different category), so tests about RunView cache traffic must scope to the 'RunViewCache' category rather than the global counters.
Retrieves a value from storage. The implementation is responsible for any deserialization required by the underlying medium:
Returns null for missing keys or corrupt entries.
Expected type of the stored value. Caller-controlled — the provider does
not validate the runtime shape against this type. Falls back to unknown.
The key to retrieve
Optionalcategory: stringOptional category for key isolation (e.g., 'RunViewCache', 'Metadata')
Batched retrieval — reads N values for N keys in one logical operation.
Returns a Map keyed by the input key strings. Missing keys map to null.
The map preserves the original key set so callers can index by key without
relying on array-position alignment.
Why batch? IndexedDB serializes transactions on the same object store —
Promise.all([...N GetItem calls]) looks parallel but pays per-transaction
setup cost (~3–10ms each) for every key. A single transaction with N
get() calls amortizes that overhead. Redis can use MGET/pipelines.
In-memory implementations have no real win but implement consistently for
a uniform API.
Implementations are free to fall back to per-key reads internally if the
underlying medium doesn't support batching — the contract is just "read
all of these as efficiently as you can". An empty keys array returns
an empty map without touching the storage backend.
Expected type of all stored values. Caller-controlled.
The keys to retrieve. Duplicates are deduplicated; the returned map has one entry per unique key.
Optionalcategory: stringOptional category for key isolation (applies to all keys)
Removes an item from storage.
The key to remove
Optionalcategory: stringOptional category for key isolation
Writes to one key since the last ResetCounts. Use it to assert how often a single cache slot was rewritten when other slots in the same category may be written meanwhile.
Stores a value. Callers should pass plain data (objects/arrays/primitives/Date/etc). Implementations handle any serialization required by the medium:
Class instances lose their prototype on retrieval — store the underlying data
(e.g. via entity.GetAll()) and reconstruct on read if needed.
Type of the value being stored. Caller-controlled.
The key to store under
The value to store
Optionalcategory: stringOptional category for key isolation
Optionaloptions: LocalStorageWriteOptionsOptional expiry and index hints; a provider ignores what it cannot honour.
Wraps any ILocalStorageProvider with call counters so tests can prove cache behavior from the outside: a cache WRITE shows up as SetItemCount++, a cache READ as GetItemCount/GetItemsCount++, and "served without touching storage" (e.g. a dedup/linger hit) as no counter movement at all.