@naturalcycles/datastore-lib 4.14.0 → 4.15.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/datastore.db.js +2 -2
- package/dist/datastore.model.d.ts +9 -5
- package/dist/datastoreStreamReadable.d.ts +2 -3
- package/dist/datastoreStreamReadable.js +15 -13
- package/package.json +1 -1
- package/src/datastore.db.ts +2 -6
- package/src/datastore.model.ts +11 -5
- package/src/datastoreStreamReadable.ts +14 -12
package/dist/datastore.db.js
CHANGED
|
@@ -4,7 +4,6 @@ import { _round } from '@naturalcycles/js-lib';
|
|
|
4
4
|
import { _chunk } from '@naturalcycles/js-lib/array/array.util.js';
|
|
5
5
|
import { _assert } from '@naturalcycles/js-lib/error/assert.js';
|
|
6
6
|
import { _errorDataAppend, TimeoutError } from '@naturalcycles/js-lib/error/error.util.js';
|
|
7
|
-
import { commonLoggerMinLevel } from '@naturalcycles/js-lib/log';
|
|
8
7
|
import { _omit } from '@naturalcycles/js-lib/object/object.util.js';
|
|
9
8
|
import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
|
|
10
9
|
import { pRetry, pRetryFn } from '@naturalcycles/js-lib/promise/pRetry.js';
|
|
@@ -219,11 +218,12 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
219
218
|
void this.ds().then(async (ds) => {
|
|
220
219
|
const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table), await this.getPropertyFilter());
|
|
221
220
|
const opt = {
|
|
221
|
+
logger: this.cfg.logger,
|
|
222
222
|
...this.cfg.streamOptions,
|
|
223
223
|
..._opt,
|
|
224
224
|
};
|
|
225
225
|
(opt.experimentalCursorStream
|
|
226
|
-
? new DatastoreStreamReadable(q, opt
|
|
226
|
+
? new DatastoreStreamReadable(q, opt)
|
|
227
227
|
: ds.runQueryStream(q, this.getRunQueryOptions(opt)))
|
|
228
228
|
.on('error', err => transform.emit('error', err))
|
|
229
229
|
.pipe(transform);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DatastoreOptions, Key } from '@google-cloud/datastore';
|
|
2
2
|
import type { CommonDBOptions, CommonDBReadOptions, CommonDBSaveOptions } from '@naturalcycles/db-lib';
|
|
3
|
-
import type { CommonLogger } from '@naturalcycles/js-lib/log';
|
|
3
|
+
import type { CommonLogger, CommonLogLevel } from '@naturalcycles/js-lib/log';
|
|
4
4
|
import type { NumberOfSeconds, ObjectWithId, PositiveInteger } from '@naturalcycles/js-lib/types';
|
|
5
5
|
export interface DatastorePayload<T = any> {
|
|
6
6
|
key: Key;
|
|
@@ -30,6 +30,10 @@ export interface DatastoreDBCfg extends DatastoreOptions {
|
|
|
30
30
|
* Default to `console`
|
|
31
31
|
*/
|
|
32
32
|
logger?: CommonLogger;
|
|
33
|
+
/**
|
|
34
|
+
* Defaults to `log`.
|
|
35
|
+
*/
|
|
36
|
+
logLevel?: CommonLogLevel;
|
|
33
37
|
/**
|
|
34
38
|
* Experimental option, currently only applies to `getByIds`.
|
|
35
39
|
* Applies pTimeout to Datastore operation, re-creates Datastore on any error.
|
|
@@ -70,12 +74,12 @@ export interface DatastoreDBStreamOptions extends DatastoreDBReadOptions {
|
|
|
70
74
|
* between the queries.
|
|
71
75
|
*/
|
|
72
76
|
highWaterMark?: PositiveInteger;
|
|
77
|
+
logger?: CommonLogger;
|
|
73
78
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* @default false
|
|
79
|
+
* Defaults to `log`.
|
|
80
|
+
* Set to `debug` to allow for extra debugging, e.g in experimentalCursorStream.
|
|
77
81
|
*/
|
|
78
|
-
|
|
82
|
+
logLevel?: CommonLogLevel;
|
|
79
83
|
/**
|
|
80
84
|
* Default is undefined.
|
|
81
85
|
* If set - sets a "safety timer", which will force call _read after the specified number of seconds.
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
2
|
import type { Query } from '@google-cloud/datastore';
|
|
3
|
-
import type { CommonLogger } from '@naturalcycles/js-lib/log';
|
|
4
3
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream';
|
|
5
4
|
import type { DatastoreDBStreamOptions } from './datastore.model.js';
|
|
6
5
|
export declare class DatastoreStreamReadable<T = any> extends Readable implements ReadableTyped<T> {
|
|
7
6
|
private q;
|
|
8
|
-
private logger;
|
|
9
7
|
private readonly table;
|
|
10
8
|
private readonly originalLimit;
|
|
11
9
|
private rowsRetrieved;
|
|
@@ -26,8 +24,9 @@ export declare class DatastoreStreamReadable<T = any> extends Readable implement
|
|
|
26
24
|
private lastReadTimestamp;
|
|
27
25
|
private readonly maxWaitInterval;
|
|
28
26
|
private readonly opt;
|
|
27
|
+
private readonly logger;
|
|
29
28
|
private readonly dsOpt;
|
|
30
|
-
constructor(q: Query, opt: DatastoreDBStreamOptions
|
|
29
|
+
constructor(q: Query, opt: DatastoreDBStreamOptions);
|
|
31
30
|
_read(): void;
|
|
32
31
|
private runNextQuery;
|
|
33
32
|
private runQuery;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
2
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
|
|
3
3
|
import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js';
|
|
4
|
+
import { createCommonLoggerAtLevel } from '@naturalcycles/js-lib/log';
|
|
4
5
|
import { pRetry } from '@naturalcycles/js-lib/promise/pRetry.js';
|
|
5
6
|
export class DatastoreStreamReadable extends Readable {
|
|
6
7
|
q;
|
|
7
|
-
logger;
|
|
8
8
|
table;
|
|
9
9
|
originalLimit;
|
|
10
10
|
rowsRetrieved = 0;
|
|
@@ -25,15 +25,15 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
25
25
|
lastReadTimestamp = 0;
|
|
26
26
|
maxWaitInterval;
|
|
27
27
|
opt;
|
|
28
|
+
logger;
|
|
28
29
|
dsOpt;
|
|
29
|
-
constructor(q, opt
|
|
30
|
+
constructor(q, opt) {
|
|
30
31
|
// 1_000 was optimal in benchmarks
|
|
31
32
|
const { batchSize = 1000 } = opt;
|
|
32
33
|
const { highWaterMark = batchSize * 3 } = opt;
|
|
33
34
|
// Defaulting highWaterMark to 3x batchSize
|
|
34
35
|
super({ objectMode: true, highWaterMark });
|
|
35
36
|
this.q = q;
|
|
36
|
-
this.logger = logger;
|
|
37
37
|
this.opt = {
|
|
38
38
|
...opt,
|
|
39
39
|
batchSize,
|
|
@@ -44,24 +44,26 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
44
44
|
// Datastore expects UnixTimestamp in milliseconds
|
|
45
45
|
this.dsOpt.readTime = opt.readAt * 1000;
|
|
46
46
|
}
|
|
47
|
+
const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel);
|
|
48
|
+
this.logger = logger;
|
|
47
49
|
this.originalLimit = q.limitVal;
|
|
48
50
|
this.table = q.kinds[0];
|
|
49
|
-
logger.
|
|
51
|
+
logger.log(`!! using experimentalCursorStream`, {
|
|
50
52
|
table: this.table,
|
|
51
53
|
batchSize,
|
|
52
54
|
highWaterMark,
|
|
53
55
|
});
|
|
54
56
|
const { maxWait } = this.opt;
|
|
55
57
|
if (maxWait) {
|
|
56
|
-
logger.
|
|
58
|
+
logger.log(`!! ${this.table} maxWait ${maxWait}`);
|
|
57
59
|
this.maxWaitInterval = setInterval(() => {
|
|
58
60
|
const millisSinceLastRead = Date.now() - this.lastReadTimestamp;
|
|
59
61
|
if (millisSinceLastRead < maxWait * 1000) {
|
|
60
|
-
logger.
|
|
62
|
+
logger.log(`!! ${this.table} millisSinceLastRead(${millisSinceLastRead}) < maxWait*1000`);
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
const { queryIsRunning, rowsRetrieved } = this;
|
|
64
|
-
logger.
|
|
66
|
+
logger.log(`maxWait of ${maxWait} seconds reached, force-triggering _read`, {
|
|
65
67
|
running: queryIsRunning,
|
|
66
68
|
rowsRetrieved,
|
|
67
69
|
});
|
|
@@ -72,7 +74,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
_read() {
|
|
75
|
-
this.lastReadTimestamp =
|
|
77
|
+
this.lastReadTimestamp = localTime.nowUnixMillis();
|
|
76
78
|
// console.log(`_read called ${++this.count}, wasRunning: ${this.running}`) // debugging
|
|
77
79
|
this.countReads++;
|
|
78
80
|
if (this.done) {
|
|
@@ -84,11 +86,11 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
84
86
|
this.paused = false;
|
|
85
87
|
}
|
|
86
88
|
if (this.queryIsRunning) {
|
|
87
|
-
this.logger.
|
|
89
|
+
this.logger.debug(`_read #${this.countReads}, queryIsRunning: true, doing nothing`);
|
|
88
90
|
return;
|
|
89
91
|
}
|
|
90
92
|
void this.runNextQuery().catch(err => {
|
|
91
|
-
|
|
93
|
+
this.logger.error('error in runNextQuery', err);
|
|
92
94
|
this.emit('error', err);
|
|
93
95
|
});
|
|
94
96
|
}
|
|
@@ -139,13 +141,13 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
139
141
|
}
|
|
140
142
|
if (shouldContinue) {
|
|
141
143
|
// Keep the stream flowing
|
|
142
|
-
logger.
|
|
144
|
+
logger.debug(`${table} continuing the stream`);
|
|
143
145
|
void this.runNextQuery();
|
|
144
146
|
}
|
|
145
147
|
else {
|
|
146
148
|
// Not starting the next query
|
|
147
149
|
if (this.paused) {
|
|
148
|
-
logger.
|
|
150
|
+
logger.debug(`${table} stream is already paused`);
|
|
149
151
|
}
|
|
150
152
|
else {
|
|
151
153
|
logger.log(`${table} pausing the stream`);
|
|
@@ -168,7 +170,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
168
170
|
});
|
|
169
171
|
}
|
|
170
172
|
catch (err) {
|
|
171
|
-
|
|
173
|
+
logger.error(`DatastoreStreamReadable error!\n`, {
|
|
172
174
|
table,
|
|
173
175
|
rowsRetrieved: this.rowsRetrieved,
|
|
174
176
|
}, err);
|
package/package.json
CHANGED
package/src/datastore.db.ts
CHANGED
|
@@ -29,7 +29,6 @@ import type {
|
|
|
29
29
|
JsonSchemaString,
|
|
30
30
|
} from '@naturalcycles/js-lib/json-schema'
|
|
31
31
|
import type { CommonLogger } from '@naturalcycles/js-lib/log'
|
|
32
|
-
import { commonLoggerMinLevel } from '@naturalcycles/js-lib/log'
|
|
33
32
|
import { _omit } from '@naturalcycles/js-lib/object/object.util.js'
|
|
34
33
|
import type { PRetryOptions } from '@naturalcycles/js-lib/promise'
|
|
35
34
|
import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
|
|
@@ -344,16 +343,13 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
344
343
|
)
|
|
345
344
|
|
|
346
345
|
const opt = {
|
|
346
|
+
logger: this.cfg.logger,
|
|
347
347
|
...this.cfg.streamOptions,
|
|
348
348
|
..._opt,
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
;(opt.experimentalCursorStream
|
|
352
|
-
? new DatastoreStreamReadable<ROW>(
|
|
353
|
-
q,
|
|
354
|
-
opt,
|
|
355
|
-
commonLoggerMinLevel(this.cfg.logger, opt.debug ? 'log' : 'warn'),
|
|
356
|
-
)
|
|
352
|
+
? new DatastoreStreamReadable<ROW>(q, opt)
|
|
357
353
|
: (ds.runQueryStream(q, this.getRunQueryOptions(opt)) as ReadableTyped<ROW>)
|
|
358
354
|
)
|
|
359
355
|
.on('error', err => transform.emit('error', err))
|
package/src/datastore.model.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
CommonDBReadOptions,
|
|
5
5
|
CommonDBSaveOptions,
|
|
6
6
|
} from '@naturalcycles/db-lib'
|
|
7
|
-
import type { CommonLogger } from '@naturalcycles/js-lib/log'
|
|
7
|
+
import type { CommonLogger, CommonLogLevel } from '@naturalcycles/js-lib/log'
|
|
8
8
|
import type { NumberOfSeconds, ObjectWithId, PositiveInteger } from '@naturalcycles/js-lib/types'
|
|
9
9
|
|
|
10
10
|
export interface DatastorePayload<T = any> {
|
|
@@ -41,6 +41,11 @@ export interface DatastoreDBCfg extends DatastoreOptions {
|
|
|
41
41
|
*/
|
|
42
42
|
logger?: CommonLogger
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Defaults to `log`.
|
|
46
|
+
*/
|
|
47
|
+
logLevel?: CommonLogLevel
|
|
48
|
+
|
|
44
49
|
/**
|
|
45
50
|
* Experimental option, currently only applies to `getByIds`.
|
|
46
51
|
* Applies pTimeout to Datastore operation, re-creates Datastore on any error.
|
|
@@ -86,12 +91,13 @@ export interface DatastoreDBStreamOptions extends DatastoreDBReadOptions {
|
|
|
86
91
|
*/
|
|
87
92
|
highWaterMark?: PositiveInteger
|
|
88
93
|
|
|
94
|
+
logger?: CommonLogger
|
|
95
|
+
|
|
89
96
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* @default false
|
|
97
|
+
* Defaults to `log`.
|
|
98
|
+
* Set to `debug` to allow for extra debugging, e.g in experimentalCursorStream.
|
|
93
99
|
*/
|
|
94
|
-
|
|
100
|
+
logLevel?: CommonLogLevel
|
|
95
101
|
|
|
96
102
|
/**
|
|
97
103
|
* Default is undefined.
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
} from '@google-cloud/datastore/build/src/query.js'
|
|
8
8
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
|
|
9
9
|
import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js'
|
|
10
|
-
import type
|
|
10
|
+
import { type CommonLogger, createCommonLoggerAtLevel } from '@naturalcycles/js-lib/log'
|
|
11
11
|
import { pRetry } from '@naturalcycles/js-lib/promise/pRetry.js'
|
|
12
12
|
import type { UnixTimestampMillis } from '@naturalcycles/js-lib/types'
|
|
13
13
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
|
|
@@ -35,12 +35,12 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
35
35
|
private readonly maxWaitInterval: NodeJS.Timeout | undefined
|
|
36
36
|
|
|
37
37
|
private readonly opt: DatastoreDBStreamOptions & { batchSize: number; highWaterMark: number }
|
|
38
|
+
private readonly logger: CommonLogger
|
|
38
39
|
private readonly dsOpt: RunQueryOptions
|
|
39
40
|
|
|
40
41
|
constructor(
|
|
41
42
|
private q: Query,
|
|
42
43
|
opt: DatastoreDBStreamOptions,
|
|
43
|
-
private logger: CommonLogger,
|
|
44
44
|
) {
|
|
45
45
|
// 1_000 was optimal in benchmarks
|
|
46
46
|
const { batchSize = 1000 } = opt
|
|
@@ -59,10 +59,12 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
59
59
|
this.dsOpt.readTime = opt.readAt * 1000
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel)
|
|
63
|
+
this.logger = logger
|
|
62
64
|
this.originalLimit = q.limitVal
|
|
63
65
|
this.table = q.kinds[0]!
|
|
64
66
|
|
|
65
|
-
logger.
|
|
67
|
+
logger.log(`!! using experimentalCursorStream`, {
|
|
66
68
|
table: this.table,
|
|
67
69
|
batchSize,
|
|
68
70
|
highWaterMark,
|
|
@@ -70,21 +72,21 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
70
72
|
|
|
71
73
|
const { maxWait } = this.opt
|
|
72
74
|
if (maxWait) {
|
|
73
|
-
logger.
|
|
75
|
+
logger.log(`!! ${this.table} maxWait ${maxWait}`)
|
|
74
76
|
|
|
75
77
|
this.maxWaitInterval = setInterval(
|
|
76
78
|
() => {
|
|
77
79
|
const millisSinceLastRead = Date.now() - this.lastReadTimestamp
|
|
78
80
|
|
|
79
81
|
if (millisSinceLastRead < maxWait * 1000) {
|
|
80
|
-
logger.
|
|
82
|
+
logger.log(
|
|
81
83
|
`!! ${this.table} millisSinceLastRead(${millisSinceLastRead}) < maxWait*1000`,
|
|
82
84
|
)
|
|
83
85
|
return
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
const { queryIsRunning, rowsRetrieved } = this
|
|
87
|
-
logger.
|
|
89
|
+
logger.log(`maxWait of ${maxWait} seconds reached, force-triggering _read`, {
|
|
88
90
|
running: queryIsRunning,
|
|
89
91
|
rowsRetrieved,
|
|
90
92
|
})
|
|
@@ -99,7 +101,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
override _read(): void {
|
|
102
|
-
this.lastReadTimestamp =
|
|
104
|
+
this.lastReadTimestamp = localTime.nowUnixMillis()
|
|
103
105
|
|
|
104
106
|
// console.log(`_read called ${++this.count}, wasRunning: ${this.running}`) // debugging
|
|
105
107
|
this.countReads++
|
|
@@ -117,12 +119,12 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
if (this.queryIsRunning) {
|
|
120
|
-
this.logger.
|
|
122
|
+
this.logger.debug(`_read #${this.countReads}, queryIsRunning: true, doing nothing`)
|
|
121
123
|
return
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
void this.runNextQuery().catch(err => {
|
|
125
|
-
|
|
127
|
+
this.logger.error('error in runNextQuery', err)
|
|
126
128
|
this.emit('error', err)
|
|
127
129
|
})
|
|
128
130
|
}
|
|
@@ -192,12 +194,12 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
192
194
|
|
|
193
195
|
if (shouldContinue) {
|
|
194
196
|
// Keep the stream flowing
|
|
195
|
-
logger.
|
|
197
|
+
logger.debug(`${table} continuing the stream`)
|
|
196
198
|
void this.runNextQuery()
|
|
197
199
|
} else {
|
|
198
200
|
// Not starting the next query
|
|
199
201
|
if (this.paused) {
|
|
200
|
-
logger.
|
|
202
|
+
logger.debug(`${table} stream is already paused`)
|
|
201
203
|
} else {
|
|
202
204
|
logger.log(`${table} pausing the stream`)
|
|
203
205
|
this.paused = true
|
|
@@ -223,7 +225,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
223
225
|
},
|
|
224
226
|
)
|
|
225
227
|
} catch (err) {
|
|
226
|
-
|
|
228
|
+
logger.error(
|
|
227
229
|
`DatastoreStreamReadable error!\n`,
|
|
228
230
|
{
|
|
229
231
|
table,
|