Zum Inhalt springen
Deutsch

InMemoryCache

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Defined in: src/cache/InMemoryCache.ts:41

In-process Cache backed by a Map with LRU eviction and per-entry TTL.

Bounded by maxEntries (default 10 000): inserting a new key beyond the cap evicts the least-recently-used entry, so a flood of distinct keys — e.g. attacker-chosen Idempotency-Key or rate-limit keys — cannot grow the map without limit (security audit HTTP-2). Set maxEntries: Infinity to opt out (unbounded — OOMs eventually; only do this when you control the key space).

Expiry has two paths: lazy (checked on every get/incr/setIfAbsent/ mget) and an optional periodic sweep every cleanupMs (default 60 000) that reclaims expired-but-never-re-read entries. Set cleanupMs to 0 / Infinity to disable the background sweep.

Configure via an InMemoryCacheOptions builder or plain object; through the CacheExtension the same fields resolve from the HOCON path actor-ts.cache.in-memory instead. Out-of-range values throw OptionsError.

Suitable for tests, single-process dev servers, and as a per-process front-end to a slower remote cache. Not suitable for multi-process coordination (use RedisCache for that).

new InMemoryCache(options?): InMemoryCache

Defined in: src/cache/InMemoryCache.ts:46

InMemoryCacheOptions = {}

InMemoryCache

close(): Promise<void>

Defined in: src/cache/InMemoryCache.ts:137

Best-effort teardown. Idempotent.

Promise<void>

Cache.close


delete(…keys): Promise<void>

Defined in: src/cache/InMemoryCache.ts:108

Delete one or many keys. Idempotent — missing keys are a no-op.

string[]

Promise<void>

Cache.delete


get<V>(key): Promise<Option<V>>

Defined in: src/cache/InMemoryCache.ts:59

Get a value; returns None on miss, expiry, or transient backend failure.

V

string

Promise<Option<V>>

Cache.get


incr(key, ttlMs?): Promise<number>

Defined in: src/cache/InMemoryCache.ts:77

Atomic increment by 1 — returns the new value. When ttlMs is supplied AND the key was newly created (counter value is 1 after the call), the TTL is set; subsequent increments do not refresh it. This is the right semantics for a fixed-window rate-limiter.

string

number

Promise<number>

Cache.incr


mget<V>(keys): Promise<Map<string, V>>

Defined in: src/cache/InMemoryCache.ts:112

Bulk get (#14) — fetch multiple keys in a single round-trip when the backend supports it. Returns a Map keyed by the input keys; misses (no entry, expired, malformed payload, transient backend failure) are simply absent from the result rather than mapped to undefined. Map.get(k) therefore returns V | undefined with the same “missing key” semantics as the single-key get.

Order of the returned Map matches the order of the input keys for backends that support it (Redis MGET); backends that fall back to parallel single-key reads (Memcached) may surface a different iteration order — don’t rely on it.

V

readonly string[]

Promise<Map<string, V>>

Cache.mget


mset<V>(entries, ttlMs?): Promise<void>

Defined in: src/cache/InMemoryCache.ts:128

Bulk set (#14) — write multiple key/value pairs with a shared TTL. The atomicity guarantee is per backend: Redis emits a single MSET (no-TTL) or pipelined SET ... PX (with-TTL); Memcached has no native bulk write so the calls go out in parallel. Single-process backends (InMemory) trivially see the whole bag at once. ttlMs applies to every entry.

V

ReadonlyMap<string, V>

number

Promise<void>

Cache.mset


set<V>(key, value, ttlMs?): Promise<void>

Defined in: src/cache/InMemoryCache.ts:70

Set a value with optional TTL (milliseconds). Omitting ttlMs means no expiry.

V

string

V

number

Promise<void>

Cache.set


setIfAbsent<V>(key, value, ttlMs?): Promise<boolean>

Defined in: src/cache/InMemoryCache.ts:97

Set only if the key does not yet exist. Returns true on success (the value was stored), false on collision (someone else got there first). Used as the kernel of idempotency-key dedup.

Atomicity is a hard guarantee, not best effort. Every backend maps this onto a single native compare-and-set primitive — Redis SET … NX, Memcached ADD, and a Map read/write pair that the single-threaded event loop cannot interleave. No backend may implement it as get-then-set: that pair has a window in which two callers both observe the key absent and both write, and every caller of this method is relying on exactly one of them winning. Contention is therefore safe by construction — with N concurrent callers, precisely one sees true.

The atomicity is per key on one server. It does not survive a Memcached cluster whose topology changes mid-flight, where a key can be rehashed onto a server that has never seen it (see the Memcached page); nor does it coordinate across Redis instances that are not the same logical keyspace.

ttlMs is applied only on the write that wins — a losing call leaves the incumbent entry’s expiry untouched, so a retry loop can never extend someone else’s hold. Sub-second precision is backend-dependent: Memcached’s protocol is second-granular and rounds up, with a 1 s floor.

Pass a ttlMs whenever this is used as a lock. The pair “acquire, then release by deleting” has no owner-side recovery: if the holder crashes, is paused past its deadline, or loses the network before it deletes the key, nothing else will ever remove that entry. Without a TTL the lock is wedged until an operator intervenes; with one, the TTL is the recovery mechanism and its length is the maximum stall. See acquireLock in CacheLock.ts for a helper that wraps this in a token-checked release, so a holder whose TTL already lapsed cannot free the next owner’s lock.

V

string

V

number

Promise<boolean>

Cache.setIfAbsent


sizeForTest(): number

Defined in: src/cache/InMemoryCache.ts:146

Test hook — current entry count, including expired-but-not-cleaned entries.

number