UNPKG

next

Version:

The React Framework

109 lines (108 loc) • 4.84 kB
/** * A timestamp in milliseconds elapsed since the epoch */ export type Timestamp = number; export interface CacheEntry { /** * The serialized value of the entry. A cache handler consumes this stream in * `set` and persists what it delivers. A handler can buffer the stream, or it * can pipe it to its storage as chunks arrive. Two rules apply either way: * * - A handler must return a new stream from every `get`. * - A handler must not retain the stream after `set` resolves. * * A stream can be read one time only. A second reader of the same stream gets * no data, or an error while the first reader holds the lock. A retained * stream also keeps a reference to the async context of the request that * created it, which keeps the state of that request reachable for as long as * the entry lives. * * The same applies to the `pendingEntry` promise that `set` receives. A * handler must not put that promise in a map that outlives the request. * * The stream can error and deliver partial data. Each handler decides whether * it keeps the partial entry or discards it. */ value: ReadableStream<Uint8Array>; /** * The tags configured for the entry excluding soft tags */ tags: string[]; /** * This is for the client, not used to calculate cache entry expiration * [duration in seconds] */ stale: number; /** * When the cache entry was created [timestamp in milliseconds] */ timestamp: Timestamp; /** * How long the entry is allowed to be used (should be longer than revalidate) * [duration in seconds] * * This is the hard limit. Next.js compares it against `timestamp` on every * read and treats a too-old entry as a miss, so a handler does not need to * check the age of an entry before it returns one. The dev server raises the * limit to five minutes when `expire` is shorter, to keep reloads fast. */ expire: number; /** * How long until the entry should be revalidated [duration in seconds] * * An entry that is past `revalidate` but within `expire` is still served, and * Next.js generates a fresh one in the background. A negative value always * lies in the past, so it forces that background refresh on the next read. * The built-in handler returns `-1` for an entry whose tag is stale, which * serves the entry one more time and replaces it. */ revalidate: number; } export interface CacheHandler { /** * Retrieve a cache entry for the given cache key, if available. Will return * undefined if there's nothing stored, or if the given soft tags are stale. * * Each call returns a new `value` stream over the stored bytes. See * `CacheEntry.value`. */ get(cacheKey: string, softTags: string[]): Promise<undefined | CacheEntry>; /** * Store a cache entry for the given cache key. When this is called, the entry * may still be pending, i.e. its value stream may still be written to. So it * needs to be awaited first. If a `get` for the same cache key is called, * before the pending entry is complete, the cache handler must wait for the * `set` operation to finish, before returning the entry, instead of returning * undefined. * * The handler takes ownership of the entry's `value` stream, and consumes it * exactly once. See `CacheEntry.value`. * * The handler also owns eviction. Next.js never removes an entry from the * store, so the store needs a mechanism of its own, such as a time to live * from `expire`, or a size-bounded LRU. */ set(cacheKey: string, pendingEntry: Promise<CacheEntry>): Promise<void>; /** * This function is called once per request, before the first cache read for * this handler's kind. A request that reads nothing from this handler does * not call it. If applicable, it should communicate with the tags service to * refresh the local tags manifest accordingly. */ refreshTags(): Promise<void>; /** * This function is called for each set of soft tags that are relevant at the * start of a request. The result is the maximum timestamp of a revalidate * event for the tags. Returns `0` if none of the tags were ever revalidated. * Returns `Infinity` if the soft tags are supposed to be passed into the * `get` method instead to be checked for expiration. */ getExpiration(tags: string[]): Promise<Timestamp>; /** * This function is called when tags are revalidated/expired. If applicable, * it should update the tags manifest accordingly. */ updateTags(tags: string[], durations?: { expire?: number; }): Promise<void>; }