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,78 @@
/*
This is the default "use cache" handler it defaults
to an in memory store
*/ import { LRUCache } from '../lru-cache';
import { isTagStale, tagsManifest } from '../incremental-cache/tags-manifest.external';
// LRU cache default to max 50 MB but in future track
const memoryCache = new 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 (isTagStale(entry.tags, entry.timestamp) || 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 (!tagsManifest.items[tag]) {
tagsManifest.items[tag] = {};
}
// TODO: use performance.now and update file-system-cache?
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);
}
};
export default DefaultCacheHandler;
//# sourceMappingURL=default.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
// 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
export { };
//# 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;AAmC7B,WAgBC"}