pixl-server-storage 3.0.16 → 3.0.19
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/Filesystem.js +52 -0
- package/engines/S3.js +39 -2
- package/package.json +1 -1
- package/storage.js +33 -3
package/engines/Filesystem.js
CHANGED
|
@@ -315,6 +315,58 @@ module.exports = Class.create({
|
|
|
315
315
|
inp.pipe( outp );
|
|
316
316
|
},
|
|
317
317
|
|
|
318
|
+
putStreamCustom: function(key, inp, opts, callback) {
|
|
319
|
+
// store key+stream of data to disk
|
|
320
|
+
var self = this;
|
|
321
|
+
var file = this.getFilePath(key);
|
|
322
|
+
|
|
323
|
+
this.logDebug(9, "Storing Binary Stream Object: " + key, file);
|
|
324
|
+
|
|
325
|
+
var dir = path.dirname( file );
|
|
326
|
+
|
|
327
|
+
var temp_file = this.tempDir + '/' + path.basename(file) + '.tmp.' + this.tempFileCounter;
|
|
328
|
+
this.tempFileCounter = (this.tempFileCounter + 1) % 10000000;
|
|
329
|
+
|
|
330
|
+
// create the write stream to temp file
|
|
331
|
+
var outp = fs.createWriteStream( temp_file, opts || {} );
|
|
332
|
+
|
|
333
|
+
outp.on('error', function(err) {
|
|
334
|
+
// failed to write file
|
|
335
|
+
var msg = "Failed to write file: " + key + ": " + temp_file + ": " + err.message;
|
|
336
|
+
self.logError('file', msg);
|
|
337
|
+
return callback( new Error(msg), null );
|
|
338
|
+
} );
|
|
339
|
+
|
|
340
|
+
outp.on('finish', function() {
|
|
341
|
+
// make sure parent dirs exist, async
|
|
342
|
+
self._makeDirs( dir, 0o0775, function(err) {
|
|
343
|
+
if (err) {
|
|
344
|
+
// failed to create directory
|
|
345
|
+
var msg = "Failed to create directory: " + key + ": " + dir + ": " + err.message;
|
|
346
|
+
self.logError('file', msg);
|
|
347
|
+
return callback( new Error(msg), null );
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// rename temp file to final
|
|
351
|
+
self._renameFile( temp_file, file, function (err) {
|
|
352
|
+
if (err) {
|
|
353
|
+
// failed to write file
|
|
354
|
+
var msg = "Failed to rename file: " + key + ": " + temp_file + ": " + err.message;
|
|
355
|
+
self.logError('file', msg);
|
|
356
|
+
return callback( new Error(msg), null );
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// all done
|
|
360
|
+
self.logDebug(9, "Store operation complete: " + key);
|
|
361
|
+
callback(null, null);
|
|
362
|
+
} ); // rename
|
|
363
|
+
} ); // mkdirp
|
|
364
|
+
} ); // pipe finish
|
|
365
|
+
|
|
366
|
+
// pipe inp to outp
|
|
367
|
+
inp.pipe( outp );
|
|
368
|
+
},
|
|
369
|
+
|
|
318
370
|
head: function(key, callback) {
|
|
319
371
|
// head value given key
|
|
320
372
|
var self = this;
|
package/engines/S3.js
CHANGED
|
@@ -166,6 +166,33 @@ module.exports = Class.create({
|
|
|
166
166
|
} );
|
|
167
167
|
},
|
|
168
168
|
|
|
169
|
+
putStreamCustom: function(key, inp, opts, callback) {
|
|
170
|
+
// store key+stream of data to S3, inc options
|
|
171
|
+
var self = this;
|
|
172
|
+
var orig_key = key;
|
|
173
|
+
key = this.prepKey(key);
|
|
174
|
+
|
|
175
|
+
var params = {};
|
|
176
|
+
params.Key = this.extKey(key, orig_key);
|
|
177
|
+
params.Body = inp;
|
|
178
|
+
if (opts) Tools.mergeHashInto(params, opts);
|
|
179
|
+
|
|
180
|
+
this.logDebug(9, "Storing S3 Binary Stream: " + key);
|
|
181
|
+
|
|
182
|
+
// double-callback protection (bug in aws-sdk)
|
|
183
|
+
var done = false;
|
|
184
|
+
this.s3.upload(params, function(err, data) {
|
|
185
|
+
if (done) return; else done = true;
|
|
186
|
+
|
|
187
|
+
if (err) {
|
|
188
|
+
self.logError('s3', "Failed to store stream: " + key + ": " + (err.message || err), err);
|
|
189
|
+
}
|
|
190
|
+
else self.logDebug(9, "Stream store complete: " + key);
|
|
191
|
+
|
|
192
|
+
if (callback) callback(err, data);
|
|
193
|
+
} );
|
|
194
|
+
},
|
|
195
|
+
|
|
169
196
|
head: function(key, callback) {
|
|
170
197
|
// head s3 value given key
|
|
171
198
|
var self = this;
|
|
@@ -193,7 +220,14 @@ module.exports = Class.create({
|
|
|
193
220
|
if (done) return; else done = true;
|
|
194
221
|
|
|
195
222
|
if (err) {
|
|
196
|
-
if ((err.code
|
|
223
|
+
if ((err.code == 'NoSuchKey') || (err.code == 'NotFound')) {
|
|
224
|
+
// key not found, special case, don't log an error
|
|
225
|
+
// always include "Not found" in error message
|
|
226
|
+
err = new Error("Failed to head key: " + key + ": Not found");
|
|
227
|
+
err.code = "NoSuchKey";
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
// some other error
|
|
197
231
|
self.logError('s3', "Failed to head key: " + key + ": " + (err.message || err), err);
|
|
198
232
|
}
|
|
199
233
|
callback( err, null );
|
|
@@ -277,7 +311,10 @@ module.exports = Class.create({
|
|
|
277
311
|
self.logDebug(9, "JSON fetch complete: " + key, self.debugLevel(10) ? body : null);
|
|
278
312
|
}
|
|
279
313
|
|
|
280
|
-
callback( null, body
|
|
314
|
+
callback( null, body, {
|
|
315
|
+
mod: Math.floor((new Date(data.LastModified)).getTime() / 1000),
|
|
316
|
+
len: data.ContentLength
|
|
317
|
+
} );
|
|
281
318
|
} );
|
|
282
319
|
},
|
|
283
320
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-server-storage",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.19",
|
|
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
|
@@ -226,6 +226,36 @@ module.exports = Class.create({
|
|
|
226
226
|
} );
|
|
227
227
|
},
|
|
228
228
|
|
|
229
|
+
putStreamCustom: function(key, stream, opts, callback) {
|
|
230
|
+
// store key+stream with engine-specific opts
|
|
231
|
+
var self = this;
|
|
232
|
+
|
|
233
|
+
if (!this.started) return callback( new Error("Storage has not completed startup.") );
|
|
234
|
+
key = this.normalizeKey( key );
|
|
235
|
+
|
|
236
|
+
if (!this.isBinaryKey(key)) {
|
|
237
|
+
return callback( new Error("Stream values are only allowed with keys containing file extensions, e.g. " + key + ".bin") );
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// sanity checks
|
|
241
|
+
if (!stream || !stream.pipe) return callback( new Error("Not a valid stream.") );
|
|
242
|
+
|
|
243
|
+
// invoke engine and track perf
|
|
244
|
+
var pf = this.perf.begin('put');
|
|
245
|
+
|
|
246
|
+
this.engine.putStreamCustom( key, stream, opts, function(err) {
|
|
247
|
+
// put complete
|
|
248
|
+
var elapsed = pf.end();
|
|
249
|
+
|
|
250
|
+
if (!err) self.logTransaction('put', key, {
|
|
251
|
+
elapsed_ms: elapsed
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
callback(err);
|
|
255
|
+
if (!err) self.emit('putStream', key);
|
|
256
|
+
} );
|
|
257
|
+
},
|
|
258
|
+
|
|
229
259
|
putMulti: function(records, callback) {
|
|
230
260
|
// put multiple records at once, given object of keys and values
|
|
231
261
|
var self = this;
|
|
@@ -324,7 +354,7 @@ module.exports = Class.create({
|
|
|
324
354
|
// invoke engine and track perf
|
|
325
355
|
var pf = this.perf.begin('get');
|
|
326
356
|
|
|
327
|
-
this.engine.get( key, function(err, value) {
|
|
357
|
+
this.engine.get( key, function(err, value, info) {
|
|
328
358
|
// get complete
|
|
329
359
|
var elapsed = pf.end();
|
|
330
360
|
|
|
@@ -339,8 +369,8 @@ module.exports = Class.create({
|
|
|
339
369
|
elapsed_ms: elapsed
|
|
340
370
|
});
|
|
341
371
|
|
|
342
|
-
callback(null, value);
|
|
343
|
-
if (!err) self.emit('get', key, value);
|
|
372
|
+
callback(null, value, info);
|
|
373
|
+
if (!err) self.emit('get', key, value, info);
|
|
344
374
|
} );
|
|
345
375
|
},
|
|
346
376
|
|