@naturalcycles/datastore-lib 4.14.0 → 4.15.1
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 +3 -3
- package/dist/datastore.model.d.ts +9 -5
- package/dist/datastoreStreamReadable.d.ts +2 -3
- package/dist/datastoreStreamReadable.js +30 -15
- package/package.json +1 -1
- package/src/datastore.db.ts +3 -7
- package/src/datastore.model.ts +11 -5
- package/src/datastoreStreamReadable.ts +30 -14
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,13 +218,14 @@ 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
|
-
.on('error', err => transform.
|
|
228
|
+
.on('error', err => transform.destroy(err))
|
|
229
229
|
.pipe(transform);
|
|
230
230
|
});
|
|
231
231
|
return 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,12 +86,12 @@ 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
|
-
|
|
92
|
-
this.
|
|
93
|
+
this.logger.error('error in runNextQuery', err);
|
|
94
|
+
this.destroy(err);
|
|
93
95
|
});
|
|
94
96
|
}
|
|
95
97
|
async runNextQuery() {
|
|
@@ -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`);
|
|
@@ -160,6 +162,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
160
162
|
return await q.run(this.dsOpt);
|
|
161
163
|
}, {
|
|
162
164
|
name: `DatastoreStreamReadable.query(${table})`,
|
|
165
|
+
predicate: err => RETRY_ON.some(s => err?.message?.toLowerCase()?.includes(s)),
|
|
163
166
|
maxAttempts: 5,
|
|
164
167
|
delay: 5000,
|
|
165
168
|
delayMultiplier: 2,
|
|
@@ -168,13 +171,25 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
168
171
|
});
|
|
169
172
|
}
|
|
170
173
|
catch (err) {
|
|
171
|
-
|
|
174
|
+
logger.error(`DatastoreStreamReadable error!\n`, {
|
|
172
175
|
table,
|
|
173
176
|
rowsRetrieved: this.rowsRetrieved,
|
|
174
177
|
}, err);
|
|
175
|
-
this.emit('error', err);
|
|
176
178
|
clearInterval(this.maxWaitInterval);
|
|
179
|
+
this.destroy(err);
|
|
177
180
|
return;
|
|
178
181
|
}
|
|
179
182
|
}
|
|
180
183
|
}
|
|
184
|
+
// Examples of errors:
|
|
185
|
+
// UNKNOWN: Stream removed
|
|
186
|
+
const RETRY_ON = [
|
|
187
|
+
'GOAWAY',
|
|
188
|
+
'UNAVAILABLE',
|
|
189
|
+
'UNKNOWN',
|
|
190
|
+
'DEADLINE_EXCEEDED',
|
|
191
|
+
'ABORTED',
|
|
192
|
+
'much contention',
|
|
193
|
+
'try again',
|
|
194
|
+
'timeout',
|
|
195
|
+
].map(s => s.toLowerCase());
|
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,19 +343,16 @@ 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
|
-
.on('error', err => transform.
|
|
355
|
+
.on('error', err => transform.destroy(err))
|
|
360
356
|
.pipe(transform)
|
|
361
357
|
})
|
|
362
358
|
|
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,13 +119,13 @@ 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
|
-
|
|
126
|
-
this.
|
|
127
|
+
this.logger.error('error in runNextQuery', err)
|
|
128
|
+
this.destroy(err)
|
|
127
129
|
})
|
|
128
130
|
}
|
|
129
131
|
|
|
@@ -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
|
|
@@ -215,6 +217,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
215
217
|
},
|
|
216
218
|
{
|
|
217
219
|
name: `DatastoreStreamReadable.query(${table})`,
|
|
220
|
+
predicate: err => RETRY_ON.some(s => err?.message?.toLowerCase()?.includes(s)),
|
|
218
221
|
maxAttempts: 5,
|
|
219
222
|
delay: 5000,
|
|
220
223
|
delayMultiplier: 2,
|
|
@@ -223,7 +226,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
223
226
|
},
|
|
224
227
|
)
|
|
225
228
|
} catch (err) {
|
|
226
|
-
|
|
229
|
+
logger.error(
|
|
227
230
|
`DatastoreStreamReadable error!\n`,
|
|
228
231
|
{
|
|
229
232
|
table,
|
|
@@ -231,9 +234,22 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
231
234
|
},
|
|
232
235
|
err,
|
|
233
236
|
)
|
|
234
|
-
this.emit('error', err)
|
|
235
237
|
clearInterval(this.maxWaitInterval)
|
|
238
|
+
this.destroy(err as Error)
|
|
236
239
|
return
|
|
237
240
|
}
|
|
238
241
|
}
|
|
239
242
|
}
|
|
243
|
+
|
|
244
|
+
// Examples of errors:
|
|
245
|
+
// UNKNOWN: Stream removed
|
|
246
|
+
const RETRY_ON = [
|
|
247
|
+
'GOAWAY',
|
|
248
|
+
'UNAVAILABLE',
|
|
249
|
+
'UNKNOWN',
|
|
250
|
+
'DEADLINE_EXCEEDED',
|
|
251
|
+
'ABORTED',
|
|
252
|
+
'much contention',
|
|
253
|
+
'try again',
|
|
254
|
+
'timeout',
|
|
255
|
+
].map(s => s.toLowerCase())
|