@naturalcycles/datastore-lib 3.24.0 → 3.25.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/dist/DatastoreStreamReadable.d.ts +2 -1
- package/dist/DatastoreStreamReadable.js +48 -31
- package/dist/datastore.db.js +8 -5
- package/dist/datastoreKeyValueDB.js +15 -3
- package/package.json +1 -1
- package/src/DatastoreStreamReadable.ts +67 -40
- package/src/datastore.db.ts +15 -11
- package/src/datastoreKeyValueDB.ts +30 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { Readable } from 'stream';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
3
|
import { Query } from '@google-cloud/datastore';
|
|
4
4
|
import { CommonLogger } from '@naturalcycles/js-lib';
|
|
5
5
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
@@ -14,6 +14,7 @@ export declare class DatastoreStreamReadable<T = any> extends Readable implement
|
|
|
14
14
|
private done;
|
|
15
15
|
private lastQueryDone?;
|
|
16
16
|
private totalWait;
|
|
17
|
+
private table;
|
|
17
18
|
private opt;
|
|
18
19
|
constructor(q: Query, opt: DatastoreDBStreamOptions, logger: CommonLogger);
|
|
19
20
|
private runNextQuery;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DatastoreStreamReadable = void 0;
|
|
4
|
-
const
|
|
4
|
+
const node_stream_1 = require("node:stream");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
class DatastoreStreamReadable extends
|
|
6
|
+
class DatastoreStreamReadable extends node_stream_1.Readable {
|
|
7
7
|
constructor(q, opt, logger) {
|
|
8
8
|
super({ objectMode: true });
|
|
9
9
|
this.q = q;
|
|
@@ -19,7 +19,8 @@ class DatastoreStreamReadable extends stream_1.Readable {
|
|
|
19
19
|
...opt,
|
|
20
20
|
};
|
|
21
21
|
this.originalLimit = q.limitVal;
|
|
22
|
-
|
|
22
|
+
this.table = q.kinds[0];
|
|
23
|
+
logger.log(`!! using experimentalCursorStream !! ${this.table}, batchSize: ${opt.batchSize}`);
|
|
23
24
|
}
|
|
24
25
|
async runNextQuery() {
|
|
25
26
|
if (this.done)
|
|
@@ -39,38 +40,54 @@ class DatastoreStreamReadable extends stream_1.Readable {
|
|
|
39
40
|
if (this.endCursor) {
|
|
40
41
|
q = q.start(this.endCursor);
|
|
41
42
|
}
|
|
43
|
+
let rows = [];
|
|
44
|
+
let info = {};
|
|
42
45
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.push(null);
|
|
55
|
-
this.done = true;
|
|
56
|
-
}
|
|
57
|
-
else if (this.opt.singleBatchBuffer) {
|
|
58
|
-
// here we don't start next query until we're asked (via next _read call)
|
|
59
|
-
// do, let's do nothing
|
|
60
|
-
}
|
|
61
|
-
else if (this.opt.rssLimitMB) {
|
|
62
|
-
const rssMB = Math.round(process.memoryUsage().rss / 1024 / 1024);
|
|
63
|
-
if (rssMB <= this.opt.rssLimitMB) {
|
|
64
|
-
void this.runNextQuery();
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
this.logger.log(`rssLimitMB reached ${rssMB} > ${this.opt.rssLimitMB}, pausing stream`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
46
|
+
await (0, js_lib_1.pRetry)(async () => {
|
|
47
|
+
const res = await q.run();
|
|
48
|
+
rows = res[0];
|
|
49
|
+
info = res[1];
|
|
50
|
+
}, {
|
|
51
|
+
name: `DatastoreStreamReadable.query(${this.table})`,
|
|
52
|
+
maxAttempts: 5,
|
|
53
|
+
delay: 5000,
|
|
54
|
+
delayMultiplier: 2,
|
|
55
|
+
logger: this.logger,
|
|
56
|
+
});
|
|
70
57
|
}
|
|
71
58
|
catch (err) {
|
|
72
|
-
console.error(
|
|
59
|
+
console.error(`DatastoreStreamReadable error!\n`, {
|
|
60
|
+
table: this.table,
|
|
61
|
+
rowsRetrieved: this.rowsRetrieved,
|
|
62
|
+
}, err);
|
|
73
63
|
this.emit('error', err);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.rowsRetrieved += rows.length;
|
|
67
|
+
this.logger.log(`got ${rows.length} rows, ${this.rowsRetrieved} rowsRetrieved, totalWait: ${(0, js_lib_1._ms)(this.totalWait)}`, info.moreResults);
|
|
68
|
+
this.endCursor = info.endCursor;
|
|
69
|
+
this.running = false; // ready to take more _reads
|
|
70
|
+
this.lastQueryDone = Date.now();
|
|
71
|
+
rows.forEach(row => this.push(row));
|
|
72
|
+
if (!info.endCursor ||
|
|
73
|
+
info.moreResults === 'NO_MORE_RESULTS' ||
|
|
74
|
+
(this.originalLimit && this.rowsRetrieved >= this.originalLimit)) {
|
|
75
|
+
this.logger.log(`!!!! DONE! ${this.rowsRetrieved} rowsRetrieved, totalWait: ${(0, js_lib_1._ms)(this.totalWait)}`);
|
|
76
|
+
this.push(null);
|
|
77
|
+
this.done = true;
|
|
78
|
+
}
|
|
79
|
+
else if (this.opt.singleBatchBuffer) {
|
|
80
|
+
// here we don't start next query until we're asked (via next _read call)
|
|
81
|
+
// do, let's do nothing
|
|
82
|
+
}
|
|
83
|
+
else if (this.opt.rssLimitMB) {
|
|
84
|
+
const rssMB = Math.round(process.memoryUsage().rss / 1024 / 1024);
|
|
85
|
+
if (rssMB <= this.opt.rssLimitMB) {
|
|
86
|
+
void this.runNextQuery();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.logger.log(`rssLimitMB reached ${rssMB} > ${this.opt.rssLimitMB}, pausing stream`);
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
}
|
|
76
93
|
_read() {
|
package/dist/datastore.db.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DatastoreDB = void 0;
|
|
4
|
-
const
|
|
4
|
+
const node_stream_1 = require("node:stream");
|
|
5
5
|
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
6
6
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
7
7
|
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
@@ -133,14 +133,17 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
|
|
|
133
133
|
...this.cfg.streamOptions,
|
|
134
134
|
..._opt,
|
|
135
135
|
};
|
|
136
|
-
|
|
136
|
+
const stream = (opt.experimentalCursorStream
|
|
137
137
|
? new DatastoreStreamReadable_1.DatastoreStreamReadable(q, opt, (0, js_lib_1.commonLoggerMinLevel)(this.cfg.logger, opt.debug ? 'log' : 'warn'))
|
|
138
|
-
: this.ds().runQueryStream(q))
|
|
138
|
+
: this.ds().runQueryStream(q))
|
|
139
|
+
.on('error', err => stream.emit('error', err))
|
|
140
|
+
.pipe(new node_stream_1.Transform({
|
|
139
141
|
objectMode: true,
|
|
140
142
|
transform: (chunk, _enc, cb) => {
|
|
141
143
|
cb(null, this.mapId(chunk));
|
|
142
144
|
},
|
|
143
145
|
}));
|
|
146
|
+
return stream;
|
|
144
147
|
}
|
|
145
148
|
streamQuery(dbQuery, opt) {
|
|
146
149
|
const q = (0, query_util_1.dbQueryToDatastoreQuery)(dbQuery, this.ds().createQuery(dbQuery.table));
|
|
@@ -199,10 +202,10 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
|
|
|
199
202
|
const ops = (0, db_lib_1.mergeDBOperations)(_tx.ops);
|
|
200
203
|
for await (const op of ops) {
|
|
201
204
|
if (op.type === 'saveBatch') {
|
|
202
|
-
await this.saveBatch(op.table, op.rows, { ...opt, tx });
|
|
205
|
+
await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt, tx });
|
|
203
206
|
}
|
|
204
207
|
else if (op.type === 'deleteByIds') {
|
|
205
|
-
await this.deleteByIds(op.table, op.ids, { ...opt, tx });
|
|
208
|
+
await this.deleteByIds(op.table, op.ids, { ...op.opt, ...opt, tx });
|
|
206
209
|
}
|
|
207
210
|
else {
|
|
208
211
|
throw new Error(`DBOperation not supported: ${op.type}`);
|
|
@@ -30,22 +30,34 @@ class DatastoreKeyValueDB {
|
|
|
30
30
|
const q = db_lib_1.DBQuery.create(table)
|
|
31
31
|
.select(['id'])
|
|
32
32
|
.limit(limit || 0);
|
|
33
|
-
|
|
33
|
+
const stream = this.db
|
|
34
|
+
.streamQuery(q)
|
|
35
|
+
.on('error', err => stream.emit('error', err))
|
|
36
|
+
.pipe((0, nodejs_lib_1.transformMapSimple)(objectWithId => objectWithId.id, {
|
|
34
37
|
errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
35
38
|
}));
|
|
39
|
+
return stream;
|
|
36
40
|
}
|
|
37
41
|
streamValues(table, limit) {
|
|
38
42
|
// `select v` doesn't work for some reason
|
|
39
43
|
const q = db_lib_1.DBQuery.create(table).limit(limit || 0);
|
|
40
|
-
|
|
44
|
+
const stream = this.db
|
|
45
|
+
.streamQuery(q)
|
|
46
|
+
.on('error', err => stream.emit('error', err))
|
|
47
|
+
.pipe((0, nodejs_lib_1.transformMapSimple)(obj => obj.v, {
|
|
41
48
|
errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
42
49
|
}));
|
|
50
|
+
return stream;
|
|
43
51
|
}
|
|
44
52
|
streamEntries(table, limit) {
|
|
45
53
|
const q = db_lib_1.DBQuery.create(table).limit(limit || 0);
|
|
46
|
-
|
|
54
|
+
const stream = this.db
|
|
55
|
+
.streamQuery(q)
|
|
56
|
+
.on('error', err => stream.emit('error', err))
|
|
57
|
+
.pipe((0, nodejs_lib_1.transformMapSimple)(obj => [obj.id, obj.v], {
|
|
47
58
|
errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
48
59
|
}));
|
|
60
|
+
return stream;
|
|
49
61
|
}
|
|
50
62
|
async count(_table) {
|
|
51
63
|
this.db.cfg.logger.warn(`DatastoreKeyValueDB.count is not supported`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Readable } from 'stream'
|
|
1
|
+
import { Readable } from 'node:stream'
|
|
2
|
+
import type { RunQueryInfo } from '@google-cloud/datastore/build/src/query'
|
|
2
3
|
import { Query } from '@google-cloud/datastore'
|
|
3
|
-
import { _ms, CommonLogger } from '@naturalcycles/js-lib'
|
|
4
|
+
import { _ms, CommonLogger, pRetry } from '@naturalcycles/js-lib'
|
|
4
5
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
5
6
|
import type { DatastoreDBStreamOptions } from './datastore.model'
|
|
6
7
|
|
|
@@ -12,6 +13,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
12
13
|
private done = false
|
|
13
14
|
private lastQueryDone?: number
|
|
14
15
|
private totalWait = 0
|
|
16
|
+
private table: string
|
|
15
17
|
|
|
16
18
|
private opt: DatastoreDBStreamOptions & { batchSize: number }
|
|
17
19
|
|
|
@@ -25,8 +27,9 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
this.originalLimit = q.limitVal
|
|
30
|
+
this.table = q.kinds[0]!
|
|
28
31
|
|
|
29
|
-
logger.log(`!! using experimentalCursorStream !! batchSize: ${opt.batchSize}`)
|
|
32
|
+
logger.log(`!! using experimentalCursorStream !! ${this.table}, batchSize: ${opt.batchSize}`)
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
private async runNextQuery(): Promise<void> {
|
|
@@ -52,48 +55,72 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
52
55
|
q = q.start(this.endCursor)
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
let rows: T[] = []
|
|
59
|
+
let info: RunQueryInfo = {}
|
|
60
|
+
|
|
55
61
|
try {
|
|
56
|
-
|
|
62
|
+
await pRetry(
|
|
63
|
+
async () => {
|
|
64
|
+
const res = await q.run()
|
|
65
|
+
rows = res[0]
|
|
66
|
+
info = res[1]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: `DatastoreStreamReadable.query(${this.table})`,
|
|
70
|
+
maxAttempts: 5,
|
|
71
|
+
delay: 5000,
|
|
72
|
+
delayMultiplier: 2,
|
|
73
|
+
logger: this.logger,
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.error(
|
|
78
|
+
`DatastoreStreamReadable error!\n`,
|
|
79
|
+
{
|
|
80
|
+
table: this.table,
|
|
81
|
+
rowsRetrieved: this.rowsRetrieved,
|
|
82
|
+
},
|
|
83
|
+
err,
|
|
84
|
+
)
|
|
85
|
+
this.emit('error', err)
|
|
86
|
+
return
|
|
87
|
+
}
|
|
57
88
|
|
|
58
|
-
|
|
89
|
+
this.rowsRetrieved += rows.length
|
|
90
|
+
this.logger.log(
|
|
91
|
+
`got ${rows.length} rows, ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(
|
|
92
|
+
this.totalWait,
|
|
93
|
+
)}`,
|
|
94
|
+
info.moreResults,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
this.endCursor = info.endCursor
|
|
98
|
+
this.running = false // ready to take more _reads
|
|
99
|
+
this.lastQueryDone = Date.now()
|
|
100
|
+
|
|
101
|
+
rows.forEach(row => this.push(row))
|
|
102
|
+
|
|
103
|
+
if (
|
|
104
|
+
!info.endCursor ||
|
|
105
|
+
info.moreResults === 'NO_MORE_RESULTS' ||
|
|
106
|
+
(this.originalLimit && this.rowsRetrieved >= this.originalLimit)
|
|
107
|
+
) {
|
|
59
108
|
this.logger.log(
|
|
60
|
-
|
|
61
|
-
this.totalWait,
|
|
62
|
-
)}`,
|
|
63
|
-
info.moreResults,
|
|
109
|
+
`!!!! DONE! ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(this.totalWait)}`,
|
|
64
110
|
)
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.logger.log(
|
|
78
|
-
`!!!! DONE! ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(this.totalWait)}`,
|
|
79
|
-
)
|
|
80
|
-
this.push(null)
|
|
81
|
-
this.done = true
|
|
82
|
-
} else if (this.opt.singleBatchBuffer) {
|
|
83
|
-
// here we don't start next query until we're asked (via next _read call)
|
|
84
|
-
// do, let's do nothing
|
|
85
|
-
} else if (this.opt.rssLimitMB) {
|
|
86
|
-
const rssMB = Math.round(process.memoryUsage().rss / 1024 / 1024)
|
|
87
|
-
|
|
88
|
-
if (rssMB <= this.opt.rssLimitMB) {
|
|
89
|
-
void this.runNextQuery()
|
|
90
|
-
} else {
|
|
91
|
-
this.logger.log(`rssLimitMB reached ${rssMB} > ${this.opt.rssLimitMB}, pausing stream`)
|
|
92
|
-
}
|
|
111
|
+
this.push(null)
|
|
112
|
+
this.done = true
|
|
113
|
+
} else if (this.opt.singleBatchBuffer) {
|
|
114
|
+
// here we don't start next query until we're asked (via next _read call)
|
|
115
|
+
// do, let's do nothing
|
|
116
|
+
} else if (this.opt.rssLimitMB) {
|
|
117
|
+
const rssMB = Math.round(process.memoryUsage().rss / 1024 / 1024)
|
|
118
|
+
|
|
119
|
+
if (rssMB <= this.opt.rssLimitMB) {
|
|
120
|
+
void this.runNextQuery()
|
|
121
|
+
} else {
|
|
122
|
+
this.logger.log(`rssLimitMB reached ${rssMB} > ${this.opt.rssLimitMB}, pausing stream`)
|
|
93
123
|
}
|
|
94
|
-
} catch (err) {
|
|
95
|
-
console.error('DatastoreStreamReadable error!\n', err)
|
|
96
|
-
this.emit('error', err)
|
|
97
124
|
}
|
|
98
125
|
}
|
|
99
126
|
|
package/src/datastore.db.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transform } from 'stream'
|
|
1
|
+
import { Transform } from 'node:stream'
|
|
2
2
|
import type { Datastore, Key, Query } from '@google-cloud/datastore'
|
|
3
3
|
import {
|
|
4
4
|
BaseCommonDB,
|
|
@@ -216,7 +216,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
216
216
|
..._opt,
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
const stream: ReadableTyped<ROW> = (
|
|
220
220
|
opt.experimentalCursorStream
|
|
221
221
|
? new DatastoreStreamReadable(
|
|
222
222
|
q,
|
|
@@ -224,14 +224,18 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
224
224
|
commonLoggerMinLevel(this.cfg.logger, opt.debug ? 'log' : 'warn'),
|
|
225
225
|
)
|
|
226
226
|
: this.ds().runQueryStream(q)
|
|
227
|
-
).pipe(
|
|
228
|
-
new Transform({
|
|
229
|
-
objectMode: true,
|
|
230
|
-
transform: (chunk, _enc, cb) => {
|
|
231
|
-
cb(null, this.mapId(chunk))
|
|
232
|
-
},
|
|
233
|
-
}),
|
|
234
227
|
)
|
|
228
|
+
.on('error', err => stream.emit('error', err))
|
|
229
|
+
.pipe(
|
|
230
|
+
new Transform({
|
|
231
|
+
objectMode: true,
|
|
232
|
+
transform: (chunk, _enc, cb) => {
|
|
233
|
+
cb(null, this.mapId(chunk))
|
|
234
|
+
},
|
|
235
|
+
}),
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
return stream
|
|
235
239
|
}
|
|
236
240
|
|
|
237
241
|
override streamQuery<ROW extends ObjectWithId>(
|
|
@@ -327,9 +331,9 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
327
331
|
|
|
328
332
|
for await (const op of ops) {
|
|
329
333
|
if (op.type === 'saveBatch') {
|
|
330
|
-
await this.saveBatch(op.table, op.rows, { ...opt, tx })
|
|
334
|
+
await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt, tx })
|
|
331
335
|
} else if (op.type === 'deleteByIds') {
|
|
332
|
-
await this.deleteByIds(op.table, op.ids, { ...opt, tx })
|
|
336
|
+
await this.deleteByIds(op.table, op.ids, { ...op.opt, ...opt, tx })
|
|
333
337
|
} else {
|
|
334
338
|
throw new Error(`DBOperation not supported: ${(op as any).type}`)
|
|
335
339
|
}
|
|
@@ -49,32 +49,47 @@ export class DatastoreKeyValueDB implements CommonKeyValueDB {
|
|
|
49
49
|
.select(['id'])
|
|
50
50
|
.limit(limit || 0)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
const stream: ReadableTyped<string> = this.db
|
|
53
|
+
.streamQuery<KVObject>(q)
|
|
54
|
+
.on('error', err => stream.emit('error', err))
|
|
55
|
+
.pipe(
|
|
56
|
+
transformMapSimple<ObjectWithId<string>, string>(objectWithId => objectWithId.id, {
|
|
57
|
+
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
58
|
+
}),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return stream
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
streamValues(table: string, limit?: number): ReadableTyped<Buffer> {
|
|
60
65
|
// `select v` doesn't work for some reason
|
|
61
66
|
const q = DBQuery.create(table).limit(limit || 0)
|
|
62
67
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
const stream: ReadableTyped<string> = this.db
|
|
69
|
+
.streamQuery<KVObject>(q)
|
|
70
|
+
.on('error', err => stream.emit('error', err))
|
|
71
|
+
.pipe(
|
|
72
|
+
transformMapSimple<{ v: Buffer }, Buffer>(obj => obj.v, {
|
|
73
|
+
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return stream
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple> {
|
|
71
81
|
const q = DBQuery.create(table).limit(limit || 0)
|
|
72
82
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
const stream: ReadableTyped<string> = this.db
|
|
84
|
+
.streamQuery<KVObject>(q)
|
|
85
|
+
.on('error', err => stream.emit('error', err))
|
|
86
|
+
.pipe(
|
|
87
|
+
transformMapSimple<KVObject, KeyValueDBTuple>(obj => [obj.id, obj.v], {
|
|
88
|
+
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
89
|
+
}),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
return stream
|
|
78
93
|
}
|
|
79
94
|
|
|
80
95
|
async count(_table: string): Promise<number> {
|