inital commit

This commit is contained in:
2026-01-01 15:25:19 +05:30
commit f0ae49465a
36361 changed files with 4894111 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
import type { CacheHandler } from './types';
declare const DefaultCacheHandler: CacheHandler;
export default DefaultCacheHandler;

View File

@@ -0,0 +1,88 @@
/*
This is the default "use cache" handler it defaults
to an in memory store
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _lrucache = require("../lru-cache");
const _tagsmanifestexternal = require("../incremental-cache/tags-manifest.external");
// LRU cache default to max 50 MB but in future track
const memoryCache = new _lrucache.LRUCache(50 * 1024 * 1024, (entry)=>entry.size);
const pendingSets = new Map();
const DefaultCacheHandler = {
async get (cacheKey, softTags) {
await pendingSets.get(cacheKey);
const privateEntry = memoryCache.get(cacheKey);
if (!privateEntry) {
return undefined;
}
const entry = privateEntry.entry;
if (performance.timeOrigin + performance.now() > entry.timestamp + entry.revalidate * 1000) {
// In memory caches should expire after revalidate time because it is unlikely that
// a new entry will be able to be used before it is dropped from the cache.
return undefined;
}
if ((0, _tagsmanifestexternal.isTagStale)(entry.tags, entry.timestamp) || (0, _tagsmanifestexternal.isTagStale)(softTags, entry.timestamp)) {
return undefined;
}
const [returnStream, newSaved] = entry.value.tee();
entry.value = newSaved;
return {
...entry,
value: returnStream
};
},
async set (cacheKey, pendingEntry) {
let resolvePending = ()=>{};
const pendingPromise = new Promise((resolve)=>{
resolvePending = resolve;
});
pendingSets.set(cacheKey, pendingPromise);
const entry = await pendingEntry;
let size = 0;
try {
const [value, clonedValue] = entry.value.tee();
entry.value = value;
const reader = clonedValue.getReader();
for(let chunk; !(chunk = await reader.read()).done;){
size += Buffer.from(chunk.value).byteLength;
}
memoryCache.set(cacheKey, {
entry,
isErrored: false,
errorRetryCount: 0,
size
});
} catch {
// TODO: store partial buffer with error after we retry 3 times
} finally{
resolvePending();
pendingSets.delete(cacheKey);
}
},
async expireTags (...tags) {
for (const tag of tags){
if (!_tagsmanifestexternal.tagsManifest.items[tag]) {
_tagsmanifestexternal.tagsManifest.items[tag] = {};
}
// TODO: use performance.now and update file-system-cache?
_tagsmanifestexternal.tagsManifest.items[tag].revalidatedAt = Date.now();
}
},
// This is only meant to invalidate in memory tags
// not meant to be propagated like expireTags would
// in multi-instance scenario
async receiveExpiredTags (...tags) {
return this.expireTags(...tags);
}
};
const _default = DefaultCacheHandler;
//# sourceMappingURL=default.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
export interface CacheEntry {
/**
* The ReadableStream can error and only have partial
* data so any cache handlers need to handle this case
* and decide to keep the partial cache around or not
*/
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
*/
stale: number;
/**
* When the cache entry was created
*/
timestamp: number;
/**
* How long the entry can last (should be longer than revalidate)
*/
expire: number;
/**
* How long until the entry should revalidate
*/
revalidate: number;
}
export interface CacheHandler {
get(cacheKey: string, softTags: string[]): Promise<undefined | CacheEntry>;
set(cacheKey: string, entry: Promise<CacheEntry>): Promise<void>;
expireTags(...tags: string[]): Promise<void>;
receiveExpiredTags(...tags: string[]): Promise<void>;
}

View File

@@ -0,0 +1,12 @@
// In-memory caches are fragile and should not use stale-while-revalidate
// semantics on the caches because it's not worth warming up an entry that's
// likely going to get evicted before we get to use it anyway. However,
// we also don't want to reuse a stale entry for too long so stale entries
// should be considered expired/missing in such CacheHandlers.
// This is the entry we store
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/lib/cache-handlers/types.ts"],"sourcesContent":["// In-memory caches are fragile and should not use stale-while-revalidate\n// semantics on the caches because it's not worth warming up an entry that's\n// likely going to get evicted before we get to use it anyway. However,\n// we also don't want to reuse a stale entry for too long so stale entries\n// should be considered expired/missing in such CacheHandlers.\n\n// This is the entry we store\nexport interface CacheEntry {\n /**\n * The ReadableStream can error and only have partial\n * data so any cache handlers need to handle this case\n * and decide to keep the partial cache around or not\n */\n value: ReadableStream<Uint8Array>\n\n /**\n * The tags configured for the entry excluding soft tags\n */\n tags: string[]\n\n /**\n * This is for the client not used to calculate cache entry expiration\n */\n stale: number\n\n /**\n * When the cache entry was created\n */\n timestamp: number\n\n /**\n * How long the entry can last (should be longer than revalidate)\n */\n expire: number\n\n /**\n * How long until the entry should revalidate\n */\n revalidate: number\n}\n\nexport interface CacheHandler {\n get(cacheKey: string, softTags: string[]): Promise<undefined | CacheEntry>\n\n set(cacheKey: string, entry: Promise<CacheEntry>): Promise<void>\n\n // This is called when expireTags('') is called\n // and should update tags manifest accordingly\n expireTags(...tags: string[]): Promise<void>\n\n // This is called when an action request sends\n // NEXT_CACHE_REVALIDATED_TAGS_HEADER and tells\n // us these tags are expired and the manifest\n // should be updated this differs since in a multi\n // instance environment you don't propagate these\n // as they are request specific\n receiveExpiredTags(...tags: string[]): Promise<void>\n}\n"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,4EAA4E;AAC5E,uEAAuE;AACvE,0EAA0E;AAC1E,8DAA8D;AAE9D,6BAA6B"}