pixl-server-storage 4.0.3 → 4.1.1
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 +81 -10
- package/engines/Couchbase.js +0 -1
- package/engines/Filesystem.js +59 -28
- package/engines/Postgres.js +515 -0
- package/engines/Redis.js +129 -29
- package/engines/RedisCluster.js +128 -29
- package/engines/S3.js +53 -25
- package/engines/SQLite.js +65 -22
- package/package.json +1 -1
- package/test/config.json +19 -0
- package/test/data/backups/backup-2026-04-05-20-23-56.db.gz +0 -0
- package/test/data/backups/backup-2026-06-08-20-33-01.db.gz +0 -0
- package/test/data/backups/backup-2026-02-15-18-10-21.db.gz +0 -0
- package/test/data/backups/backup-2026-02-15-18-10-33.db.gz +0 -0
package/engines/SQLite.js
CHANGED
|
@@ -153,6 +153,7 @@ module.exports = Class.create({
|
|
|
153
153
|
err.message = "Failed to store object: " + key + ": " + err;
|
|
154
154
|
self.logError('sqlite', '' + err);
|
|
155
155
|
if (callback) callback(err);
|
|
156
|
+
return;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
self.logDebug(9, "Store complete: " + key);
|
|
@@ -190,13 +191,22 @@ module.exports = Class.create({
|
|
|
190
191
|
if (this.cache && this.cache.has(key)) {
|
|
191
192
|
var item = this.cache.getMeta(key);
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
194
|
+
if (item.value.length == 0) {
|
|
195
|
+
process.nextTick( function() {
|
|
196
|
+
var err = new Error("Failed to head key: " + key + ": Not found");
|
|
197
|
+
err.code = "NoSuchKey";
|
|
198
|
+
callback( err );
|
|
198
199
|
} );
|
|
199
|
-
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
process.nextTick( function() {
|
|
203
|
+
self.logDebug(9, "Cached head complete: " + key);
|
|
204
|
+
callback( null, {
|
|
205
|
+
mod: item.date,
|
|
206
|
+
len: item.value.length
|
|
207
|
+
} );
|
|
208
|
+
} );
|
|
209
|
+
}
|
|
200
210
|
return;
|
|
201
211
|
} // cache
|
|
202
212
|
|
|
@@ -208,12 +218,18 @@ module.exports = Class.create({
|
|
|
208
218
|
catch (err) {
|
|
209
219
|
err.message = "Failed to head key: " + key + ": " + err;
|
|
210
220
|
self.logError('sqlite', '' + err);
|
|
211
|
-
callback(err);
|
|
221
|
+
return callback(err);
|
|
212
222
|
}
|
|
213
223
|
|
|
214
224
|
if (!row) {
|
|
215
225
|
var err = new Error("Failed to head key: " + key + ": Not found");
|
|
216
226
|
err.code = "NoSuchKey";
|
|
227
|
+
|
|
228
|
+
if (self.cache && !self.storage.isBinaryKey(key)) {
|
|
229
|
+
// store 'empty' stub in cache
|
|
230
|
+
self.cache.set( key, Buffer.alloc(0), { date: 0 } );
|
|
231
|
+
}
|
|
232
|
+
|
|
217
233
|
return callback(err, null);
|
|
218
234
|
}
|
|
219
235
|
callback(null, { mod: row.modified, len: row['length(value)'] });
|
|
@@ -229,19 +245,29 @@ module.exports = Class.create({
|
|
|
229
245
|
|
|
230
246
|
// check cache first
|
|
231
247
|
if (this.cache && !is_binary && this.cache.has(key)) {
|
|
232
|
-
var
|
|
248
|
+
var item = this.cache.getMeta(key);
|
|
233
249
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
callback(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
250
|
+
if (item.value.length == 0) {
|
|
251
|
+
process.nextTick( function() {
|
|
252
|
+
var err = new Error("Failed to fetch key: " + key + ": Not found");
|
|
253
|
+
err.code = "NoSuchKey";
|
|
254
|
+
callback( err );
|
|
255
|
+
} );
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
process.nextTick( function() {
|
|
259
|
+
var data = null;
|
|
260
|
+
try { data = JSON.parse( item.value.toString() ); }
|
|
261
|
+
catch (e) {
|
|
262
|
+
self.logError('file', "Failed to parse JSON record: " + key + ": " + e);
|
|
263
|
+
callback( e, null );
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
self.logDebug(9, "Cached JSON fetch complete: " + key, self.debugLevel(10) ? data : null);
|
|
267
|
+
|
|
268
|
+
callback( null, data );
|
|
269
|
+
} );
|
|
270
|
+
}
|
|
245
271
|
return;
|
|
246
272
|
} // cache
|
|
247
273
|
|
|
@@ -256,11 +282,18 @@ module.exports = Class.create({
|
|
|
256
282
|
err.message = "Failed to fetch key: " + key + ": " + err;
|
|
257
283
|
self.logError('sqlite', '' + err);
|
|
258
284
|
callback(err);
|
|
285
|
+
return;
|
|
259
286
|
}
|
|
260
287
|
|
|
261
288
|
if (!row) {
|
|
262
289
|
var err = new Error("Failed to fetch key: " + key + ": Not found");
|
|
263
290
|
err.code = "NoSuchKey";
|
|
291
|
+
|
|
292
|
+
if (self.cache && !is_binary) {
|
|
293
|
+
// store 'empty' stub in cache
|
|
294
|
+
self.cache.set( key, Buffer.alloc(0), { date: 0 } );
|
|
295
|
+
}
|
|
296
|
+
|
|
264
297
|
return callback(err, null);
|
|
265
298
|
}
|
|
266
299
|
if (is_binary) {
|
|
@@ -297,6 +330,7 @@ module.exports = Class.create({
|
|
|
297
330
|
err.message = "Failed to fetch key: " + key + ": " + err;
|
|
298
331
|
self.logError('sqlite', '' + err);
|
|
299
332
|
callback(err);
|
|
333
|
+
return;
|
|
300
334
|
}
|
|
301
335
|
|
|
302
336
|
if (!row) {
|
|
@@ -365,7 +399,6 @@ module.exports = Class.create({
|
|
|
365
399
|
end = buf.length ? buf.length - 1 : 0;
|
|
366
400
|
}
|
|
367
401
|
if (isNaN(start) || isNaN(end) || (start < 0) || (start >= buf.length) || (end < start) || (end >= buf.length)) {
|
|
368
|
-
download.destroy();
|
|
369
402
|
callback( new Error("Invalid byte range (" + start + '-' + end + ") for key: " + key + " (len: " + buf.length + ")"), null );
|
|
370
403
|
return;
|
|
371
404
|
}
|
|
@@ -391,16 +424,26 @@ module.exports = Class.create({
|
|
|
391
424
|
catch (err) {
|
|
392
425
|
self.logError('sqlite', "Failed to delete object: " + key + ": " + err);
|
|
393
426
|
callback(err);
|
|
427
|
+
return;
|
|
394
428
|
}
|
|
395
429
|
|
|
396
430
|
if (!info.changes) {
|
|
397
431
|
var err = new Error("Failed to delete object: " + key + ": Not found");
|
|
398
432
|
err.code = "NoSuchKey";
|
|
433
|
+
|
|
434
|
+
if (self.cache && !self.storage.isBinaryKey(key)) {
|
|
435
|
+
// store 'empty' stub in cache
|
|
436
|
+
self.cache.set( key, Buffer.alloc(0), { date: 0 } );
|
|
437
|
+
}
|
|
438
|
+
|
|
399
439
|
return callback(err);
|
|
400
440
|
}
|
|
401
441
|
self.logDebug(9, "Delete complete: " + key);
|
|
402
|
-
|
|
403
|
-
|
|
442
|
+
|
|
443
|
+
// possibly "delete" from LRU cache as well
|
|
444
|
+
if (self.cache && !self.storage.isBinaryKey(key)) {
|
|
445
|
+
// store 'empty' stub in cache
|
|
446
|
+
self.cache.set( key, Buffer.alloc(0), { date: 0 } );
|
|
404
447
|
}
|
|
405
448
|
callback();
|
|
406
449
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-server-storage",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
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/test/config.json
CHANGED
|
@@ -84,6 +84,25 @@
|
|
|
84
84
|
"compress": true,
|
|
85
85
|
"keep": 7
|
|
86
86
|
}
|
|
87
|
+
},
|
|
88
|
+
"Postgres": {
|
|
89
|
+
"min": 0,
|
|
90
|
+
"max": 32,
|
|
91
|
+
"host": "localhost",
|
|
92
|
+
"database": "postgres",
|
|
93
|
+
"user": "postgres",
|
|
94
|
+
"password": "postgres",
|
|
95
|
+
"port": 5432,
|
|
96
|
+
"statement_timeout": 5000,
|
|
97
|
+
"query_timeout": 6000,
|
|
98
|
+
"connectionTimeoutMillis": 30000,
|
|
99
|
+
"idleTimeoutMillis": 10000,
|
|
100
|
+
"table": "items",
|
|
101
|
+
"cache": {
|
|
102
|
+
"enabled": true,
|
|
103
|
+
"maxItems": 100000,
|
|
104
|
+
"maxBytes": 104857600
|
|
105
|
+
}
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|