@nxtedition/lib 17.2.22 → 18.0.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/app.js +5 -1
- package/couch.js +60 -103
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -473,7 +473,11 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
473
473
|
? rxjs.timer(0, 10e3).pipe(
|
|
474
474
|
rx.exhaustMap(async () => {
|
|
475
475
|
try {
|
|
476
|
-
|
|
476
|
+
try {
|
|
477
|
+
await couch.up()
|
|
478
|
+
} catch {
|
|
479
|
+
await couch.info()
|
|
480
|
+
}
|
|
477
481
|
return [
|
|
478
482
|
{
|
|
479
483
|
id: 'app:couch',
|
package/couch.js
CHANGED
|
@@ -5,6 +5,7 @@ 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'
|
|
8
9
|
|
|
9
10
|
// https://github.com/fastify/fastify/blob/main/lib/reqIdGenFactory.js
|
|
10
11
|
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
@@ -225,16 +226,21 @@ export function makeCouch(opts) {
|
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
|
|
228
|
-
async function*
|
|
229
|
+
async function* parse(live) {
|
|
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
|
+
|
|
229
242
|
const req = {
|
|
230
|
-
path:
|
|
231
|
-
dbPathname +
|
|
232
|
-
'/_changes' +
|
|
233
|
-
`?${new URLSearchParams({
|
|
234
|
-
...params,
|
|
235
|
-
...options.query,
|
|
236
|
-
feed: 'continuous',
|
|
237
|
-
})}`,
|
|
243
|
+
path: `${dbPathname}/_changes?${new URLSearchParams(params2)}`,
|
|
238
244
|
idempotent: false,
|
|
239
245
|
blocking: true,
|
|
240
246
|
method,
|
|
@@ -250,34 +256,63 @@ export function makeCouch(opts) {
|
|
|
250
256
|
bodyTimeout: 2 * (params.heartbeat || 60e3),
|
|
251
257
|
}
|
|
252
258
|
|
|
259
|
+
const HEAD = '{"results":['
|
|
260
|
+
const TAIL = '],'
|
|
261
|
+
|
|
253
262
|
try {
|
|
254
263
|
const res = await client.request(req)
|
|
255
264
|
|
|
256
265
|
retryCount = 0
|
|
257
266
|
|
|
258
267
|
let str = ''
|
|
268
|
+
let state = 0
|
|
259
269
|
for await (const chunk of res.body) {
|
|
260
270
|
const lines = (str + chunk).split('\n')
|
|
261
271
|
str = lines.pop() ?? ''
|
|
262
272
|
|
|
263
|
-
const
|
|
273
|
+
const changes = []
|
|
264
274
|
for (const line of lines) {
|
|
265
|
-
if (
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
params.since =
|
|
275
|
+
if (live) {
|
|
276
|
+
const data = JSON.parse(line)
|
|
277
|
+
if (data.last_seq) {
|
|
278
|
+
params.since = data.last_seq
|
|
279
|
+
assert(params.since, 'invalid last_seq: ' + params.since)
|
|
280
|
+
} else {
|
|
281
|
+
params.since = data.seq || params.since
|
|
282
|
+
changes.push(data)
|
|
269
283
|
}
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
} else {
|
|
285
|
+
// NOTE: This makes some assumptions about the format of the JSON.
|
|
286
|
+
if (state === 0) {
|
|
287
|
+
if (line === HEAD) {
|
|
288
|
+
state = 1
|
|
289
|
+
} else {
|
|
290
|
+
assert(line.length < HEAD.length, 'invalid line: ' + line)
|
|
291
|
+
}
|
|
292
|
+
} else if (state === 1) {
|
|
293
|
+
if (line === TAIL) {
|
|
294
|
+
state = 2
|
|
295
|
+
} else {
|
|
296
|
+
const idx = line.lastIndexOf('}') + 1
|
|
297
|
+
assert(idx > 0, 'invalid line; ' + line)
|
|
298
|
+
const data = JSON.parse(line.slice(0, idx))
|
|
299
|
+
params.since = data.seq || params.since
|
|
300
|
+
changes.push(data)
|
|
301
|
+
}
|
|
302
|
+
} else if (state === 2) {
|
|
303
|
+
state = 3
|
|
304
|
+
params.since = JSON.parse('{' + line).last_seq
|
|
305
|
+
assert(params.since, 'invalid last_seq: ' + params.since)
|
|
272
306
|
} else {
|
|
273
|
-
|
|
307
|
+
assert(false, 'invalid state: ' + state)
|
|
274
308
|
}
|
|
275
309
|
}
|
|
276
310
|
}
|
|
277
311
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
312
|
+
yield changes
|
|
313
|
+
|
|
314
|
+
remaining -= changes.length
|
|
315
|
+
assert(remaining >= 0, 'invalid remaining: ' + remaining)
|
|
281
316
|
}
|
|
282
317
|
} catch (err) {
|
|
283
318
|
Object.assign(err, { data: req })
|
|
@@ -285,93 +320,15 @@ export function makeCouch(opts) {
|
|
|
285
320
|
}
|
|
286
321
|
}
|
|
287
322
|
|
|
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
|
-
|
|
368
323
|
try {
|
|
369
324
|
while (true) {
|
|
370
325
|
try {
|
|
371
|
-
if (
|
|
372
|
-
yield*
|
|
326
|
+
if (batched) {
|
|
327
|
+
yield* parse(live)
|
|
373
328
|
} else {
|
|
374
|
-
|
|
329
|
+
for await (const changes of parse(live)) {
|
|
330
|
+
yield* changes
|
|
331
|
+
}
|
|
375
332
|
}
|
|
376
333
|
return
|
|
377
334
|
} catch (err) {
|