pixl-server-storage 4.2.2 → 4.3.0
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 +30 -2
- package/engines/Filesystem.js +1 -1
- package/engines/Postgres.js +1 -1
- package/engines/Redis.js +1 -1
- package/engines/RedisCluster.js +1 -1
- package/engines/S3.js +1 -1
- package/engines/SQLite.js +1 -1
- package/package.json +2 -2
- package/transaction.js +2 -1
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ Here is the table of contents for this current document:
|
|
|
65
65
|
+ [AWS RDS](#aws-rds)
|
|
66
66
|
+ [Postgres Password Plugin](#postgres-password-plugin)
|
|
67
67
|
* [Hybrid](#hybrid)
|
|
68
|
+
- [Cache Buffer Copying](#cache-buffer-copying)
|
|
68
69
|
- [Key Normalization](#key-normalization)
|
|
69
70
|
- [Basic Functions](#basic-functions)
|
|
70
71
|
* [Storing Records](#storing-records)
|
|
@@ -417,8 +418,9 @@ The properties are as follows:
|
|
|
417
418
|
| `enabled` | Boolean | Set this to `true` to enable the filesystem caching system. |
|
|
418
419
|
| `maxItems` | Integer | This is the maximum number of objects to allow in the cache. |
|
|
419
420
|
| `maxBytes` | Integer | This is the maximum number of bytes to allow in the cache. |
|
|
421
|
+
| `copyBuffers` | Boolean | Defaults to `true`. Stores independent, unpooled copies of cached Buffers. Set to `false` to opt out. See [Cache Buffer Copying](#cache-buffer-copying). |
|
|
420
422
|
|
|
421
|
-
The cache will automatically expire objects in LRU fashion when either of the limits are exceeded (whichever is hit first). Set
|
|
423
|
+
The cache will automatically expire objects in LRU fashion when either of the limits are exceeded (whichever is hit first). Set either limit to `0` for no limit.
|
|
422
424
|
|
|
423
425
|
Note that binary records are **not** cached. This system is for JSON records only.
|
|
424
426
|
|
|
@@ -518,8 +520,9 @@ The properties are as follows:
|
|
|
518
520
|
| `enabled` | Boolean | Set this to `true` to enable the S3 caching system. |
|
|
519
521
|
| `maxItems` | Integer | This is the maximum number of objects to allow in the cache. |
|
|
520
522
|
| `maxBytes` | Integer | This is the maximum number of bytes to allow in the cache. |
|
|
523
|
+
| `copyBuffers` | Boolean | Defaults to `true`. Stores independent, unpooled copies of cached Buffers. Set to `false` to opt out. See [Cache Buffer Copying](#cache-buffer-copying). |
|
|
521
524
|
|
|
522
|
-
The cache will automatically expire objects in LRU fashion when either of the limits are met (whichever is reached first). Set
|
|
525
|
+
The cache will automatically expire objects in LRU fashion when either of the limits are met (whichever is reached first). Set either limit to `0` for no limit.
|
|
523
526
|
|
|
524
527
|
It is recommended that you set the `maxItems` and `maxBytes` high enough to allow new data written to live for *at least* several seconds before getting expired out of the cache. This depends on the overall storage throughput of your application, but 1,000 max items and 10 MB max bytes is probably fine for most use cases.
|
|
525
528
|
|
|
@@ -1055,6 +1058,31 @@ Note that all of the engine configuration objects are on the same level as the `
|
|
|
1055
1058
|
|
|
1056
1059
|
When transactions are enabled, the `Hybrid` engine routes transaction commits through the configured `docEngine`, because pixl-server-storage transactions only apply to JSON records. If the `docEngine` supports native transactions, such as Postgres, Redis or SQLite, `Hybrid` will use that native commit path automatically. The `binaryEngine` is not involved in transactions, because binary keys are passed straight through.
|
|
1057
1060
|
|
|
1061
|
+
# Cache Buffer Copying
|
|
1062
|
+
|
|
1063
|
+
All six engine caches (`Filesystem`, `S3`, `Redis`, `RedisCluster`, `SQLite`, and `Postgres`) default to `copyBuffers: true`. This applies whenever the engine's cache is enabled with `cache.enabled: true`; existing cache configurations receive the new default automatically.
|
|
1064
|
+
|
|
1065
|
+
These caches store serialized JSON records as Buffers. A small Buffer can share a much larger memory allocation with other Buffers, and keeping it in the cache can retain that entire allocation. Node.js 24.18.0 increased the default Buffer pool size from 8 KiB to 64 KiB, making this retention more costly. See the [Node.js 24.18.0 release notes](https://nodejs.org/en/blog/release/v24.18.0).
|
|
1066
|
+
|
|
1067
|
+
The Postgres report in [issue #8](https://github.com/jhuckaby/pixl-server-storage/issues/8) demonstrated how retained backing allocations could greatly exceed the cached payload size. The same retention pattern can affect all six engines, so Buffer copying is enabled by default across their caches. Each cached Buffer gets its own unpooled copy when added or replaced, preventing it from retaining an oversized shared allocation. This adds an allocation and byte copy on insertion, but cache hits do not make additional Buffer copies. The `maxBytes` setting still measures cache key and value sizes, rather than total process memory.
|
|
1068
|
+
|
|
1069
|
+
If you need to avoid the extra copying, set `copyBuffers` to `false` inside your engine's `cache` configuration. For example, merge this fragment into your existing `Storage` configuration for Postgres:
|
|
1070
|
+
|
|
1071
|
+
```json
|
|
1072
|
+
{
|
|
1073
|
+
"Postgres": {
|
|
1074
|
+
"cache": {
|
|
1075
|
+
"enabled": true,
|
|
1076
|
+
"maxItems": 100000,
|
|
1077
|
+
"maxBytes": 104857600,
|
|
1078
|
+
"copyBuffers": false
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
Use the same `cache.copyBuffers` property inside any of the other five engine configuration blocks. Caching remains enabled in this example, while disabling Buffer copying restores the previous retention behavior. Omit `copyBuffers`, or set it to `true`, to use the recommended default.
|
|
1085
|
+
|
|
1058
1086
|
# Key Normalization
|
|
1059
1087
|
|
|
1060
1088
|
In order to maintain compatibility with all the various engines, keys are "normalized" on all entry points. Specifically, they undergo the following transformations before being passed along to the engine:
|
package/engines/Filesystem.js
CHANGED
|
@@ -80,7 +80,7 @@ module.exports = Class.create({
|
|
|
80
80
|
var cache_opts = this.config.get('cache');
|
|
81
81
|
if (cache_opts && cache_opts.enabled) {
|
|
82
82
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
83
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
83
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
84
84
|
this.cache.on('expire', function(item, reason) {
|
|
85
85
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
86
86
|
key: item.key,
|
package/engines/Postgres.js
CHANGED
|
@@ -67,7 +67,7 @@ module.exports = Class.create({
|
|
|
67
67
|
var cache_opts = pg_config.cache;
|
|
68
68
|
if (cache_opts && cache_opts.enabled) {
|
|
69
69
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
70
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
70
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
71
71
|
this.cache.on('expire', function(item, reason) {
|
|
72
72
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
73
73
|
key: item.key,
|
package/engines/Redis.js
CHANGED
|
@@ -54,7 +54,7 @@ module.exports = Class.create({
|
|
|
54
54
|
var cache_opts = r_config.cache;
|
|
55
55
|
if (cache_opts && cache_opts.enabled) {
|
|
56
56
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
57
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
57
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
58
58
|
this.cache.on('expire', function(item, reason) {
|
|
59
59
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
60
60
|
key: item.key,
|
package/engines/RedisCluster.js
CHANGED
|
@@ -56,7 +56,7 @@ module.exports = Class.create({
|
|
|
56
56
|
var cache_opts = r_config.cache;
|
|
57
57
|
if (cache_opts && cache_opts.enabled) {
|
|
58
58
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
59
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
59
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
60
60
|
this.cache.on('expire', function(item, reason) {
|
|
61
61
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
62
62
|
key: item.key,
|
package/engines/S3.js
CHANGED
|
@@ -49,7 +49,7 @@ module.exports = Class.create({
|
|
|
49
49
|
var cache_opts = s3_config.cache;
|
|
50
50
|
if (cache_opts && cache_opts.enabled) {
|
|
51
51
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
52
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
52
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
53
53
|
this.cache.on('expire', function(item, reason) {
|
|
54
54
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
55
55
|
key: item.key,
|
package/engines/SQLite.js
CHANGED
|
@@ -68,7 +68,7 @@ module.exports = Class.create({
|
|
|
68
68
|
var cache_opts = this.config.get('cache');
|
|
69
69
|
if (cache_opts && cache_opts.enabled) {
|
|
70
70
|
this.logDebug(3, "Setting up LRU cache", cache_opts);
|
|
71
|
-
this.cache = new Cache( Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) );
|
|
71
|
+
this.cache = new Cache({ copyBuffers: true, ...Tools.copyHashRemoveKeys(cache_opts, { enabled: 1 }) });
|
|
72
72
|
this.cache.on('expire', function(item, reason) {
|
|
73
73
|
self.logDebug(9, "Expiring LRU cache object: " + item.key + " due to: " + reason, {
|
|
74
74
|
key: item.key,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-server-storage",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
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",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"he": "1.1.1",
|
|
31
31
|
"moo": "0.4.3",
|
|
32
32
|
"nearley": "2.20.1",
|
|
33
|
-
"pixl-cache": "^1.
|
|
33
|
+
"pixl-cache": "^1.1.2",
|
|
34
34
|
"pixl-class": "^1.0.3",
|
|
35
35
|
"pixl-perf": "^1.0.9",
|
|
36
36
|
"pixl-server": "^1.0.39",
|
package/transaction.js
CHANGED
|
@@ -575,7 +575,8 @@ module.exports = Class.create({
|
|
|
575
575
|
trans.aborting = true;
|
|
576
576
|
|
|
577
577
|
var num_actions = Tools.numKeys(trans.keys || {});
|
|
578
|
-
this.logError('rollback', "Aborting transaction: " + trans.id, { path: path, actions: num_actions });
|
|
578
|
+
if (num_actions) this.logError('rollback', "Aborting transaction: " + trans.id, { path: path, actions: num_actions });
|
|
579
|
+
else this.logDebug(6, "Aborting empty transaction (no-op): " + trans.id, { path: path, actions: num_actions });
|
|
579
580
|
|
|
580
581
|
// read in file line by line
|
|
581
582
|
// (file may not exist, which is fine, hence 'ignore_not_found')
|