pixl-server-storage 3.0.18 → 3.0.21
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/README.md +4 -2
- package/engines/Filesystem.js +52 -0
- package/engines/S3.js +27 -0
- package/package.json +3 -3
- package/storage.js +30 -0
- package/test/test-hash.js +1 -1
package/README.md
CHANGED
|
@@ -523,10 +523,12 @@ Note that binary records are **not** cached, as they are generally large. Only
|
|
|
523
523
|
|
|
524
524
|
## Couchbase
|
|
525
525
|
|
|
526
|
-
|
|
526
|
+
Please note that as of this writing (April 2022), pixl-server-storage only supports Couchbase Client v2, so you need to force install version `2.6.12` (see instructions below). Work is underway to support the v3 API, which has many breaking changes.
|
|
527
|
+
|
|
528
|
+
If you want to use [Couchbase](http://www.couchbase.com/nosql-databases/couchbase-server) as a backing store, here is how to do so. First, you need to manually install the [couchbase](https://www.npmjs.com/package/couchbase) module into your app, and it **must be v2**:
|
|
527
529
|
|
|
528
530
|
```
|
|
529
|
-
npm install --save couchbase
|
|
531
|
+
npm install --save couchbase@2.6.12
|
|
530
532
|
```
|
|
531
533
|
|
|
532
534
|
Then configure your storage thusly:
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-server-storage",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.21",
|
|
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",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"pixl-server": "^1.0.0",
|
|
25
|
-
"pixl-class": "^1.0.
|
|
25
|
+
"pixl-class": "^1.0.3",
|
|
26
26
|
"pixl-tools": "^1.0.24",
|
|
27
27
|
"pixl-perf": "^1.0.0",
|
|
28
28
|
"pixl-cache": "^1.0.1",
|
|
29
|
-
"async": "2.6.
|
|
29
|
+
"async": "2.6.4",
|
|
30
30
|
"nearley": "2.20.1",
|
|
31
31
|
"moo": "0.4.3",
|
|
32
32
|
"porter-stemmer": "0.9.1",
|
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;
|
package/test/test-hash.js
CHANGED
|
@@ -10,7 +10,7 @@ var async = require('async');
|
|
|
10
10
|
var Tools = require('pixl-tools');
|
|
11
11
|
|
|
12
12
|
// const BAD_KEYS = Object.getOwnPropertyNames( Object.prototype );
|
|
13
|
-
const BAD_KEYS = ['constructor', '__defineGetter__', '__defineSetter__', 'hasOwnProperty', '__lookupGetter__', '__lookupSetter__', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'valueOf', '
|
|
13
|
+
const BAD_KEYS = ['constructor', '__defineGetter__', '__defineSetter__', 'hasOwnProperty', '__lookupGetter__', '__lookupSetter__', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'valueOf', 'toLocaleString'];
|
|
14
14
|
|
|
15
15
|
module.exports = {
|
|
16
16
|
tests: [
|