@nxtedition/nxt-undici 7.3.20 → 7.3.22

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
@@ -176,7 +176,8 @@ export interface CacheStore {
176
176
  key: CacheKey,
177
177
  value: CacheValue & { body: null | Buffer | Buffer[]; start: number; end: number },
178
178
  ): void
179
- purgeStale(): void
179
+ gc(): void
180
+ clear(): void
180
181
  close(): void
181
182
  }
182
183
 
@@ -242,7 +243,8 @@ export class SqliteCacheStore implements CacheStore {
242
243
  key: CacheKey,
243
244
  value: CacheValue & { body: null | Buffer | Buffer[]; start: number; end: number },
244
245
  ): void
245
- purgeStale(): void
246
+ gc(): void
247
+ clear(): void
246
248
  close(): void
247
249
  }
248
250
 
@@ -52,7 +52,7 @@ class Handler extends DecoratorHandler {
52
52
  return super.onHeaders(statusCode, headers, resume)
53
53
  }
54
54
 
55
- if (isDisturbed(this.#opts.body)) {
55
+ if (statusCode !== 303 && isDisturbed(this.#opts.body)) {
56
56
  throw new Error(`Disturbed request cannot be redirected.`)
57
57
  }
58
58
 
@@ -102,8 +102,12 @@ class Handler extends DecoratorHandler {
102
102
 
103
103
  // https://tools.ietf.org/html/rfc7231#section-6.4.4
104
104
  // In case of HTTP 303, always replace method to be either HEAD or GET
105
- if (statusCode === 303 && this.#opts.method !== 'HEAD') {
106
- this.#opts = { ...this.#opts, method: 'GET', body: null }
105
+ if (statusCode === 303) {
106
+ this.#opts = {
107
+ ...this.#opts,
108
+ method: this.#opts.method !== 'HEAD' ? 'GET' : 'HEAD',
109
+ body: null,
110
+ }
107
111
  }
108
112
  }
109
113
 
@@ -4,7 +4,7 @@ import { parseRangeHeader, getFastNow } from './utils.js'
4
4
  // Bump version when the URL key format or schema changes to invalidate old caches.
5
5
  const VERSION = 10
6
6
 
7
- /** @typedef {{ purgeStale: () => void } } */
7
+ /** @typedef {{ gc: () => void, clear: () => void } } */
8
8
  const stores = new Set()
9
9
 
10
10
  {
@@ -12,7 +12,17 @@ const stores = new Set()
12
12
  offPeakBC.unref()
13
13
  offPeakBC.onmessage = () => {
14
14
  for (const store of stores) {
15
- store.purgeStale()
15
+ store.gc()
16
+ }
17
+ }
18
+ }
19
+
20
+ {
21
+ const clearCacheBC = new BroadcastChannel('nxt:clearCache')
22
+ clearCacheBC.unref()
23
+ clearCacheBC.onmessage = () => {
24
+ for (const store of stores) {
25
+ store.clear()
16
26
  }
17
27
  }
18
28
  }
@@ -42,6 +52,11 @@ export class SqliteCacheStore {
42
52
  */
43
53
  #db
44
54
 
55
+ /**
56
+ * @type {number}
57
+ */
58
+ #dbTimeout = 20
59
+
45
60
  /**
46
61
  * @type {import('node:sqlite').StatementSync}
47
62
  */
@@ -69,7 +84,11 @@ export class SqliteCacheStore {
69
84
  * @param {import('undici-types/cache-interceptor.d.ts').default.SqliteCacheStoreOpts & { maxSize?: number } | undefined} opts
70
85
  */
71
86
  constructor(opts) {
72
- this.#db = new DatabaseSync(opts?.location ?? ':memory:', { timeout: 20, ...opts?.db })
87
+ this.#dbTimeout = opts?.db?.timeout ?? this.#dbTimeout
88
+ this.#db = new DatabaseSync(opts?.location ?? ':memory:', {
89
+ ...opts?.db,
90
+ timeout: this.#dbTimeout,
91
+ })
73
92
 
74
93
  const maxSize = opts?.maxSize ?? 256 * 1024 * 1024
75
94
  this.#db.exec(`
@@ -157,13 +176,43 @@ export class SqliteCacheStore {
157
176
  stores.add(this)
158
177
  }
159
178
 
160
- purgeStale() {
179
+ gc() {
161
180
  try {
181
+ this.#db.exec('PRAGMA busy_timeout = 1000')
162
182
  this.#deleteExpiredValuesQuery.run(getFastNow())
163
183
  this.#db.exec('PRAGMA wal_checkpoint(TRUNCATE)')
164
184
  this.#db.exec('PRAGMA optimize')
165
185
  } catch (err) {
166
186
  process.emitWarning(err)
187
+ } finally {
188
+ try {
189
+ this.#db.exec(`PRAGMA busy_timeout = ${this.#dbTimeout}`)
190
+ } catch (err) {
191
+ process.emitWarning(err)
192
+ }
193
+ }
194
+ }
195
+
196
+ clear() {
197
+ this.#insertBatch.length = 0
198
+
199
+ if (this.#closed) {
200
+ return
201
+ }
202
+
203
+ try {
204
+ this.#db.exec('PRAGMA busy_timeout = 1000')
205
+ this.#db.exec(`DELETE FROM cacheInterceptorV${VERSION}`)
206
+ this.#db.exec('PRAGMA wal_checkpoint(TRUNCATE)')
207
+ this.#db.exec('PRAGMA optimize')
208
+ } catch (err) {
209
+ process.emitWarning(err)
210
+ } finally {
211
+ try {
212
+ this.#db.exec(`PRAGMA busy_timeout = ${this.#dbTimeout}`)
213
+ } catch (err) {
214
+ process.emitWarning(err)
215
+ }
167
216
  }
168
217
  }
169
218
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/nxt-undici",
3
- "version": "7.3.20",
3
+ "version": "7.3.22",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "main": "lib/index.js",