Skip to content
This repository has been archived by the owner on Dec 9, 2024. It is now read-only.

Commit

Permalink
Add caching to routes
Browse files Browse the repository at this point in the history
POST requests will set to cache, but never read from it
GET requests will set to, and read from, cache. If `no-cache` is present in the `cache-control` header, a fresh/non-cached version will be retrieved, set to cache, and returned
  • Loading branch information
zarathustra323 committed Nov 30, 2021
1 parent 4bbcc73 commit d319c31
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
24 changes: 19 additions & 5 deletions services/oembed/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const helmet = require('helmet');
const { json } = require('body-parser');
const { asyncRoute } = require('@parameter1/base-cms-utils');
const embedly = require('./embedly');
const cache = require('./cache');

const app = express();
const dev = process.env.NODE_ENV === 'development';
Expand All @@ -12,15 +13,28 @@ app.use(json());
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);

app.post('/', asyncRoute(async (req, res) => {
const { body } = req;
const data = await embedly.oembed(body.url, body.params);
const { url, ...params } = req.body;
const data = await embedly.oembed(url, params);
// post will set to cache, but not read from it
await cache.setFor({ url, params, data });
res.json(data);
}));

app.get('/', asyncRoute(async (req, res) => {
const { query } = req;
const data = await embedly.oembed(query.url, query);
res.json(data);
const { url, ...params } = req.query;
const cacheControl = req.headers['cache-control'];
const noCache = cacheControl && /no-cache/i.test(cacheControl);

// allow for fresh data retrieval
const cached = noCache ? null : await cache.getFor({ url, params });
res.set('X-Cache', cached ? 'hit' : 'miss');
if (cached) {
res.set('Age', cached.age);
return res.json(cached.data);
}
const data = await embedly.oembed(url, params);
await cache.setFor({ url, params, data });
return res.json(data);
}));

// eslint-disable-next-line no-unused-vars
Expand Down
30 changes: 30 additions & 0 deletions services/oembed/src/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { createHash } = require('crypto');
const redis = require('./redis');

const createCacheKey = ({ url, params } = {}) => {
const hash = createHash('sha256').update(JSON.stringify({ url, params })).digest('hex');
return `base_oembed:${hash}`;
};

const getFor = async ({ url, params } = {}) => {
const key = createCacheKey({ url, params });
const serialized = await redis.get(key);
if (!serialized) return null;
const cacheValue = JSON.parse(serialized);
const age = Math.round((Date.now() - cacheValue.cacheTime) / 1000);
return { ...cacheValue, age };
};

const setFor = async ({ url, params, data } = {}) => {
const key = createCacheKey({ url, params });
const cacheValue = { data, cacheTime: Date.now() };
const ttl = 60 * 60 * 24 * 3; // cache for 72 hours
await redis.set(key, JSON.stringify(cacheValue), 'EX', ttl);
};


module.exports = {
createCacheKey,
getFor,
setFor,
};

0 comments on commit d319c31

Please sign in to comment.