AniLink - v3.0.0
    Preparing search index...

    Class ResponseCache

    An in-memory TTL response cache with an LRU eviction cap.

    The cache is per-instance (one per AniLink client when enabled) so cache state never leaks across clients. Entries expire after ttlMs and the cache is capped at maxEntries with least-recently-used eviction.

    Aliasing: values returned from ResponseCache.get are deep clones of the cached entry, so a caller that mutates the returned object cannot corrupt the cached copy or affect subsequent reads. Consumers that treat cached responses as immutable can disable the read-side clone with cloneOnRead: false (see ResponseCacheOptions.cloneOnRead); the write-side clone in ResponseCache.set still keeps the cache from aliasing the caller's object.

    Invalidation: entries expire after ttlMs, and a successful non-GET request dispatched through the same transport automatically invalidates the cached reads of what it mutated: REST writes drop the mutated resource's cached GET entries (see ResponseCache.deleteMatching) and GraphQL mutation documents drop every cached query at the endpoint (see ResponseCache.deleteAllForUrl), so a read-after-write sequence refetches instead of serving the pre-mutation entry. A read whose network response was in flight when an invalidation affecting it landed does not re-cache its stale response (see ResponseCache.setIfFresh). Use ResponseCache.delete for exact-key invalidation or ResponseCache.clear to drop everything.

    Observability: ResponseCache.stats returns a frozen snapshot of the live entry count and the lifetime hit/miss/expiration/eviction counters, so tuning can distinguish a too-small cache (rising evictions) from a too-short TTL (rising expirations).

    Privacy: the cache stores the full response body of every GET request when enabled, including authenticated user-scoped responses (for example /Viewer-style queries that return the user's profile or email). Cached bodies are retained in plaintext in the JS heap for up to ttlMs and are accessible to any code holding a reference to the ResponseCache instance. Entries are scoped by a SHA-256 hash of the bearer token so cached responses never cross identities, but within one identity sensitive payloads are retained verbatim. Do not enable the cache for clients that fetch private user data unless ttlMs is short and the cache instance is not shared across trust boundaries.

    Index
    • Removes the cached entry for the given request, if present. Use this for targeted invalidation after a mutation that changes the resource (for example a POST that updates the entity a cached GET returned). Only cacheable reads are tracked, GET requests and GraphQL query documents dispatched as POST, so other methods are a no-op and return false.

      Parameters

      • method: string

        The HTTP method.

      • url: string

        The request URL.

      • Optionaldata: string | object

        The request body, when present.

      • OptionalauthKey: string

        An authentication-safe credential identity, so cached responses never cross bearer-token identities.

      Returns boolean

      true when an entry was removed, false when it was absent or the method is not cached.

    • Removes every cached read keyed at the given URL, GET entries and GraphQL query POST entries alike, across query strings, documents, variables, and auth namespaces, and returns how many entries were removed.

      This is the invalidation path for GraphQL writes: every GraphQL operation of one provider is keyed at the same endpoint URL, and a mutation document can change what many different query documents return (a SaveMediaListEntry changes what both a MediaList and a MediaListCollection query report), so no finer-grained prefix than the endpoint can be derived. Dropping the endpoint's cached queries is conservative: the next reads refetch fresh data instead of serving pre-mutation entries for the rest of the TTL.

      Parameters

      • url: string

        The request URL whose cached reads should be dropped; its query string and fragment are ignored.

      Returns number

      The number of cached entries removed.

    • Removes every cached GET entry whose URL starts with urlPrefix at a path-segment boundary, and returns how many entries were removed.

      The prefix is matched against the canonicalized URL with its query string and fragment stripped, so a cached read of https://host/anime/21?fields=... is invalidated by the prefix https://host/anime/21. The match is boundary-aware: the prefix https://host/anime/21 does not match https://host/anime/212. The cached URL must be either exactly the prefix, continue with / (a child path), ? (a query string), or # (a fragment). Matching spans every auth namespace, because a mutation performed by one identity changes the underlying resource for every identity that can read it.

      This is the invalidation path used by mutation-triggered cache invalidation for REST writes: after a successful write, the transport derives the mutated resource's base URL and drops every cached read of that resource. It is also usable directly for manual bulk invalidation. GraphQL mutation documents invalidate through ResponseCache.deleteAllForUrl instead: their cached reads are keyed at the endpoint URL, which no resource prefix can name.

      Parameters

      • urlPrefix: string

        The resource base URL whose cached reads should be dropped; query strings and fragments on the prefix are ignored.

      Returns number

      The number of cached entries removed.

    • Removes every cached GraphQL query POST entry at the given URL whose document selects one of the given root fields, and returns how many entries were removed.

      This is the scoped invalidation path for mapped GraphQL mutations (see invalidateAfterMutation): a mutation whose root field is known to affect only certain query root fields drops exactly those cached queries, leaving unrelated root fields' entries warm, instead of the whole-endpoint sweep deleteAllForUrl performs. The match is against the document's single selected root field, recorded on the entry at write time (see CacheEntry.rootField), so a query document is attributed to the root field it selects, not to every field it mentions. Entries whose document could not be attributed to a single root field (fragment-spread roots, multi-field selections) are dropped too, fail-closed like the unmapped-mutation fallback, because such a document may select data the affected-field match cannot see.

      Parameters

      • url: string

        The request URL whose cached reads should be considered; its query string and fragment are ignored.

      • rootFields: readonly string[]

        The query root fields whose cached entries should be dropped.

      Returns number

      The number of cached entries removed.

    • Reads a cached response for the given request, or undefined when the entry is absent or expired. Expired entries are evicted on read. By default the returned value is a deep clone of the cached entry, so a caller that mutates it cannot corrupt the cached copy or affect subsequent reads; with cloneOnRead: false the cached object itself is returned and callers must treat it as immutable.

      Type Parameters

      • T

      Parameters

      • method: string

        The HTTP method.

      • url: string

        The request URL.

      • Optionaldata: string | object

        The request body, when present.

      • OptionalauthKey: string

        An authentication-safe credential identity, so cached responses never cross bearer-token identities.

      Returns T | undefined

      A deep clone of the cached response body (or the cached object itself when cloneOnRead is disabled), or undefined.

    • Returns the current invalidation generation, for callers that need to detect an invalidation landing between a cache-miss read and its write-back (see setIfFresh). The counter is global, but the check in setIfFresh is scoped: only invalidations affecting the read's own key drop its write-back.

      Returns number

      The current generation counter value.

    • Stores a response in the cache, evicting the LRU entry when the cap is is reached. Only cacheable reads are stored, GET requests and GraphQL query documents dispatched as POST; mutations and other methods are no-ops. The value is deep-copied on write; the cache never aliases the caller's object.

      Note for direct callers: a POST body shaped like { query: "..." } is treated as a GraphQL document and cached when the document declares a read. Do not use set for REST POST writes whose body only carries a query field: the transport excludes those via its protocol flag, but set itself cannot distinguish them.

      Type Parameters

      • T

      Parameters

      • method: string

        The HTTP method.

      • url: string

        The request URL.

      • data: string | object | undefined

        The request body, when present.

      • authKey: string | undefined

        An authentication-safe credential identity, so cached responses never cross bearer-token identities.

      • response: T

        The response body to cache.

      Returns void

    • Stores a response only when no invalidation affecting the request has landed since the caller captured the generation, the write-back half of the in-flight-read guard.

      The transport captures the generation right after a cache miss (before the network read starts) and hands it here on success. When a mutation invalidates the cache while that read is in flight, the generation has moved on and the stale response is dropped instead of re-cached, closing the read-after-write race a plain ResponseCache.set would reintroduce. The check is scoped to the request's own key: an invalidation of a different resource does not drop this write-back, so concurrent reads of unaffected resources keep filling the cache.

      Type Parameters

      • T

      Parameters

      • method: string

        The HTTP method.

      • url: string

        The request URL.

      • data: string | object | undefined

        The request body, when present.

      • authKey: string | undefined

        An authentication-safe credential identity, so cached responses never cross bearer-token identities.

      • generationAtRead: number

        The generation the caller captured before the read went to the network.

      • response: T

        The response body to cache.

      • OptionalrootField: string

        The GraphQL document's single selected root field, when the caller knows it, so scoped invalidations that landed while the read was in flight are matched against the read's own root field; an unattributed document (undefined) is treated as affected by every scoped invalidation, fail-closed.

      Returns boolean

      Whether the response was stored: false when an invalidation affecting the read landed while it was in flight (the stale response is dropped) or a write-side guard skipped it. That is the signal behind the cacheWrite flag on the transport's onResponse emission, so consumers can measure cache fill rate.

    • Returns a read-only snapshot of the cache's size and lifetime counters, so cache tuning (ttlMs/maxEntries) can be data-driven: entry counts and eviction/expiration counters distinguish a too-small cache (rising evictions) from a too-short TTL (rising expirations), and hit-rate dashboards compute hits / (hits + misses + expirations): an expired-on-read entry counts as an expiration, not a miss, so the three counters partition every get() call.

      The counters are cumulative for the cache instance's lifetime: delete(), deleteMatching(), deleteAllForUrl(), and clear() drop entries but never reset or increment the counters, and entries reflects the current live entry count. The returned object is frozen, so a caller cannot mutate the cache's internal state through it.

      Returns ResponseCacheStats

      A frozen { entries, hits, misses, expirations, evictions } snapshot of the cache's current size and lifetime counters.