Add "debug" config and "allowStale" configs

This commit is contained in:
Tim Donohue
2023-02-07 12:22:32 -06:00
parent a150c64e2f
commit c099bc468d
5 changed files with 33 additions and 6 deletions

View File

@@ -49,6 +49,8 @@ cache:
# NOTE: To control the cache size, use the "max" setting. Keep in mind, individual cached pages are usually small (<100KB). # NOTE: To control the cache size, use the "max" setting. Keep in mind, individual cached pages are usually small (<100KB).
# Enabling *both* caches will mean that a page may be cached twice, once in each cache (but may expire at different times via timeToLive). # Enabling *both* caches will mean that a page may be cached twice, once in each cache (but may expire at different times via timeToLive).
serverSide: serverSide:
# Set to true to see all cache hits/misses/refreshes in your console logs. Useful for debugging SSR caching issues.
debug: false
# When enabled (i.e. max > 0), known bots will be sent pages from a server side cache specific for bots. # When enabled (i.e. max > 0), known bots will be sent pages from a server side cache specific for bots.
# (Keep in mind, bot detection cannot be guarranteed. It is possible some bots will bypass this cache.) # (Keep in mind, bot detection cannot be guarranteed. It is possible some bots will bypass this cache.)
botCache: botCache:
@@ -62,6 +64,11 @@ cache:
# NOTE: For the bot cache, this setting may impact how quickly search engine bots will index new content on your site. # NOTE: For the bot cache, this setting may impact how quickly search engine bots will index new content on your site.
# For example, setting this to one week may mean that search engine bots may not find all new content for one week. # For example, setting this to one week may mean that search engine bots may not find all new content for one week.
timeToLive: 86400000 # 1 day timeToLive: 86400000 # 1 day
# When set to true, after timeToLive expires, the next request will receive the *cached* page & then re-render the page
# behind the scenes to update the cache. This ensures users primarily interact with the cache, but may receive stale pages (older than timeToLive).
# When set to false, after timeToLive expires, the next request will wait on SSR to complete & receive a fresh page (which is then saved to cache).
# This ensures stale pages (older than timeToLive) are never returned from the cache, but some users will wait on SSR.
allowStale: true
# When enabled (i.e. max > 0), all anonymous users will be sent pages from a server side cache. # When enabled (i.e. max > 0), all anonymous users will be sent pages from a server side cache.
# This allows anonymous users to interact more quickly with the site, but also means they may see slightly # This allows anonymous users to interact more quickly with the site, but also means they may see slightly
# outdated content (based on timeToLive) # outdated content (based on timeToLive)
@@ -74,6 +81,11 @@ cache:
# copy is automatically refreshed on the next request. # copy is automatically refreshed on the next request.
# NOTE: For the anonymous cache, it is recommended to keep this value low to avoid anonymous users seeing outdated content. # NOTE: For the anonymous cache, it is recommended to keep this value low to avoid anonymous users seeing outdated content.
timeToLive: 10000 # 10 seconds timeToLive: 10000 # 10 seconds
# When set to true, after timeToLive expires, the next request will receive the *cached* page & then re-render the page
# behind the scenes to update the cache. This ensures users primarily interact with the cache, but may receive stale pages (older than timeToLive).
# When set to false, after timeToLive expires, the next request will wait on SSR to complete & receive a fresh page (which is then saved to cache).
# This ensures stale pages (older than timeToLive) are never returned from the cache, but some users will wait on SSR.
allowStale: true
# Authentication settings # Authentication settings
auth: auth:

View File

