@nxtedition/lib 18.0.2 → 18.0.4
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/couch.js +105 -65
- package/package.json +1 -1
package/couch.js
CHANGED
|
@@ -5,7 +5,6 @@ import { defaultDelay as delay } from './http.js'
|
|
|
5
5
|
import querystring from 'querystring'
|
|
6
6
|
import urljoin from 'url-join'
|
|
7
7
|
import undici from 'undici'
|
|
8
|
-
import assert from 'node:assert'
|
|
9
8
|
|
|
10
9
|
// https://github.com/fastify/fastify/blob/main/lib/reqIdGenFactory.js
|
|
11
10
|
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
@@ -226,21 +225,16 @@ export function makeCouch(opts) {
|
|
|
226
225
|
}
|
|
227
226
|
}
|
|
228
227
|
|
|
229
|
-
async function*
|
|
230
|
-
let remaining = Number(options.limit) || Infinity
|
|
231
|
-
|
|
232
|
-
const params2 = {
|
|
233
|
-
...params,
|
|
234
|
-
...options.query,
|
|
235
|
-
feed: live ? 'continuous' : 'normal',
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (Number.isFinite(remaining)) {
|
|
239
|
-
params.limit = remaining
|
|
240
|
-
}
|
|
241
|
-
|
|
228
|
+
async function* continuous() {
|
|
242
229
|
const req = {
|
|
243
|
-
path:
|
|
230
|
+
path:
|
|
231
|
+
dbPathname +
|
|
232
|
+
'/_changes' +
|
|
233
|
+
`?${new URLSearchParams({
|
|
234
|
+
...params,
|
|
235
|
+
...options.query,
|
|
236
|
+
feed: 'continuous',
|
|
237
|
+
})}`,
|
|
244
238
|
idempotent: false,
|
|
245
239
|
blocking: true,
|
|
246
240
|
method,
|
|
@@ -256,68 +250,34 @@ export function makeCouch(opts) {
|
|
|
256
250
|
bodyTimeout: 2 * (params.heartbeat || 60e3),
|
|
257
251
|
}
|
|
258
252
|
|
|
259
|
-
const HEAD = '{"results":['
|
|
260
|
-
const TAIL = '],'
|
|
261
|
-
|
|
262
253
|
try {
|
|
263
254
|
const res = await client.request(req)
|
|
264
255
|
|
|
265
256
|
retryCount = 0
|
|
266
257
|
|
|
267
258
|
let str = ''
|
|
268
|
-
let state = 0
|
|
269
259
|
for await (const chunk of res.body) {
|
|
270
260
|
const lines = (str + chunk).split('\n')
|
|
271
261
|
str = lines.pop() ?? ''
|
|
272
262
|
|
|
273
|
-
const
|
|
263
|
+
const results = batched ? [] : null
|
|
274
264
|
for (const line of lines) {
|
|
275
|
-
if (line
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const data = JSON.parse(line)
|
|
280
|
-
if (data.last_seq) {
|
|
281
|
-
params.since = data.last_seq
|
|
282
|
-
assert(params.since, 'invalid last_seq: ' + params.since)
|
|
283
|
-
} else {
|
|
284
|
-
params.since = data.seq || params.since
|
|
285
|
-
changes.push(data)
|
|
265
|
+
if (line) {
|
|
266
|
+
const change = JSON.parse(line)
|
|
267
|
+
if (change.seq) {
|
|
268
|
+
params.since = change.seq
|
|
286
269
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (state === 0) {
|
|
290
|
-
if (line === HEAD) {
|
|
291
|
-
state = 1
|
|
292
|
-
} else {
|
|
293
|
-
assert(line.length < HEAD.length, 'invalid line: ' + line)
|
|
294
|
-
}
|
|
295
|
-
} else if (state === 1) {
|
|
296
|
-
if (line === TAIL) {
|
|
297
|
-
state = 2
|
|
298
|
-
} else {
|
|
299
|
-
const idx = line.lastIndexOf('}') + 1
|
|
300
|
-
assert(idx > 0, 'invalid line; ' + line)
|
|
301
|
-
const data = JSON.parse(line.slice(0, idx))
|
|
302
|
-
params.since = data.seq || params.since
|
|
303
|
-
changes.push(data)
|
|
304
|
-
}
|
|
305
|
-
} else if (state === 2) {
|
|
306
|
-
state = 3
|
|
307
|
-
params.since = JSON.parse('{' + line).last_seq
|
|
308
|
-
assert(params.since, 'invalid last_seq: ' + params.since)
|
|
270
|
+
if (results) {
|
|
271
|
+
results.push(change)
|
|
309
272
|
} else {
|
|
310
|
-
|
|
273
|
+
yield change
|
|
311
274
|
}
|
|
312
275
|
}
|
|
313
276
|
}
|
|
314
277
|
|
|
315
|
-
if (
|
|
316
|
-
yield
|
|
278
|
+
if (results?.length) {
|
|
279
|
+
yield results
|
|
317
280
|
}
|
|
318
|
-
|
|
319
|
-
remaining -= changes.length
|
|
320
|
-
assert(remaining >= 0, 'invalid remaining: ' + remaining)
|
|
321
281
|
}
|
|
322
282
|
} catch (err) {
|
|
323
283
|
Object.assign(err, { data: req })
|
|
@@ -325,15 +285,93 @@ export function makeCouch(opts) {
|
|
|
325
285
|
}
|
|
326
286
|
}
|
|
327
287
|
|
|
288
|
+
async function* normal() {
|
|
289
|
+
const batchSize =
|
|
290
|
+
options.batch_size ?? options.batchSize ?? (params.include_docs ? 512 : 4096)
|
|
291
|
+
let remaining = parseInt(options.limit) || Infinity
|
|
292
|
+
|
|
293
|
+
const next = async () => {
|
|
294
|
+
const req = {
|
|
295
|
+
path:
|
|
296
|
+
dbPathname +
|
|
297
|
+
'/_changes' +
|
|
298
|
+
`?${new URLSearchParams({
|
|
299
|
+
...params,
|
|
300
|
+
...options.query,
|
|
301
|
+
limit: Math.min(remaining, batchSize),
|
|
302
|
+
feed: live ? 'longpoll' : 'normal',
|
|
303
|
+
})}`,
|
|
304
|
+
idempotent: true,
|
|
305
|
+
blocking: live,
|
|
306
|
+
method,
|
|
307
|
+
body: JSON.stringify(body),
|
|
308
|
+
signal: ac.signal,
|
|
309
|
+
headers: {
|
|
310
|
+
'user-agent': userAgent,
|
|
311
|
+
'request-id': genReqId(),
|
|
312
|
+
...(body ? { 'content-type': 'application/json' } : {}),
|
|
313
|
+
},
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
const res = await client.request(req)
|
|
318
|
+
|
|
319
|
+
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
320
|
+
throw makeError(req, {
|
|
321
|
+
status: res.statusCode,
|
|
322
|
+
headers: res.headers,
|
|
323
|
+
data: await res.body.text(),
|
|
324
|
+
})
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return await res.body.json()
|
|
328
|
+
} catch (err) {
|
|
329
|
+
Object.assign(err, { data: req })
|
|
330
|
+
return { err }
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
let promise
|
|
335
|
+
while (remaining) {
|
|
336
|
+
const { last_seq: seq, results, err } = await (promise ?? next())
|
|
337
|
+
promise = null
|
|
338
|
+
|
|
339
|
+
if (err) {
|
|
340
|
+
throw err
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
retryCount = 0
|
|
344
|
+
|
|
345
|
+
if (seq) {
|
|
346
|
+
params.since = seq
|
|
347
|
+
if (results.length > 0 && !results.at(-1)?.seq) {
|
|
348
|
+
results.at(-1).seq = seq
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
remaining -= results.length
|
|
353
|
+
|
|
354
|
+
if (!live && results.length === 0) {
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
promise = next()
|
|
359
|
+
|
|
360
|
+
if (batched) {
|
|
361
|
+
yield results
|
|
362
|
+
} else {
|
|
363
|
+
yield* results
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
328
368
|
try {
|
|
329
369
|
while (true) {
|
|
330
370
|
try {
|
|
331
|
-
if (
|
|
332
|
-
yield*
|
|
371
|
+
if (live && !options.batchSize && !options.batch_size) {
|
|
372
|
+
yield* continuous()
|
|
333
373
|
} else {
|
|
334
|
-
|
|
335
|
-
yield* changes
|
|
336
|
-
}
|
|
374
|
+
yield* normal()
|
|
337
375
|
}
|
|
338
376
|
return
|
|
339
377
|
} catch (err) {
|
|
@@ -341,7 +379,9 @@ export function makeCouch(opts) {
|
|
|
341
379
|
throw err
|
|
342
380
|
} else if (typeof retry === 'function') {
|
|
343
381
|
const retryState = { since: params.since }
|
|
344
|
-
Object.assign(retryState, await retry(err, retryCount++, retryState, { signal }))
|
|
382
|
+
Object.assign(retryState, await retry(err, retryCount++, retryState, { signal }), () =>
|
|
383
|
+
delay(err, retryCount, { signal }),
|
|
384
|
+
)
|
|
345
385
|
params.since = retryState.since ?? 0
|
|
346
386
|
} else {
|
|
347
387
|
await delay(err, retryCount, { signal })
|