pixl-server-storage 3.0.7 → 3.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/engines/Couchbase.js +26 -0
- package/engines/Filesystem.js +30 -0
- package/engines/Hybrid.js +6 -0
- package/engines/Redis.js +27 -0
- package/engines/RedisCluster.js +27 -0
- package/engines/S3.js +40 -0
- package/package.json +1 -1
- package/storage.js +15 -0
package/engines/Couchbase.js
CHANGED
|
@@ -228,6 +228,32 @@ module.exports = Class.create({
|
|
|
228
228
|
} );
|
|
229
229
|
},
|
|
230
230
|
|
|
231
|
+
getStreamRange: function(key, start, end, callback) {
|
|
232
|
+
// get readable stream to record value given key and range
|
|
233
|
+
var self = this;
|
|
234
|
+
|
|
235
|
+
// The Couchbase Node.JS 2.0 API has no stream support.
|
|
236
|
+
// So, we have to do this the RAM-hard way...
|
|
237
|
+
this.get( key, function(err, buf) {
|
|
238
|
+
if (err && (err.code != CouchbaseAPI.errors.keyNotFound)) {
|
|
239
|
+
// some other error
|
|
240
|
+
err.message = "Failed to fetch key: " + key + ": " + err.message;
|
|
241
|
+
self.logError('couchbase', err.message);
|
|
242
|
+
return callback(err);
|
|
243
|
+
}
|
|
244
|
+
else if (!buf) {
|
|
245
|
+
// record not found
|
|
246
|
+
var err = new Error("Failed to fetch key: " + key + ": Not found");
|
|
247
|
+
err.code = "NoSuchKey";
|
|
248
|
+
return callback( err, null );
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
var range = buf.slice(start, end + 1);
|
|
252
|
+
var stream = new BufferStream(range);
|
|
253
|
+
callback(null, stream);
|
|
254
|
+
} );
|
|
255
|
+
},
|
|
256
|
+
|
|
231
257
|
delete: function(key, callback) {
|
|
232
258
|
// delete Couchbase key given key
|
|
233
259
|
// Example CB error message: The key does not exist on the server
|
package/engines/Filesystem.js
CHANGED
|
@@ -453,6 +453,36 @@ module.exports = Class.create({
|
|
|
453
453
|
} );
|
|
454
454
|
},
|
|
455
455
|
|
|
456
|
+
getStreamRange: function(key, start, end, callback) {
|
|
457
|
+
// get readable stream to record value given key and byte range
|
|
458
|
+
var self = this;
|
|
459
|
+
var file = this.getFilePath(key);
|
|
460
|
+
|
|
461
|
+
this.logDebug(9, "Fetching ranged binary stream: " + key, { file, start, end } );
|
|
462
|
+
|
|
463
|
+
// make sure record exists
|
|
464
|
+
fs.stat(file, function(err, stats) {
|
|
465
|
+
if (err) {
|
|
466
|
+
if (err.message.match(/ENOENT/)) {
|
|
467
|
+
err.message = "File not found";
|
|
468
|
+
err.code = "NoSuchKey";
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
// log fs errors that aren't simple missing files (i.e. I/O errors)
|
|
472
|
+
self.logError('file', "Failed to stat file: " + key + ": " + file + ": " + err.message);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
err.message = "Failed to head key: " + key + ": " + err.message;
|
|
476
|
+
return callback( err, null );
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// create read stream
|
|
480
|
+
var inp = fs.createReadStream( file, { start, end } );
|
|
481
|
+
|
|
482
|
+
callback( null, inp );
|
|
483
|
+
} );
|
|
484
|
+
},
|
|
485
|
+
|
|
456
486
|
delete: function(key, callback) {
|
|
457
487
|
// delete key given key
|
|
458
488
|
var self = this;
|
package/engines/Hybrid.js
CHANGED
|
@@ -79,6 +79,12 @@ module.exports = Class.create({
|
|
|
79
79
|
this.binaryEngine.getStream( key, callback );
|
|
80
80
|
},
|
|
81
81
|
|
|
82
|
+
getStreamRange: function(key, start, end, callback) {
|
|
83
|
+
// get readable stream to record value given key and range
|
|
84
|
+
// streams are binary only!
|
|
85
|
+
this.binaryEngine.getStreamRange( key, start, end, callback );
|
|
86
|
+
},
|
|
87
|
+
|
|
82
88
|
delete: function(key, callback) {
|
|
83
89
|
// delete hybrid key given key
|
|
84
90
|
if (this.storage.isBinaryKey(key)) {
|
package/engines/Redis.js
CHANGED
|
@@ -231,6 +231,33 @@ module.exports = Class.create({
|
|
|
231
231
|
} );
|
|
232
232
|
},
|
|
233
233
|
|
|
234
|
+
getStreamRange: function(key, start, end, callback) {
|
|
235
|
+
// get readable stream to record value given key and range
|
|
236
|
+
var self = this;
|
|
237
|
+
|
|
238
|
+
// The Redis API has no stream support.
|
|
239
|
+
// So, we have to do this the RAM-hard way...
|
|
240
|
+
|
|
241
|
+
this.get( key, function(err, buf) {
|
|
242
|
+
if (err) {
|
|
243
|
+
// an actual error
|
|
244
|
+
err.message = "Failed to fetch key: " + key + ": " + err;
|
|
245
|
+
self.logError('redis', ''+err);
|
|
246
|
+
return callback(err);
|
|
247
|
+
}
|
|
248
|
+
else if (!buf) {
|
|
249
|
+
// record not found
|
|
250
|
+
var err = new Error("Failed to fetch key: " + key + ": Not found");
|
|
251
|
+
err.code = "NoSuchKey";
|
|
252
|
+
return callback( err, null );
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
var range = buf.slice(start, end + 1);
|
|
256
|
+
var stream = new BufferStream(range);
|
|
257
|
+
callback(null, stream);
|
|
258
|
+
} );
|
|
259
|
+
},
|
|
260
|
+
|
|
234
261
|
delete: function(key, callback) {
|
|
235
262
|
// delete Redis key given key
|
|
236
263
|
var self = this;
|
package/engines/RedisCluster.js
CHANGED
|
@@ -248,6 +248,33 @@ module.exports = Class.create({
|
|
|
248
248
|
} );
|
|
249
249
|
},
|
|
250
250
|
|
|
251
|
+
getStreamRange: function(key, start, end, callback) {
|
|
252
|
+
// get readable stream to record value given key and range
|
|
253
|
+
var self = this;
|
|
254
|
+
|
|
255
|
+
// The Redis API has no stream support.
|
|
256
|
+
// So, we have to do this the RAM-hard way...
|
|
257
|
+
|
|
258
|
+
this.get( key, function(err, buf) {
|
|
259
|
+
if (err) {
|
|
260
|
+
// an actual error
|
|
261
|
+
err.message = "Failed to fetch key: " + key + ": " + err;
|
|
262
|
+
self.logError('redis', ''+err);
|
|
263
|
+
return callback(err);
|
|
264
|
+
}
|
|
265
|
+
else if (!buf) {
|
|
266
|
+
// record not found
|
|
267
|
+
var err = new Error("Failed to fetch key: " + key + ": Not found");
|
|
268
|
+
err.code = "NoSuchKey";
|
|
269
|
+
return callback( err, null );
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
var range = buf.slice(start, end + 1);
|
|
273
|
+
var stream = new BufferStream(range);
|
|
274
|
+
callback(null, stream);
|
|
275
|
+
} );
|
|
276
|
+
},
|
|
277
|
+
|
|
251
278
|
delete: function(key, callback) {
|
|
252
279
|
// delete Redis key given key
|
|
253
280
|
var self = this;
|
package/engines/S3.js
CHANGED
|
@@ -324,6 +324,46 @@ module.exports = Class.create({
|
|
|
324
324
|
}); // headObject
|
|
325
325
|
},
|
|
326
326
|
|
|
327
|
+
getStreamRange: function(key, start, end, callback) {
|
|
328
|
+
// get readable stream to record value given key and range
|
|
329
|
+
var self = this;
|
|
330
|
+
var orig_key = key;
|
|
331
|
+
key = this.prepKey(key);
|
|
332
|
+
|
|
333
|
+
this.logDebug(9, "Fetching ranged S3 stream: " + key, { start, end });
|
|
334
|
+
|
|
335
|
+
var params = { Key: this.extKey(key, orig_key) };
|
|
336
|
+
|
|
337
|
+
// double-callback protection (bug in aws-sdk)
|
|
338
|
+
var done = false;
|
|
339
|
+
this.s3.headObject( params, function(err) {
|
|
340
|
+
if (done) return; else done = true;
|
|
341
|
+
|
|
342
|
+
if (err) {
|
|
343
|
+
if (err.code != 'NoSuchKey') {
|
|
344
|
+
self.logError('s3', "Failed to head key: " + key + ": " + err.message);
|
|
345
|
+
}
|
|
346
|
+
callback( err, null );
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
params.Range = "bytes=" + start + "-" + end;
|
|
351
|
+
var download = self.s3.getObject(params).createReadStream();
|
|
352
|
+
|
|
353
|
+
download.once('error', function(err) {
|
|
354
|
+
self.logError('s3', "Failed to download key: " + key + ": " + err.message);
|
|
355
|
+
});
|
|
356
|
+
download.once('end', function() {
|
|
357
|
+
self.logDebug(9, "S3 stream download complete: " + key);
|
|
358
|
+
} );
|
|
359
|
+
download.once('close', function() {
|
|
360
|
+
self.logDebug(9, "S3 stream download closed: " + key);
|
|
361
|
+
} );
|
|
362
|
+
|
|
363
|
+
callback( null, download );
|
|
364
|
+
}); // headObject
|
|
365
|
+
},
|
|
366
|
+
|
|
327
367
|
delete: function(key, callback) {
|
|
328
368
|
// delete s3 key given key
|
|
329
369
|
var self = this;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-server-storage",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"description": "A key/value/list storage component for the pixl-server framework.",
|
|
5
5
|
"author": "Joseph Huckaby <jhuckaby@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/jhuckaby/pixl-server-storage",
|
package/storage.js
CHANGED
|
@@ -354,6 +354,21 @@ module.exports = Class.create({
|
|
|
354
354
|
this.engine.getStream( key, callback );
|
|
355
355
|
},
|
|
356
356
|
|
|
357
|
+
getStreamRange: function(key, start, end, callback) {
|
|
358
|
+
// fetch value via stream pipe and range
|
|
359
|
+
// start and end are both inclusive
|
|
360
|
+
var self = this;
|
|
361
|
+
if (!this.started) return callback( new Error("Storage has not completed startup.") );
|
|
362
|
+
|
|
363
|
+
key = this.normalizeKey( key );
|
|
364
|
+
|
|
365
|
+
if (!this.isBinaryKey(key)) {
|
|
366
|
+
return callback( new Error("Stream values are only allowed with keys containing file extensions, e.g. " + key + ".bin") );
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
this.engine.getStreamRange( key, start, end, callback );
|
|
370
|
+
},
|
|
371
|
+
|
|
357
372
|
getMulti: function(keys, callback) {
|
|
358
373
|
// fetch multiple records at once, given array of keys
|
|
359
374
|
// callback is provided an array of values in matching order to keys
|