next
Version:
The React Framework
152 lines (151 loc) • 6.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
executeRevalidates: null,
withExecuteRevalidates: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
executeRevalidates: function() {
return executeRevalidates;
},
withExecuteRevalidates: function() {
return withExecuteRevalidates;
}
});
const _handlers = require("./use-cache/handlers");
async function withExecuteRevalidates(store, callback) {
if (!store) {
return callback();
}
// If we executed any revalidates during the request, then we don't want to execute them again.
// save the state so we can check if anything changed after we're done running callbacks.
const savedRevalidationState = cloneRevalidationState(store);
try {
return await callback();
} finally{
// Check if we have any new revalidates, and if so, wait until they are all resolved.
const newRevalidates = diffRevalidationState(savedRevalidationState, cloneRevalidationState(store));
await executeRevalidates(store, newRevalidates);
}
}
function cloneRevalidationState(store) {
return {
pendingRevalidatedTags: store.pendingRevalidatedTags ? [
...store.pendingRevalidatedTags
] : [],
pendingRevalidates: {
...store.pendingRevalidates
},
pendingRevalidateWrites: store.pendingRevalidateWrites ? [
...store.pendingRevalidateWrites
] : []
};
}
function diffRevalidationState(prev, curr) {
const prevTagsWithProfile = new Set(prev.pendingRevalidatedTags.map((item)=>{
const profileKey = typeof item.profile === 'object' ? JSON.stringify(item.profile) : item.profile || '';
return `${item.tag}:${profileKey}`;
}));
const prevRevalidateWrites = new Set(prev.pendingRevalidateWrites);
return {
pendingRevalidatedTags: curr.pendingRevalidatedTags.filter((item)=>{
const profileKey = typeof item.profile === 'object' ? JSON.stringify(item.profile) : item.profile || '';
return !prevTagsWithProfile.has(`${item.tag}:${profileKey}`);
}),
pendingRevalidates: Object.fromEntries(Object.entries(curr.pendingRevalidates).filter(([key])=>!(key in prev.pendingRevalidates))),
pendingRevalidateWrites: curr.pendingRevalidateWrites.filter((promise)=>!prevRevalidateWrites.has(promise))
};
}
async function revalidateTags(tagsWithProfile, incrementalCache, workStore) {
if (tagsWithProfile.length === 0) {
return;
}
const handlers = (0, _handlers.getCacheHandlers)();
const promises = [];
// Group tags by profile for batch processing
const tagsByProfile = new Map();
for (const item of tagsWithProfile){
const profile = item.profile;
// Find existing profile by comparing values
let existingKey = undefined;
for (const [key] of tagsByProfile){
if (typeof key === 'string' && typeof profile === 'string' && key === profile) {
existingKey = key;
break;
}
if (typeof key === 'object' && typeof profile === 'object' && JSON.stringify(key) === JSON.stringify(profile)) {
existingKey = key;
break;
}
if (key === profile) {
existingKey = key;
break;
}
}
const profileKey = existingKey || profile;
if (!tagsByProfile.has(profileKey)) {
tagsByProfile.set(profileKey, []);
}
tagsByProfile.get(profileKey).push(item.tag);
}
// Process each profile group
for (const [profile, tagsForProfile] of tagsByProfile){
// Look up the cache profile from workStore if available
let durations;
if (profile) {
let cacheLife;
if (typeof profile === 'object') {
// Profile is already a cacheLife configuration object
cacheLife = profile;
} else if (typeof profile === 'string') {
var _workStore_cacheLifeProfiles;
// Profile is a string key, look it up in workStore
cacheLife = workStore == null ? void 0 : (_workStore_cacheLifeProfiles = workStore.cacheLifeProfiles) == null ? void 0 : _workStore_cacheLifeProfiles[profile];
if (!cacheLife) {
throw Object.defineProperty(new Error(`Invalid profile provided "${profile}" must be configured under cacheLife in next.config or be "max"`), "__NEXT_ERROR_CODE", {
value: "E873",
enumerable: false,
configurable: true
});
}
}
if (cacheLife) {
durations = {
expire: cacheLife.expire
};
}
}
// If profile is not found and not 'max', durations will be undefined
// which will trigger immediate expiration in the cache handler
for (const handler of handlers || []){
if (profile) {
promises.push(handler.updateTags == null ? void 0 : handler.updateTags.call(handler, tagsForProfile, durations));
} else {
promises.push(handler.updateTags == null ? void 0 : handler.updateTags.call(handler, tagsForProfile));
}
}
if (incrementalCache) {
promises.push(incrementalCache.revalidateTag(tagsForProfile, durations));
}
}
await Promise.all(promises);
}
async function executeRevalidates(workStore, state) {
const pendingRevalidatedTags = (state == null ? void 0 : state.pendingRevalidatedTags) ?? workStore.pendingRevalidatedTags ?? [];
const pendingRevalidates = (state == null ? void 0 : state.pendingRevalidates) ?? workStore.pendingRevalidates ?? {};
const pendingRevalidateWrites = (state == null ? void 0 : state.pendingRevalidateWrites) ?? workStore.pendingRevalidateWrites ?? [];
return Promise.all([
revalidateTags(pendingRevalidatedTags, workStore.incrementalCache, workStore),
...Object.values(pendingRevalidates),
...pendingRevalidateWrites
]);
}
//# sourceMappingURL=revalidation-utils.js.map