@nxtedition/cache 2.1.5 → 2.1.7

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/lib/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface DatabaseOptions {
7
7
  }
8
8
  export interface LockOptions {
9
9
  minTimeout?: number;
10
+ maxTimeout?: number;
10
11
  }
11
12
  export interface Serializer<V> {
12
13
  serialize: (value: V) => Buffer | Uint8Array | string;
package/lib/index.js CHANGED
@@ -39,6 +39,7 @@ const dbs = new Set ()
39
39
 
40
40
 
41
41
 
42
+
42
43
 
43
44
 
44
45
 
@@ -96,6 +97,7 @@ export class Cache extends EventEmi
96
97
  #lockMean = 5
97
98
  #lockTimeout = 10
98
99
  #lockMinTimeout = 1
100
+ #lockMaxTimeout = 1_000
99
101
 
100
102
  #location
101
103
  #database = null
@@ -176,6 +178,12 @@ export class Cache extends EventEmi
176
178
  this.#lockTimeout = this.#lockMinTimeout
177
179
  this.#lockMean = this.#lockTimeout / 1.2
178
180
  }
181
+ if (opts.lock.maxTimeout !== undefined) {
182
+ if (typeof opts.lock.maxTimeout !== 'number') {
183
+ throw new TypeError('lock.maxTimeout must be a number')
184
+ }
185
+ this.#lockMaxTimeout = Math.max(this.#lockMinTimeout, opts.lock.maxTimeout)
186
+ }
179
187
  }
180
188
 
181
189
  if (opts?.serializer !== undefined) {
@@ -196,7 +204,7 @@ export class Cache extends EventEmi
196
204
 
197
205
  for (let n = 0; opts?.database !== null && opts?.database !== false; n++) {
198
206
  try {
199
- const maxSize = opts?.database?.maxSize ?? 256 * 1024 * 1024
207
+ const maxSize = opts?.database?.maxSize ?? 128 * 1024 * 1024
200
208
  const timeout = opts?.database?.timeout ?? 20
201
209
 
202
210
  this.#database ??= new DatabaseSync(location, { timeout })
@@ -709,13 +717,22 @@ export class Cache extends EventEmi
709
717
  // EMA of mean and variance (Welford-style), clamped to [10ms, 1s].
710
718
  // Timeout = mean * 1.2 + 3 * stddev: 20% base margin plus 3 standard
711
719
  // deviations to accommodate timing variability.
720
+ // Winsorize input at mean + 5σ so a single extreme outlier can't blow up the stats.
712
721
  const alpha = 0.2
713
- const diff = duration - this.#lockMean
722
+ const clamped = Math.min(
723
+ duration,
724
+ this.#lockMean + 5 * Math.sqrt(this.#lockVar),
725
+ this.#lockMaxTimeout,
726
+ )
727
+ const diff = clamped - this.#lockMean
714
728
  this.#lockMean += alpha * diff
715
729
  this.#lockVar = (1 - alpha) * (this.#lockVar + alpha * diff * diff)
716
730
  this.#lockTimeout = Math.max(
717
731
  this.#lockMinTimeout,
718
- Math.min(1_000, Math.ceil(this.#lockMean * 1.2 + Math.sqrt(this.#lockVar) * 3)),
732
+ Math.min(
733
+ this.#lockMaxTimeout,
734
+ Math.ceil(this.#lockMean * 1.2 + Math.sqrt(this.#lockVar) * 3),
735
+ ),
719
736
  )
720
737
  }
721
738
 
package/lib/memory.js CHANGED
@@ -13,7 +13,10 @@
13
13
 
14
14
 
15
15
 
16
- const maxInt = 2147483647
16
+ let fastNow = Date.now()
17
+ setInterval(() => {
18
+ fastNow = Date.now()
19
+ }, 1e3).unref()
17
20
 
18
21
  export class MemoryCache {
19
22
  #map = new Map()
@@ -25,7 +28,6 @@ export class MemoryCache {
25
28
  #size = 0
26
29
  #count = 0
27
30
 
28
- #counter = 0
29
31
  #cork = 0
30
32
 
31
33
  constructor(opts ) {
@@ -42,8 +44,6 @@ export class MemoryCache {
42
44
  }
43
45
 
44
46
  set(key , entry ) {
45
- this.#counter = (this.#counter + 1) & maxInt
46
-
47
47
  const existing = this.#map.get(key)
48
48
  if (existing != null) {
49
49
  this.#delete(existing)
@@ -52,7 +52,7 @@ export class MemoryCache {
52
52
  this.#map.set(key, entry)
53
53
  entry.key = key
54
54
  entry.index = this.#arr.push(entry) - 1
55
- entry.counter = this.#counter
55
+ entry.counter = fastNow
56
56
 
57
57
  this.#size += entry.size ?? 0
58
58
  this.#count += 1
@@ -76,8 +76,7 @@ export class MemoryCache {
76
76
  get(key ) {
77
77
  const entry = this.#map.get(key)
78
78
  if (entry != null) {
79
- this.#counter = (this.#counter + 1) & maxInt
80
- entry.counter = this.#counter
79
+ entry.counter = fastNow
81
80
  }
82
81
  return entry
83
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/cache",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -30,5 +30,5 @@
30
30
  "tsd": "^0.33.0",
31
31
  "typescript": "^5.9.3"
32
32
  },
33
- "gitHead": "8a59edc35cba6e3bdf43e82710a7cdbf413dc19c"
33
+ "gitHead": "160284d139399d39195532624e26d564aa8c8003"
34
34
  }