@nxtedition/lib 27.0.4 → 27.0.6

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.
Files changed (3) hide show
  1. package/app.js +1 -4
  2. package/couch.js +69 -23
  3. package/package.json +16 -11
package/app.js CHANGED
@@ -589,10 +589,7 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
589
589
  if (numa != null) {
590
590
  try {
591
591
  const affinity = numa.setAffinity(numa)
592
- logger.debug(
593
- { hostname: config.hostname, numa, affinity },
594
- 'net numa succeeded',
595
- )
592
+ logger.debug({ hostname: config.hostname, numa, affinity }, 'net numa succeeded')
596
593
  } catch (err) {
597
594
  logger.error({ err, hostname: config.hostname, numa }, 'net numa failed')
598
595
  }
package/couch.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import assert from 'node:assert'
2
2
  import stream from 'node:stream'
3
3
  import querystring from 'node:querystring'
4
+ import tp from 'node:timers/promises'
5
+
4
6
  import createError from 'http-errors'
5
- import { makeWeakCache } from '@nxtedition/weak-cache'
6
- import { defaultDelay as delay } from './http.js'
7
7
  import urljoin from 'url-join'
8
- import { AbortError } from './errors.js'
9
- import { dispatch, Agent, Pool, request as undiciRequest } from '@nxtedition/nxt-undici'
10
8
  import urlJoin from 'url-join'
11
9
 
10
+ import { dispatch, Agent, Pool, request as undiciRequest } from '@nxtedition/nxt-undici'
11
+ import { makeWeakCache } from '@nxtedition/weak-cache'
12
+
13
+ import { AbortError } from './errors.js'
14
+
12
15
  export function makeCouch(opts) {
13
16
  let config
14
17
  if (typeof opts === 'string') {
@@ -249,6 +252,7 @@ export function makeCouch(opts) {
249
252
  blocking = live || !params.limit || params.limit > 256,
250
253
  }) {
251
254
  let retryCount = 0
255
+ let retryTime = 0
252
256
  while (true) {
253
257
  let src
254
258
  try {
@@ -279,6 +283,7 @@ export function makeCouch(opts) {
279
283
  const ures = await undiciRequest(ureq)
280
284
 
281
285
  retryCount = 0
286
+ retryTime = 0
282
287
 
283
288
  src = ures.body
284
289
 
@@ -288,6 +293,7 @@ export function makeCouch(opts) {
288
293
  let error = null
289
294
  let ended = false
290
295
  let state = 0
296
+ let since = params.since || '0'
291
297
 
292
298
  function maybeResume() {
293
299
  if (resume) {
@@ -328,8 +334,8 @@ export function makeCouch(opts) {
328
334
  for (const line of lines) {
329
335
  if (line === '') {
330
336
  // hearbeat
331
- const ret = []
332
- ret.lastSeq = params.since
337
+ const ret = changes.splice(0)
338
+ ret.lastSeq = params.since = since
333
339
  yield ret
334
340
  } else if (line === ',') {
335
341
  // Do nothing. Couch sometimes insert new line between
@@ -337,9 +343,9 @@ export function makeCouch(opts) {
337
343
  } else if (live) {
338
344
  const data = JSON.parse(line)
339
345
  if (data.last_seq) {
340
- params.since = data.last_seq
346
+ since = data.last_seq
341
347
  } else {
342
- params.since = data.seq || params.since
348
+ since = data.seq || since
343
349
  changes.push(data)
344
350
  }
345
351
  } else {
@@ -358,7 +364,7 @@ export function makeCouch(opts) {
358
364
  try {
359
365
  assert(idx >= 0, 'invalid row: ' + idx + ' ' + line)
360
366
  const change = JSON.parse(line.slice(0, idx))
361
- params.since = change.seq || params.since
367
+ since = change.seq || since
362
368
  changes.push(change)
363
369
  } catch (err) {
364
370
  throw Object.assign(err, { data: line })
@@ -373,7 +379,7 @@ export function makeCouch(opts) {
373
379
  }
374
380
  } else if (changes.length) {
375
381
  const ret = changes.splice(0)
376
- ret.lastSeq = params.since
382
+ ret.lastSeq = params.since = since
377
383
  yield ret
378
384
  } else if (error) {
379
385
  throw error
@@ -382,26 +388,66 @@ export function makeCouch(opts) {
382
388
  resume = resolve
383
389
  })
384
390
  } else {
385
- const ret = []
386
- ret.lastSeq = params.since
391
+ const ret = changes.splice(0)
392
+ ret.lastSeq = params.since = since
387
393
  yield ret
388
394
  return
389
395
  }
390
396
  }
391
397
  } catch (err) {
392
- if (err.name === 'AbortError') {
398
+ if (err.name === 'AbortError' || !retry) {
393
399
  throw err
394
- } else if (typeof retry === 'function') {
395
- const retryState = { since: params.since }
396
- Object.assign(
397
- retryState,
398
- await retry(err, retryCount++, retryState, { signal, logger }, () =>
399
- delay(err, retryCount, { signal, logger }),
400
- ),
401
- )
402
- params.since = retryState.since ?? 0
403
400
  } else {
404
- await delay(err, retryCount, { signal, logger })
401
+ retryTime ||= Date.now()
402
+ const retryState = { since: params.since, time: retryTime, count: retryCount }
403
+ await retry(err, retryCount++, retryState, { signal, logger }, () => {
404
+ const { statusCode, code, message, headers } = err
405
+
406
+ if (retryTime && Date.now() - retryTime > 2 * 60e3) {
407
+ throw err
408
+ }
409
+
410
+ if (statusCode && [420, 429, 502, 503, 504].includes(statusCode)) {
411
+ const retryAfter = headers?.['retry-after']
412
+ ? Number(headers['retry-after']) * 1e3
413
+ : null
414
+ const delay =
415
+ retryAfter != null && Number.isFinite(retryAfter)
416
+ ? retryAfter
417
+ : Math.min(10e3, retryCount * 1e3)
418
+ return tp.setTimeout(delay, true, { signal: opts?.signal ?? undefined })
419
+ }
420
+
421
+ if (
422
+ [
423
+ 'ECONNRESET',
424
+ 'ECONNREFUSED',
425
+ 'ENOTFOUND',
426
+ 'ENETDOWN',
427
+ 'ENETUNREACH',
428
+ 'EHOSTDOWN',
429
+ 'EHOSTUNREACH',
430
+ 'EPIPE',
431
+ 'EAI_AGAIN',
432
+ 'ENODATA',
433
+ 'UND_ERR_CONNECT_TIMEOUT',
434
+ 'UND_ERR_SOCKET',
435
+ ].includes(code)
436
+ ) {
437
+ return tp.setTimeout(Math.min(10e3, retryCount * 1e3), true, {
438
+ signal: opts?.signal ?? undefined,
439
+ })
440
+ }
441
+
442
+ if (['other side closed'].includes(message)) {
443
+ return tp.setTimeout(Math.min(10e3, retryCount * 1e3), true, {
444
+ signal: opts?.signal ?? undefined,
445
+ })
446
+ }
447
+
448
+ throw err
449
+ })
450
+ params.since = retryState.since ?? 0
405
451
  }
406
452
  } finally {
407
453
  src?.on('error', () => {}).destroy()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "27.0.4",
3
+ "version": "27.0.6",
4
4
  "license": "UNLICENSED",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "type": "module",
@@ -44,19 +44,20 @@
44
44
  "under-pressure.js"
45
45
  ],
46
46
  "scripts": {
47
- "test": "node --test-timeout 60000 --test",
48
- "test:types": "tsd"
47
+ "test": "node --test-timeout 60000 --test"
49
48
  },
50
49
  "dependencies": {
51
50
  "@elastic/elasticsearch": "^8.17.1",
52
51
  "@elastic/transport": "^8.9.3",
53
- "@nxtedition/nxt-undici": "^6.4.17",
52
+ "@nxtedition/nxt-undici": "^7.1.4",
54
53
  "@nxtedition/sched": "^1.0.2",
55
- "@nxtedition/template": "^1.0.0",
56
- "@nxtedition/weak-cache": "^1.0.0",
54
+ "@nxtedition/template": "^1.0.2",
55
+ "@nxtedition/weak-cache": "^1.0.1",
57
56
  "diff": "5.2.0",
57
+ "eslint": "^9.38.0",
58
58
  "fast-querystring": "^1.1.2",
59
59
  "http-errors": "^2.0.0",
60
+ "lerna": "^9.0.0",
60
61
  "lodash": "^4.17.21",
61
62
  "lru-cache": "^11.2.2",
62
63
  "mime": "^4.0.7",
@@ -66,18 +67,22 @@
66
67
  "pino": "^10.1.0",
67
68
  "qs": "^6.14.0",
68
69
  "request-target": "^1.0.2",
70
+ "typescript-eslint": "^8.46.2",
69
71
  "url-join": "^5.0.0",
70
72
  "xuid": "^4.1.5",
71
- "yocto-queue": "^1.2.1"
73
+ "yocto-queue": "^1.2.2"
72
74
  },
73
75
  "devDependencies": {
74
- "@nxtedition/deepstream.io-client-js": ">=31.2.1",
76
+ "@nxtedition/deepstream.io-client-js": ">=31.2.9",
75
77
  "@types/lodash": "^4.17.20",
76
- "@types/node": "^24.9.1",
78
+ "@types/node": "^24.10.1",
77
79
  "canvas": "^3.1.0",
80
+ "eslint": "^9.39.1",
81
+ "lerna": "^9.0.1",
78
82
  "rxjs": "^7.8.2",
79
83
  "tsd": "^0.33.0",
80
- "typescript": "^5.9.3"
84
+ "typescript": "^5.9.3",
85
+ "typescript-eslint": "^8.46.4"
81
86
  },
82
87
  "peerDependencies": {
83
88
  "@elastic/elasticsearch": "^8.6.0",
@@ -87,5 +92,5 @@
87
92
  "pino": ">=7.0.0",
88
93
  "rxjs": "^7.0.0"
89
94
  },
90
- "gitHead": "be0475e7b0d724ba6f2f9fdbaa0c3f069e49e6a7"
95
+ "gitHead": "0a3d683b790eeeb5f198316a27e205f84bf93c9e"
91
96
  }