Skip to content

add support for caching revision data #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"white": false,
"eqnull": true,
"esnext": true,
"unused": true
"unused": true,
"node": true
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ The maximum number of recent revisions to keep in Redis.

*Default:* `10`

### revisionData

Metadata about the revision being uploaded. (normally provided by a plugin like [ember-cli-deploy-revision-data][6])

## Activation

As well as uploading a file to Redis, *ember-cli-deploy-redis* has the ability to mark a revision of a deployed file as `current`. This is most commonly used in the [lightning method of deployment][1] whereby an index.html file is pushed to Redis and then served to the user by a web server. The web server could be configured to return any existing revision of the index.html file as requested by a query parameter. However, the revision marked as the currently `active` revision would be returned if no query paramter is present. For more detailed information on this method of deployment please refer to the [ember-cli-deploy-lightning-pack README][1].
Expand Down
8 changes: 6 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ module.exports = {
var redisLib = context._redisLib;

return new Redis(redisOptions, redisLib);
},

revisionData: function(context) {
return context.revisionData;
}
},
configure: function(/* context */) {
Expand All @@ -69,7 +73,7 @@ module.exports = {
this.log('config ok', { verbose: true });
},

upload: function(/* context */) {
upload: function(context) {
var redisDeployClient = this.readConfig('redisDeployClient');
var revisionKey = this.readConfig('revisionKey');
var distDir = this.readConfig('distDir');
Expand All @@ -80,7 +84,7 @@ module.exports = {

this.log('Uploading `' + filePath + '`', { verbose: true });
return this._readFileContents(filePath)
.then(redisDeployClient.upload.bind(redisDeployClient, keyPrefix, revisionKey))
.then(redisDeployClient.upload.bind(redisDeployClient, keyPrefix, revisionKey, this.readConfig('revisionData')))
.then(this._uploadSuccessMessage.bind(this))
.then(function(key) {
return { redisKey: key };
Expand Down
66 changes: 56 additions & 10 deletions lib/redis.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var CoreObject = require('core-object');
var Promise = require('ember-cli/lib/ext/promise');

module.exports = CoreObject.extend({

init: function(options, lib) {
var redisOptions = options;
var redisLib = lib;
Expand Down Expand Up @@ -39,12 +40,21 @@ module.exports = CoreObject.extend({
var keyPrefix = args.shift();
var value = args.pop();
var revisionKey = args[0] || 'default';
var revisionData = args[1];
var redisKey = keyPrefix + ':' + revisionKey;

var maxEntries = this._maxRecentUploads;
var _this = this;

return Promise.resolve()
.then(this._uploadIfKeyDoesNotExist.bind(this, redisKey, value))
.then(function() {
if (revisionData) {
return _this._uploadRevisionData(keyPrefix, revisionKey, revisionData);
} else {
return Promise.resolve();
}
})
.then(this._updateRecentUploadsList.bind(this, keyPrefix, revisionKey))
.then(this._trimRecentUploadsList.bind(this, keyPrefix, maxEntries))
.then(function() {
Expand All @@ -60,24 +70,50 @@ module.exports = CoreObject.extend({
},

fetchRevisions: function(keyPrefix) {
return Promise.hash({
revisions: this._listRevisions(keyPrefix),
current: this.activeRevision(keyPrefix)
var _this = this;
return this._listRevisions(keyPrefix).then(function(revisions) {
return Promise.hash({
revisions: Promise.resolve(revisions),
current: _this.activeRevision(keyPrefix),
revisionData: _this._revisionData(keyPrefix, revisions)
});
}).then(function(results) {
return results.revisions.map(function(revision) {
return {
revision: revision,
active: revision === results.current
};
});
return results.revisions.map(function(revision, i) {
var hash = {
revision: revision,
active: revision === results.current,
};
if (results.revisionData) {
hash.revisionData = results.revisionData[i];
}
return hash;
});
});
},

activeRevision: function(keyPrefix) {
var currentKey = keyPrefix + ':current';
return this._client.get(currentKey);
},

_revisionData: function(keyPrefix, revisions) {
if (revisions.length === 0) {
return Promise.resolve();
}
var dataKeys = revisions.map(function(revision) {
return keyPrefix + ':revision-data:' + revision;
});

return this._client.mget(dataKeys).then(function(data) {
if (!data) {
return Promise.resolve();
}
return data.map(function(d) {
return JSON.parse(d);
});
});
},

_listRevisions: function(keyPrefix) {
var client = this._client;
var listKey = keyPrefix + ':revisions';
Expand Down Expand Up @@ -116,7 +152,7 @@ module.exports = CoreObject.extend({
});
},
reject
);
);
});
},

Expand All @@ -138,6 +174,15 @@ module.exports = CoreObject.extend({
});
},

_uploadRevisionData: function(keyPrefix, revisionKey, revisionData) {
var client = this._client;
var redisKey = keyPrefix + ':revision-data:' + revisionKey;
return Promise.resolve()
.then(function() {
return client.set(redisKey, JSON.stringify(revisionData));
});
},

_updateRecentUploadsList: function(keyPrefix, revisionKey) {
var client = this._client;
var score = new Date().getTime();
Expand All @@ -161,6 +206,7 @@ module.exports = CoreObject.extend({
revisions.forEach(function(revision) {
if (revision !== current) {
client.del(keyPrefix + ":" + revision);
client.del(keyPrefix + ":revision-data:" + revision);
client.zrem(listKey, revision);
}
});
Expand Down
7 changes: 6 additions & 1 deletion tests/helpers/fake-redis-client.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* jshint node: true */
var Promise = require('ember-cli/lib/ext/promise');
var CoreObject = require('core-object');

module.exports = CoreObject.extend({
Expand All @@ -21,6 +23,9 @@ module.exports = CoreObject.extend({
zrange: function() {
},
zrevrange: function() {
return this.recentRevisions;
return Promise.resolve(this.recentRevisions);
},
mget: function() {
return Promise.resolve();
}
});
2 changes: 2 additions & 0 deletions tests/unit/index-nodetest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* jshint node: true */
/* jshint jasmine: true */
'use strict';

var Promise = require('ember-cli/lib/ext/promise');
Expand Down
39 changes: 37 additions & 2 deletions tests/unit/lib/redis-nodetest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* jshint node: true */
/* jshint jasmine: true */
'use strict';

var FakeRedis = require('../../helpers/fake-redis-lib');
Expand Down Expand Up @@ -81,15 +83,15 @@ describe('redis', function() {
});
});

it('trims the list of recent uploads and removes the index key', function() {
it('trims the list of recent uploads and removes the index key and the revisionData', function() {
var finalUploads = ['3','4','5','6','7','8','9','10','11','key:12'];

var redis = new Redis({}, new FakeRedis(FakeClient.extend({
get: function(key) {
return Promise.resolve(null);
},
del: function(key) {
assert(key === 'key:1' || key === 'key:2');
assert(key === 'key:1' || key === 'key:2' || key === 'key:revision-data:1' || key === 'key:revision-data:2');
},
zrange: function() {
return this.recentRevisions.slice(0,2);
Expand Down Expand Up @@ -339,5 +341,38 @@ describe('redis', function() {
);
});
});

it('retrieves revisionData', function() {
var redis = new Redis({}, new FakeRedis(FakeClient.extend({
get: function() {
},
mget: function(keys) {
return Promise.resolve(['{"revisionKey":"a","timestamp":"2016-03-13T14:25:40.563Z","scm":{"sha":"9101968710f18a6720c48bf032fd82efd5743b7d","email":"[email protected]","name":"Mattia Gheda","timestamp":"2015-12-22T12:44:48.000Z","branch":"master"}}']);
}
})));

redis._client.recentRevisions = ['a'];

var promise = redis.fetchRevisions('key-prefix');
return assert.isFulfilled(promise)
.then(function(result) {
assert.deepEqual(result, [
{
revision: 'a',
active: false,
revisionData: {
revisionKey: 'a',
timestamp: '2016-03-13T14:25:40.563Z',
scm:
{ sha: '9101968710f18a6720c48bf032fd82efd5743b7d',
email: '[email protected]',
name: 'Mattia Gheda',
timestamp: '2015-12-22T12:44:48.000Z',
branch: 'master' }
}
}
]);
});
});
});
});