Agoric Cache
This cache mechanism allows a cache client function to synchronize with a cache
backend. Any passable object can be a cache key or a cache value.
Demo
import { makeCache, makeScalarStoreCoordinator } from '@agoric/cache';
import { M } from '@agoric/store';
import { makeScalarBigMapStore } from '@agoric/vat-data';
const store = makeScalarBigMapStore('cache');
const coordinator = makeScalarStoreCoordinator(store);
const cache = makeCache(coordinator);
await cache('baz');
await cache('baz', 'barbosa');
await cache('baz', 'babaloo', undefined);
await cache('baz', 'babaloo', 'barbosa');
await cache('frotz', 'default');
await cache('frotz', 'ignored');
await cache('foo');
const updater = (oldValue = 'bar') => `${oldValue}1`;
await cache('foo', updater, M.any());
await cache('foo', updater, M.any());
await cache('foo');
await cache('foo', updater, 'nomatch');
await cache('foo', updater, 'bar11');
await cache('foo', updater, 'bar11');
await cache('foo');
Cache client
The client-side API is normally exposed as a single function named cache. You
can create a cache client function by running makeCache(coordinator, follower). If not specified, the default coordinator is just a local in-memory
map without persistence.
- the ground state for a cache key value is
undefined. It is impossible to distinguish a set value of undefined from an unset key
cache(key, (oldValue) => ERef<newValue>, guardPattern?): Promise<newValue> -
transactionally updates the value of key from a value matched by guardPattern
to the results of sanitizing the result of calling the updater function with
that value. Retries all three steps (read current value, attempt match, call updater),
if the transaction is stale. guardPattern defaults to matching only undefined.
Returns the current value after any resulting update.
cache(key, passable, guardPattern?): Promise<newValue> -
same as above with an updater function that ignores arguments and returns
passable (e.g., () => passable).
Cache coordinator
The cache coordinator must implement the Coordinator interface, which supports
eventual consistency with optimistic updates:
interface Updater {
update: (oldValue: Passable) => unknown
}
interface Coordinator {
getRecentValue: (key: Passable) => Promise<Passable>,
setCacheValue: (key: Passable, newValue: Passable, guardPattern: Pattern) => Promise<Passable>,
updateCacheValue: (key: Passable, updater: ERef<Updater>, assertedMatch: Matcher) => Promise<Passable>,
}