Skip to content

Commit

Permalink
Merge pull request #9 from bbc/stats
Browse files Browse the repository at this point in the history
Fix: apply cache name when sending events
  • Loading branch information
cejast authored Jan 30, 2018
2 parents ef6187c + e0aa441 commit 25a3cf1
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 68 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const maxAge = require('./lib/maxAge');
const staleIfError = require('./lib/staleIfError');
const events = require('./lib/cache').events;
const events = require('./lib/events').emitter;

module.exports = {
maxAge,
Expand Down
17 changes: 3 additions & 14 deletions lib/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@

const _ = require('lodash');
const bluebird = require('bluebird');
const EventEmitter = require('events');
const events = require('./events');

const VERSION = require('../package').version;

const events = new EventEmitter();
const TimeoutError = bluebird.TimeoutError;

function emitEvent(event, name) {
const type = name ? `cache.${name}.${event}` : `cache.${event}`;
events.emit(type);
}

function createCacheKey(segment, id) {
const versionedSegment = `http-transport:${VERSION}:${segment}`;

Expand All @@ -27,15 +21,10 @@ function getFromCache(cache, segment, id, opts) {
let pending = new Promise((resolve, reject) => {
cache.get(createCacheKey(segment, id), (err, cached) => {
if (err) {
emitEvent('error', cache.name);
events.emitCacheEvent('error', opts);
return reject(err);
}

if (!cached) {
emitEvent('miss', cache.name);
} else {
emitEvent('hit', cache.name);
}
resolve(cached);
});
});
Expand All @@ -49,7 +38,7 @@ function getFromCache(cache, segment, id, opts) {

return pending.catch((err) => {
if (err instanceof TimeoutError) {
emitEvent('timeout', cache.name);
events.emitCacheEvent('timeout', opts);
}

if (_.get(opts, 'ignoreCacheErrors', false)) {
Expand Down
15 changes: 15 additions & 0 deletions lib/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

const EventEmitter = require('events');
const events = new EventEmitter();

function emitCacheEvent(event, opts) {
const name = opts && opts.name ? opts.name : null;
const type = name ? `cache.${name}.${event}` : `cache.${event}`;
events.emit(type);
}

module.exports = {
emitter: events,
emitCacheEvent
};
4 changes: 4 additions & 0 deletions lib/maxAge.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const parseCacheControl = require('./parseCacheControl');
const getFromCache = require('./cache').getFromCache;
const storeInCache = require('./cache').storeInCache;
const toResponse = require('./toResponse');
const events = require('./events');

const MAX_AGE = 'max-age';
const STALE_WHILST_REVALIDATE = 'stale-while-revalidate';
Expand Down Expand Up @@ -52,9 +53,12 @@ module.exports = (cache, opts) => {
revalidate(cached, ctx.req.getUrl(), cache, opts);
}
ctx.res = toResponse(cached);
events.emitCacheEvent('hit', opts);
return;
}

events.emitCacheEvent('miss', opts);

return next().then(() => {
if (ctx.isStale || ctx.res.statusCode >= 400) return;

Expand Down
6 changes: 3 additions & 3 deletions lib/staleIfError.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const parseCacheControl = require('./parseCacheControl');
const getFromCache = require('./cache').getFromCache;
const storeInCache = require('./cache').storeInCache;
const toResponse = require('./toResponse');
const events = require('./cache').events;
const events = require('./events');

const STALE_IF_ERROR = 'stale-if-error';
const MAX_AGE = 'max-age';
Expand Down Expand Up @@ -34,7 +34,7 @@ module.exports = (cache, opts) => {
}
})
.catch((err) => {
return getFromCache(cache, SEGMENT, ctx.req.getUrl())
return getFromCache(cache, SEGMENT, ctx.req.getUrl(), opts)
.catch((cacheErr) => {
if (_.get(opts, 'ignoreCacheErrors', false)) throw err;
throw cacheErr;
Expand All @@ -43,7 +43,7 @@ module.exports = (cache, opts) => {
if (cached) {
ctx.isStale = true;
ctx.res = toResponse(cached);
events.emit('cache.stale');
events.emitCacheEvent('stale', opts);
return;
}

Expand Down
64 changes: 16 additions & 48 deletions test/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const bluebird = require('bluebird');
const sinon = require('sinon');
const sandbox = sinon.sandbox.create();

const { getFromCache, storeInCache, events } = require('../lib/cache');
const { getFromCache, storeInCache } = require('../lib/cache');
const events = require('../').events;

const SEGMENT = 'body';
const VERSION = require('../package').version;
Expand Down Expand Up @@ -113,60 +114,27 @@ describe('Cache', () => {
});

describe('events', () => {
it('emits events with the cache id when present', () => {
it('emits events with the cache name when present', () => {
const cache = createCache();
cache.name = 'memory';

let cacheHit = false;
events.on('cache.memory.hit', () => {
cacheHit = true;
sandbox.stub(cache, 'get').callsFake(() => {
setTimeout(() => { }, 100);
});

return cache
.startAsync()
.then(() => cache.setAsync(bodySegment, cachedResponse, 600))
.then(() => {
return getFromCache(cache, SEGMENT, ID)
.catch(assert.ifError)
.then(() => {
assert.ok(cacheHit);
});
});
});

it('emits a cache hit event', () => {
const cache = createCache();

let cacheHit = false;
events.on('cache.hit', () => {
cacheHit = true;
let cacheTimeout = false;
events.on('cache.ceych.timeout', () => {
cacheTimeout = true;
});

return cache
.startAsync()
.then(() => cache.setAsync(bodySegment, cachedResponse, 600))
.then(() => {
return getFromCache(cache, SEGMENT, ID)
.catch(assert.ifError)
.then(() => {
assert.ok(cacheHit);
});
});
});

it('emits a cache miss event', () => {
const cache = createCache();

let cacheMiss = false;
events.on('cache.miss', () => {
cacheMiss = true;
});
const opts = {
name: 'ceych',
timeout: 50
};

return cache.startAsync().then(() => {
return getFromCache(cache, SEGMENT, ID)
.catch(assert.ifError)
.then(() => {
assert.ok(cacheMiss);
return getFromCache(cache, SEGMENT, ID, opts)
.then(assert.ifError)
.catch(() => {
assert.ok(cacheTimeout);
});
});
});
Expand Down
56 changes: 55 additions & 1 deletion test/maxAge.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const sinon = require('sinon');

const sandbox = sinon.sandbox.create();
const cache = require('../');
const events = require('../').events;

const api = nock('http://www.example.com');

Expand Down Expand Up @@ -100,7 +101,6 @@ describe('Max-Age', () => {
});

it('creates cache entries for item fetcher from another cache with the correct ttl', async () => {

const nearCache = createCache();
const farCache = createCache();

Expand Down Expand Up @@ -548,4 +548,58 @@ describe('Max-Age', () => {
return cache.drop(bodySegment);
});
});

describe('Events', () => {
it('emits events with name when name option is present', () => {
const cache = createCache();
api.get('/').reply(200, defaultResponse.body, defaultHeaders);

let cacheMiss = false;
events.on('cache.ceych.miss', () => {
cacheMiss = true;
});

const opts = {
name: 'ceych'
};

return requestWithCache(cache, opts)
.then(() => {
assert.ok(cacheMiss);
});
});

it('emits a cache miss event', () => {
const cache = createCache();
api.get('/').reply(200, defaultResponse.body, defaultHeaders);

let cacheMiss = false;
events.on('cache.miss', () => {
cacheMiss = true;
});

return requestWithCache(cache)
.then(() => {
assert.ok(cacheMiss);
});
});

it('emits a cache hit event', () => {
const cache = createCache();
api.get('/').reply(200, defaultResponse.body, defaultHeaders);

let cacheHit = false;
events.on('cache.hit', () => {
cacheHit = true;
});

return requestWithCache(cache)
.then(() => {
return requestWithCache(cache)
.then(() => {
assert.ok(cacheHit);
});
});
});
});
});
32 changes: 31 additions & 1 deletion test/staleIfError.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const httpTransport = require('@bbc/http-transport');
const toError = require('@bbc/http-transport-to-error');

const cache = require('../');
const events = require('../lib/cache').events;
const events = require('../').events;

const VERSION = require('../package').version;
const api = nock('http://www.example.com');
Expand Down Expand Up @@ -274,4 +274,34 @@ describe('Stale-If-Error', () => {
assert.ok(cacheStale);
});
});

it('emits a stale cache event with cache name when present', () => {
const opts = {
name: 'ceych'
};

let cacheStale = false;
events.on('cache.ceych.stale', () => {
cacheStale = true;
});

const cachedResponse = {
body: 'http-transport',
headers: defaultHeaders,
elapsedTime: 40,
url: 'http://www.example.com/',
statusCode: 200
};
const cache = createCache();

api.get('/').reply(500, defaultResponse.body, {});

return cache
.startAsync()
.then(() => cache.setAsync(bodySegment, cachedResponse, 7200))
.then(() => requestWithCache(cache, opts))
.then(() => {
assert.ok(cacheStale);
});
});
});

0 comments on commit 25a3cf1

Please sign in to comment.