Be able to synchronize the TTL of cache-control header to expire in a coherent way
This commit is contained in:
parent
027e1f1516
commit
2ec65375fc
@ -1,14 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const ONE_YEAR_IN_SECONDS = 31536000; // ttl in cache provider
|
||||
const FIVE_MINUTES_IN_SECONDS = 60 * 5; // ttl in cache provider
|
||||
const ONE_MINUTE_IN_SECONDS = 60;
|
||||
const THREE_MINUTE_IN_SECONDS = 60 * 3;
|
||||
const FIVE_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 5;
|
||||
const TEN_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 10;
|
||||
const FIFTEEN_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 15;
|
||||
const THIRTY_MINUTES_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 30;
|
||||
const ONE_HOUR_IN_SECONDS = ONE_MINUTE_IN_SECONDS * 60;
|
||||
const ONE_YEAR_IN_SECONDS = ONE_HOUR_IN_SECONDS * 24 * 365;
|
||||
|
||||
const defaultCacheTTL = {
|
||||
ttl: ONE_YEAR_IN_SECONDS,
|
||||
fallbackTtl: FIVE_MINUTES_IN_SECONDS
|
||||
};
|
||||
const cacheControl = Object.assign(defaultCacheTTL, global.settings.cache);
|
||||
|
||||
const validFallbackTTL = [
|
||||
ONE_MINUTE_IN_SECONDS,
|
||||
THREE_MINUTE_IN_SECONDS,
|
||||
FIVE_MINUTES_IN_SECONDS,
|
||||
TEN_MINUTES_IN_SECONDS,
|
||||
FIFTEEN_MINUTES_IN_SECONDS,
|
||||
THIRTY_MINUTES_IN_SECONDS,
|
||||
ONE_HOUR_IN_SECONDS
|
||||
];
|
||||
|
||||
const { ttl, fallbackTtl } = Object.assign(defaultCacheTTL, global.settings.cache);
|
||||
|
||||
module.exports = function cacheControlHeader () {
|
||||
if (!validFallbackTTL.includes(fallbackTtl)) {
|
||||
throw new Error(`Invalid fallback TTL value for Cache-Control header. Got ${fallbackTtl}, expected ${validFallbackTTL.join(', ')}`);
|
||||
}
|
||||
|
||||
return function cacheControlHeaderMiddleware (req, res, next) {
|
||||
const { cachePolicy } = res.locals.params;
|
||||
const { affectedTables, mayWrite } = res.locals;
|
||||
@ -20,15 +42,23 @@ module.exports = function cacheControlHeader () {
|
||||
}
|
||||
|
||||
if (affectedTables && affectedTables.getTables().every(table => table.updated_at !== null)) {
|
||||
const maxAge = mayWrite ? 0 : cacheControl.ttl;
|
||||
const maxAge = mayWrite ? 0 : ttl;
|
||||
res.header('Cache-Control', `no-cache,max-age=${maxAge},must-revalidate,public`);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
||||
const maxAge = cacheControl.fallbackTtl;
|
||||
res.header('Cache-Control', `no-cache,max-age=${maxAge},must-revalidate,public`);
|
||||
const maxAge = fallbackTtl;
|
||||
res.header('Cache-Control', `no-cache,max-age=${computeNextTTL({ ttlInSeconds: maxAge })},must-revalidate,public`);
|
||||
|
||||
return next();
|
||||
};
|
||||
};
|
||||
|
||||
function computeNextTTL ({ ttlInSeconds } = {}) {
|
||||
const nowInSeconds = Math.ceil(Date.now() / 1000);
|
||||
const secondsAfterPreviousTTLStep = nowInSeconds % ttlInSeconds;
|
||||
const secondsToReachTheNextTTLStep = ttlInSeconds - secondsAfterPreviousTTLStep;
|
||||
|
||||
return secondsToReachTheNextTTLStep;
|
||||
}
|
||||
|
@ -246,7 +246,14 @@ it('TRUNCATE TABLE with GET and auth', function(done){
|
||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||
// table should not get a cache channel as it won't get invalidated
|
||||
assert.ok(!res.headers.hasOwnProperty('x-cache-channel'));
|
||||
assert.equal(res.headers['cache-control'], 'no-cache,max-age=300,must-revalidate,public');
|
||||
|
||||
const fallbackTtl = global.settings.cache.fallbackTtl || 300;
|
||||
const cacheControl = res.headers['cache-control'];
|
||||
const [ , maxAge ] = cacheControl.split(',');
|
||||
const [ , value ] = maxAge.split('=');
|
||||
|
||||
assert.ok(Number(value) <= fallbackTtl);
|
||||
|
||||
var pbody = JSON.parse(res.body);
|
||||
assert.equal(pbody.total_rows, 1);
|
||||
assert.equal(pbody.rows[0].count, 0);
|
||||
|
@ -55,7 +55,12 @@ describe('cache headers', function () {
|
||||
method: 'GET'
|
||||
}, {},
|
||||
function(err, res) {
|
||||
assert.equal(res.headers['cache-control'], `no-cache,max-age=${fallbackTtl},must-revalidate,public`);
|
||||
const fallbackTtl = global.settings.cache.fallbackTtl || 300;
|
||||
const cacheControl = res.headers['cache-control'];
|
||||
const [ , maxAge ] = cacheControl.split(',');
|
||||
const [ , value ] = maxAge.split('=');
|
||||
|
||||
assert.ok(Number(value) <= fallbackTtl);
|
||||
|
||||
assert.response(server, {
|
||||
url: `/api/v1/sql?${qs.encode({
|
||||
|
Loading…
Reference in New Issue
Block a user