@@ -324,7 +324,7 @@ function initCache() {
botCache = new LRU( { botCache = new LRU( {
max: environment.cache.serverSide.botCache.max, max: environment.cache.serverSide.botCache.max,
ttl: environment.cache.serverSide.botCache.timeToLive || 24 * 60 * 60 * 1000, // 1 day ttl: environment.cache.serverSide.botCache.timeToLive || 24 * 60 * 60 * 1000, // 1 day
allowStale: true // If object is found to be stale, return stale value before deleting allowStale: environment.cache.serverSide.botCache.allowStale || true // if object is stale, return stale value before deleting
}); });
} }
@@ -335,7 +335,7 @@ function initCache() {
anonymousCache = new LRU( { anonymousCache = new LRU( {
max: environment.cache.serverSide.anonymousCache.max, max: environment.cache.serverSide.anonymousCache.max,
ttl: environment.cache.serverSide.anonymousCache.timeToLive || 10 * 1000, // 10 seconds ttl: environment.cache.serverSide.anonymousCache.timeToLive || 10 * 1000, // 10 seconds
allowStale: true // If object is found to be stale, return stale value before deleting allowStale: environment.cache.serverSide.anonymousCache.allowStale || true // if object is stale, return stale value before deleting
}); });
} }
} }
@@ -399,24 +399,25 @@ function cacheCheck(req, res, next) {
* @returns cached copy (if found) or undefined (if not found) * @returns cached copy (if found) or undefined (if not found)
*/ */
function checkCacheForRequest(cacheName: string, cache: LRU<string, any>, req, res): any { function checkCacheForRequest(cacheName: string, cache: LRU<string, any>, req, res): any {
let debug = false; // Enable to see cache hits & re-rendering in logs
// Get the cache key for this request // Get the cache key for this request
const key = getCacheKey(req); const key = getCacheKey(req);
// Check if this page is in our cache // Check if this page is in our cache
let cachedCopy = cache.get(key); let cachedCopy = cache.get(key);
if (cachedCopy) { if (cachedCopy) {
if (debug) { console.log(`CACHE HIT FOR ${key} in ${cacheName} cache`); } if (environment.cache.serverSide.debug) { console.log(`CACHE HIT FOR ${key} in ${cacheName} cache`); }
// Check if cached copy is expired (If expired, the key will now be gone from cache) // Check if cached copy is expired (If expired, the key will now be gone from cache)
// NOTE: This will only occur when "allowStale=true", as it means the "get(key)" above returned a stale value.
if (!cache.has(key)) { if (!cache.has(key)) {
if (debug) { console.log(`CACHE EXPIRED FOR ${key} in ${cacheName} cache. Re-rendering...`); } if (environment.cache.serverSide.debug) { console.log(`CACHE EXPIRED FOR ${key} in ${cacheName} cache. Re-rendering...`); }
// Update cached copy by rerendering server-side // Update cached copy by rerendering server-side
// NOTE: In this scenario the currently cached copy will be returned to the current user. // NOTE: In this scenario the currently cached copy will be returned to the current user.
// This re-render is peformed behind the scenes to update cached copy for next user. // This re-render is peformed behind the scenes to update cached copy for next user.
serverSideRender(req, res, false); serverSideRender(req, res, false);
} }
} else {
if (environment.cache.serverSide.debug) { console.log(`CACHE MISS FOR ${key} in ${cacheName} cache.`); }
} }
// return page from cache // return page from cache
@@ -455,11 +456,13 @@ function saveToCache(req, page: any) {
// (NOTE: has() will return false if page is expired in cache) // (NOTE: has() will return false if page is expired in cache)
if (botCacheEnabled() && !botCache.has(key)) { if (botCacheEnabled() && !botCache.has(key)) {
botCache.set(key, page); botCache.set(key, page);
if (environment.cache.serverSide.debug) { console.log(`CACHE SAVE FOR ${key} in bot cache.`); }
} }
// If anonymous cache is enabled, save it to that cache if it doesn't exist or is expired // If anonymous cache is enabled, save it to that cache if it doesn't exist or is expired
if (anonymousCacheEnabled() && !anonymousCache.has(key)) { if (anonymousCacheEnabled() && !anonymousCache.has(key)) {
anonymousCache.set(key, page); anonymousCache.set(key, page);
if (environment.cache.serverSide.debug) { console.log(`CACHE SAVE FOR ${key} in anonymous cache.`); }
} }
} }
} }

View File

