Skip to content

Commit 43fe41a

Browse files
committed
add support for caching revision data
1 parent 85bb524 commit 43fe41a

File tree

7 files changed

+113
-16
lines changed

7 files changed

+113
-16
lines changed

.jshintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
"white": false,
2929
"eqnull": true,
3030
"esnext": true,
31-
"unused": true
31+
"unused": true,
32+
"node": true
3233
}

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ The maximum number of recent revisions to keep in Redis.
172172

173173
*Default:* `10`
174174

175+
### revisionData
176+
177+
Metadata about the revision being uploaded. (normally provided by a plugin like [ember-cli-deploy-revision-data][6])
178+
175179
## Activation
176180

177181
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].

index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ module.exports = {
5555
var redisLib = context._redisLib;
5656

5757
return new Redis(redisOptions, redisLib);
58+
},
59+
60+
revisionData: function(context) {
61+
return context.revisionData;
5862
}
5963
},
6064
configure: function(/* context */) {
@@ -69,7 +73,7 @@ module.exports = {
6973
this.log('config ok', { verbose: true });
7074
},
7175

72-
upload: function(/* context */) {
76+
upload: function(context) {
7377
var redisDeployClient = this.readConfig('redisDeployClient');
7478
var revisionKey = this.readConfig('revisionKey');
7579
var distDir = this.readConfig('distDir');
@@ -80,7 +84,7 @@ module.exports = {
8084

8185
this.log('Uploading `' + filePath + '`', { verbose: true });
8286
return this._readFileContents(filePath)
83-
.then(redisDeployClient.upload.bind(redisDeployClient, keyPrefix, revisionKey))
87+
.then(redisDeployClient.upload.bind(redisDeployClient, keyPrefix, revisionKey, this.readConfig('revisionData')))
8488
.then(this._uploadSuccessMessage.bind(this))
8589
.then(function(key) {
8690
return { redisKey: key };

lib/redis.js

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var CoreObject = require('core-object');
22
var Promise = require('ember-cli/lib/ext/promise');
33

44
module.exports = CoreObject.extend({
5+
56
init: function(options, lib) {
67
var redisOptions = options;
78
var redisLib = lib;
@@ -39,12 +40,21 @@ module.exports = CoreObject.extend({
3940
var keyPrefix = args.shift();
4041
var value = args.pop();
4142
var revisionKey = args[0] || 'default';
43+
var revisionData = args[1];
4244
var redisKey = keyPrefix + ':' + revisionKey;
4345

4446
var maxEntries = this._maxRecentUploads;
47+
var _this = this;
4548

4649
return Promise.resolve()
4750
.then(this._uploadIfKeyDoesNotExist.bind(this, redisKey, value))
51+
.then(function() {
52+
if (revisionData) {
53+
return _this._uploadRevisionData(keyPrefix, revisionKey, revisionData);
54+
} else {
55+
return Promise.resolve();
56+
}
57+
})
4858
.then(this._updateRecentUploadsList.bind(this, keyPrefix, revisionKey))
4959
.then(this._trimRecentUploadsList.bind(this, keyPrefix, maxEntries))
5060
.then(function() {
@@ -60,24 +70,50 @@ module.exports = CoreObject.extend({
6070
},
6171

6272
fetchRevisions: function(keyPrefix) {
63-
return Promise.hash({
64-
revisions: this._listRevisions(keyPrefix),
65-
current: this.activeRevision(keyPrefix)
73+
var _this = this;
74+
return this._listRevisions(keyPrefix).then(function(revisions) {
75+
return Promise.hash({
76+
revisions: Promise.resolve(revisions),
77+
current: _this.activeRevision(keyPrefix),
78+
revisionData: _this._revisionData(keyPrefix, revisions)
79+
});
6680
}).then(function(results) {
67-
return results.revisions.map(function(revision) {
68-
return {
69-
revision: revision,
70-
active: revision === results.current
71-
};
72-
});
81+
return results.revisions.map(function(revision, i) {
82+
var hash = {
83+
revision: revision,
84+
active: revision === results.current,
85+
};
86+
if (results.revisionData) {
87+
hash.revisionData = results.revisionData[i];
88+
}
89+
return hash;
7390
});
91+
});
7492
},
7593

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

99+
_revisionData: function(keyPrefix, revisions) {
100+
if (revisions.length === 0) {
101+
return Promise.resolve();
102+
}
103+
var dataKeys = revisions.map(function(revision) {
104+
return keyPrefix + ':revision-data:' + revision;
105+
});
106+
107+
return this._client.mget(dataKeys).then(function(data) {
108+
if (!data) {
109+
return Promise.resolve();
110+
}
111+
return data.map(function(d) {
112+
return JSON.parse(d);
113+
});
114+
});
115+
},
116+
81117
_listRevisions: function(keyPrefix) {
82118
var client = this._client;
83119
var listKey = keyPrefix + ':revisions';
@@ -116,7 +152,7 @@ module.exports = CoreObject.extend({
116152
});
117153
},
118154
reject
119-
);
155+
);
120156
});
121157
},
122158

@@ -138,6 +174,15 @@ module.exports = CoreObject.extend({
138174
});
139175
},
140176

177+
_uploadRevisionData: function(keyPrefix, revisionKey, revisionData) {
178+
var client = this._client;
179+
var redisKey = keyPrefix + ':revision-data:' + revisionKey;
180+
return Promise.resolve()
181+
.then(function() {
182+
return client.set(redisKey, JSON.stringify(revisionData));
183+
});
184+
},
185+
141186
_updateRecentUploadsList: function(keyPrefix, revisionKey) {
142187
var client = this._client;
143188
var score = new Date().getTime();
@@ -161,6 +206,7 @@ module.exports = CoreObject.extend({
161206
revisions.forEach(function(revision) {
162207
if (revision !== current) {
163208
client.del(keyPrefix + ":" + revision);
209+
client.del(keyPrefix + ":revision-data:" + revision);
164210
client.zrem(listKey, revision);
165211
}
166212
});

tests/helpers/fake-redis-client.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* jshint node: true */
2+
var Promise = require('ember-cli/lib/ext/promise');
13
var CoreObject = require('core-object');
24

35
module.exports = CoreObject.extend({
@@ -21,6 +23,9 @@ module.exports = CoreObject.extend({
2123
zrange: function() {
2224
},
2325
zrevrange: function() {
24-
return this.recentRevisions;
26+
return Promise.resolve(this.recentRevisions);
27+
},
28+
mget: function() {
29+
return Promise.resolve();
2530
}
2631
});

tests/unit/index-nodetest.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* jshint node: true */
2+
/* jshint jasmine: true */
13
'use strict';
24

35
var Promise = require('ember-cli/lib/ext/promise');

tests/unit/lib/redis-nodetest.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* jshint node: true */
2+
/* jshint jasmine: true */
13
'use strict';
24

35
var FakeRedis = require('../../helpers/fake-redis-lib');
@@ -81,15 +83,15 @@ describe('redis', function() {
8183
});
8284
});
8385

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

8789
var redis = new Redis({}, new FakeRedis(FakeClient.extend({
8890
get: function(key) {
8991
return Promise.resolve(null);
9092
},
9193
del: function(key) {
92-
assert(key === 'key:1' || key === 'key:2');
94+
assert(key === 'key:1' || key === 'key:2' || key === 'key:revision-data:1' || key === 'key:revision-data:2');
9395
},
9496
zrange: function() {
9597
return this.recentRevisions.slice(0,2);
@@ -339,5 +341,38 @@ describe('redis', function() {
339341
);
340342
});
341343
});
344+
345+
it('retrieves revisionData', function() {
346+
var redis = new Redis({}, new FakeRedis(FakeClient.extend({
347+
get: function() {
348+
},
349+
mget: function(keys) {
350+
return Promise.resolve(['{"revisionKey":"a","timestamp":"2016-03-13T14:25:40.563Z","scm":{"sha":"9101968710f18a6720c48bf032fd82efd5743b7d","email":"mattia@mail.com","name":"Mattia Gheda","timestamp":"2015-12-22T12:44:48.000Z","branch":"master"}}']);
351+
}
352+
})));
353+
354+
redis._client.recentRevisions = ['a'];
355+
356+
var promise = redis.fetchRevisions('key-prefix');
357+
return assert.isFulfilled(promise)
358+
.then(function(result) {
359+
assert.deepEqual(result, [
360+
{
361+
revision: 'a',
362+
active: false,
363+
revisionData: {
364+
revisionKey: 'a',
365+
timestamp: '2016-03-13T14:25:40.563Z',
366+
scm:
367+
{ sha: '9101968710f18a6720c48bf032fd82efd5743b7d',
368+
email: 'mattia@mail.com',
369+
name: 'Mattia Gheda',
370+
timestamp: '2015-12-22T12:44:48.000Z',
371+
branch: 'master' }
372+
}
373+
}
374+
]);
375+
});
376+
});
342377
});
343378
});

0 commit comments

Comments
 (0)