Skip to content

Commit

Permalink
Added new background refresh cache behavior.
Browse files Browse the repository at this point in the history
  • Loading branch information
brianreavis committed Aug 29, 2015
1 parent 3e9a0c5 commit 4d84f1e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ module.exports = function(options) {
callback(err);
},
get: function(server, tile, callback) {
callback(err, buffer, headers);
callback(err, buffer, headers, /* refresh */);
},
set: function(server, tile, buffer, headers, callback) {
callback(err);
Expand All @@ -199,6 +199,12 @@ module.exports = function(options) {
};
```

A special behavior exists for when a cache returns a hit, but wants a new tile to be generated in the background. The use case: you have tile that's old enough it *should* be regenerated, but it's not old enough to warrant making the user wait for a new tile to be rendered. To accomplish this in a plugin, have `get()` return `true` as the fourth argument to the callback.

```js
callback(null, buffer, headers, true);
```

### Writing Providers

Providers are responsible for building tiles. A provider must define a `serve` method and optionally an `init` method that is called when the server starts.
Expand Down
12 changes: 9 additions & 3 deletions lib/TileRequestHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ TileRequestHandler.prototype['GET'] = function(server, req, callback) {
var renderedHeaders;
var renderedBuffer;
var cacheHeaders;
var backgroundRefresh = false;
var waitForCache = req.headers.hasOwnProperty('x-tilestrata-cachewait');

// process:
Expand Down Expand Up @@ -156,11 +157,15 @@ TileRequestHandler.prototype['GET'] = function(server, req, callback) {
}

function fetcher(cache, callback) {
cache.get(server, req, function(err, buffer, headers) {
cache.get(server, req, function(err, buffer, headers, refresh) {
cacheHitBuffer = buffer;
cacheHitHeaders = headers;
if (!err && buffer) return callback('HIT');
else callback(); // ignore errors
if (!err && buffer) {
backgroundRefresh = refresh;
return callback('HIT');
} else {
callback(); // ignore errors
}
});
}

Expand All @@ -169,6 +174,7 @@ TileRequestHandler.prototype['GET'] = function(server, req, callback) {
var headers = cacheHitHeaders || {};
headers['X-TileStrata-CacheHit'] = '1';
done(200, cacheHitBuffer, headers);
if (backgroundRefresh) callback(); // continue process in background
} else {
// fallback to provider
callback();
Expand Down
46 changes: 46 additions & 0 deletions test/TileRequestHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,52 @@ describe('TileRequestHandler', function() {
done();
});
});
it('should refresh tile in background if any of the caches return true for "refresh" arg on callback', function(done) {
var _responded = false;
var _cache_set_calls = 0;

var mockServer = new TileServer();
var mockRequest = TileRequest.parse('/layer/1/2/3/tile.png');
var handler = new TileRequestHandler();
var assertCacheSet = function(server, req, buffer, headers, callback) {
_cache_set_calls++;
assert.isTrue(_responded, 'Set should happen after response sent');
assert.equal(buffer.toString('utf8'), 'thedata');
assert.deepEqual(headers, {'X-Step': 'provider'});
callback();
if (_cache_set_calls === 2) {
done();
}
};

handler.use({
get: function(server, req, callback) { callback(); },
set: assertCacheSet
});

handler.use({
get: function(server, req, callback) {
var cacheData = new Buffer('cachedata', 'utf8');
var cacheHeaders = {'X-Step': 'cache'};
callback(null, cacheData, cacheHeaders, true);
},
set: assertCacheSet
});

handler.use({
serve: function(server, req, callback) {
var _buffer = new Buffer('thedata', 'utf8');
callback(null, _buffer, {'X-Step': 'provider'});
}
});

handler.GET(mockServer, mockRequest, function(status, buffer, headers) {
_responded = true;
assert.equal(status, 200);
assert.equal(buffer.toString('utf8'), 'cachedata');
assert.deepEqual(headers, {'X-Step': 'cache', 'X-TileStrata-CacheHit': '1'});
});
});
it('should attempt to cache after successful provider result', function(done) {
var mockServer = new TileServer();
var mockRequest = TileRequest.parse('/layer/1/2/3/tile.png');
Expand Down

0 comments on commit 4d84f1e

Please sign in to comment.