@@ -11,12 +11,16 @@ export interface CacheConfig extends Config {
// In-memory caches of server-side rendered (SSR) content. These caches can be used to limit the frequency // In-memory caches of server-side rendered (SSR) content. These caches can be used to limit the frequency
// of re-generating SSR pages to improve performance. // of re-generating SSR pages to improve performance.
serverSide: { serverSide: {
// Debug server-side caching. Set to true to see cache hits/misses/refreshes in console logs.
debug: boolean,
// Cache specific to known bots. Allows you to serve cached contents to bots only. // Cache specific to known bots. Allows you to serve cached contents to bots only.
botCache: { botCache: {
// Maximum number of pages (rendered via SSR) to cache. Setting max=0 disables the cache. // Maximum number of pages (rendered via SSR) to cache. Setting max=0 disables the cache.
max: number; max: number;
// Amount of time after which cached pages are considered stale (in ms) // Amount of time after which cached pages are considered stale (in ms)
timeToLive: number; timeToLive: number;
// true = return page from cache after timeToLive expires. false = return a fresh page after timeToLive expires
allowStale: boolean;
}, },
// Cache specific to anonymous users. Allows you to serve cached content to non-authenticated users. // Cache specific to anonymous users. Allows you to serve cached content to non-authenticated users.
anonymousCache: { anonymousCache: {
@@ -24,6 +28,8 @@ export interface CacheConfig extends Config {
max: number; max: number;
// Amount of time after which cached pages are considered stale (in ms) // Amount of time after which cached pages are considered stale (in ms)
timeToLive: number; timeToLive: number;
// true = return page from cache after timeToLive expires. false = return a fresh page after timeToLive expires
allowStale: boolean;
} }
} }
} }

View File

@@ -76,6 +76,7 @@ export class DefaultAppConfig implements AppConfig {
}, },
// In-memory cache of server-side rendered content // In-memory cache of server-side rendered content
serverSide: { serverSide: {
debug: false,
// Cache specific to known bots. Allows you to serve cached contents to bots only. // Cache specific to known bots. Allows you to serve cached contents to bots only.
// Defaults to caching 1,000 pages. Each page expires after 1 day // Defaults to caching 1,000 pages. Each page expires after 1 day
botCache: { botCache: {
@@ -83,6 +84,7 @@ export class DefaultAppConfig implements AppConfig {
max: 1000, max: 1000,
// Amount of time after which cached pages are considered stale (in ms) // Amount of time after which cached pages are considered stale (in ms)
timeToLive: 24 * 60 * 60 * 1000, // 1 day timeToLive: 24 * 60 * 60 * 1000, // 1 day
allowStale: true,
}, },
// Cache specific to anonymous users. Allows you to serve cached content to non-authenticated users. // Cache specific to anonymous users. Allows you to serve cached content to non-authenticated users.
// Defaults to caching 0 pages. But, when enabled, each page expires after 10 seconds (to minimize anonymous users seeing out-of-date content) // Defaults to caching 0 pages. But, when enabled, each page expires after 10 seconds (to minimize anonymous users seeing out-of-date content)
@@ -91,6 +93,7 @@ export class DefaultAppConfig implements AppConfig {
max: 0, // disabled by default max: 0, // disabled by default
// Amount of time after which cached pages are considered stale (in ms) // Amount of time after which cached pages are considered stale (in ms)
timeToLive: 10 * 1000, // 10 seconds timeToLive: 10 * 1000, // 10 seconds
allowStale: true,
} }
} }
}; };

View File

@@ -58,13 +58,16 @@ export const environment: BuildConfig = {
}, },
// In-memory cache of server-side rendered pages. Disabled in test environment (max=0) // In-memory cache of server-side rendered pages. Disabled in test environment (max=0)
serverSide: { serverSide: {
debug: false,
botCache: { botCache: {
max: 0, max: 0,
timeToLive: 24 * 60 * 60 * 1000, // 1 day timeToLive: 24 * 60 * 60 * 1000, // 1 day
allowStale: true,
}, },
anonymousCache: { anonymousCache: {
max: 0, max: 0,
timeToLive: 10 * 1000, // 10 seconds timeToLive: 10 * 1000, // 10 seconds
allowStale: true,
} }
} }
}, },