@naturalcycles/datastore-lib 4.18.3 → 4.18.5
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.d.ts +0 -1
- package/dist/datastore.db.js +7 -20
- package/dist/datastoreStreamReadable.js +5 -8
- package/dist/query.util.d.ts +3 -0
- package/dist/query.util.js +13 -0
- package/package.json +1 -1
- package/src/datastore.db.ts +7 -22
- package/src/datastoreStreamReadable.ts +5 -9
- package/src/query.util.ts +17 -0
package/dist/datastore.db.d.ts
CHANGED
|
@@ -66,7 +66,6 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
66
66
|
* It may happen that transaction is already committed/rolled back, so we don't want to throw an error here.
|
|
67
67
|
*/
|
|
68
68
|
private rollback;
|
|
69
|
-
private getRunQueryOptions;
|
|
70
69
|
}
|
|
71
70
|
/**
|
|
72
71
|
* https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
|
package/dist/datastore.db.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Datastore, PropertyFilter } from '@google-cloud/datastore';
|
|
2
2
|
import { BaseCommonDB, commonDBFullSupport } from '@naturalcycles/db-lib';
|
|
3
|
-
import { _round } from '@naturalcycles/js-lib';
|
|
4
3
|
import { _chunk } from '@naturalcycles/js-lib/array/array.util.js';
|
|
5
4
|
import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js';
|
|
6
5
|
import { _assert } from '@naturalcycles/js-lib/error/assert.js';
|
|
@@ -14,7 +13,7 @@ import { boldWhite } from '@naturalcycles/nodejs-lib/colors';
|
|
|
14
13
|
import { Pipeline } from '@naturalcycles/nodejs-lib/stream';
|
|
15
14
|
import { DatastoreType } from './datastore.model.js';
|
|
16
15
|
import { DatastoreStreamReadable } from './datastoreStreamReadable.js';
|
|
17
|
-
import { dbQueryToDatastoreQuery } from './query.util.js';
|
|
16
|
+
import { dbQueryToDatastoreQuery, getRunQueryOptions } from './query.util.js';
|
|
18
17
|
// Datastore (also Firestore and other Google APIs) supports max 500 of items when saving/deleting, etc.
|
|
19
18
|
const MAX_ITEMS = 500;
|
|
20
19
|
// It's an empyrical value, but anything less than infinity is better than infinity
|
|
@@ -90,7 +89,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
90
89
|
let ds = this.ds();
|
|
91
90
|
const keys = ids.map(id => this.key(ds, table, id));
|
|
92
91
|
let rows;
|
|
93
|
-
const dsOpt =
|
|
92
|
+
const dsOpt = getRunQueryOptions(opt);
|
|
94
93
|
if (this.cfg.timeout) {
|
|
95
94
|
// First try
|
|
96
95
|
try {
|
|
@@ -141,7 +140,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
141
140
|
async multiGet(map, opt = {}) {
|
|
142
141
|
const result = {};
|
|
143
142
|
const ds = this.ds();
|
|
144
|
-
const dsOpt =
|
|
143
|
+
const dsOpt = getRunQueryOptions(opt);
|
|
145
144
|
const keys = [];
|
|
146
145
|
for (const [table, ids] of _stringMapEntries(map)) {
|
|
147
146
|
result[table] = [];
|
|
@@ -174,7 +173,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
174
173
|
}
|
|
175
174
|
const ds = this.ds();
|
|
176
175
|
const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table));
|
|
177
|
-
const dsOpt =
|
|
176
|
+
const dsOpt = getRunQueryOptions(opt);
|
|
178
177
|
const qr = await this.runDatastoreQuery(q, dsOpt);
|
|
179
178
|
// Special case when projection query didn't specify 'id'
|
|
180
179
|
if (dbQuery._selectedFieldNames && !dbQuery._selectedFieldNames.includes('id')) {
|
|
@@ -186,7 +185,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
186
185
|
const ds = this.ds();
|
|
187
186
|
const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table));
|
|
188
187
|
const aq = ds.createAggregationQuery(q).count('count');
|
|
189
|
-
const dsOpt =
|
|
188
|
+
const dsOpt = getRunQueryOptions(opt);
|
|
190
189
|
const [entities] = await ds.runAggregationQuery(aq, dsOpt);
|
|
191
190
|
return entities[0]?.count;
|
|
192
191
|
}
|
|
@@ -209,7 +208,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
209
208
|
};
|
|
210
209
|
const readable = opt.experimentalCursorStream
|
|
211
210
|
? new DatastoreStreamReadable(q, opt)
|
|
212
|
-
: ds.runQueryStream(q,
|
|
211
|
+
: ds.runQueryStream(q, getRunQueryOptions(opt));
|
|
213
212
|
return Pipeline.from(readable).mapSync(r => this.mapId(r));
|
|
214
213
|
}
|
|
215
214
|
// https://github.com/GoogleCloudPlatform/nodejs-getting-started/blob/master/2-structured-data/books/model-datastore.js
|
|
@@ -255,7 +254,7 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
255
254
|
}
|
|
256
255
|
const ds = this.ds();
|
|
257
256
|
const datastoreQuery = dbQueryToDatastoreQuery(q.select([]), ds.createQuery(q.table));
|
|
258
|
-
const dsOpt =
|
|
257
|
+
const dsOpt = getRunQueryOptions(opt);
|
|
259
258
|
const { rows } = await this.runDatastoreQuery(datastoreQuery, dsOpt);
|
|
260
259
|
return await this.deleteByIds(q.table, rows.map(obj => obj.id), opt);
|
|
261
260
|
}
|
|
@@ -500,18 +499,6 @@ export class DatastoreDB extends BaseCommonDB {
|
|
|
500
499
|
this.cfg.logger.error(err);
|
|
501
500
|
}
|
|
502
501
|
}
|
|
503
|
-
getRunQueryOptions(opt) {
|
|
504
|
-
if (!opt.readAt)
|
|
505
|
-
return {};
|
|
506
|
-
// Datastore expects UnixTimestamp in milliseconds
|
|
507
|
-
// Datastore requires the timestamp to be rounded to the whole minutes
|
|
508
|
-
const readTime = _round(opt.readAt, 60) * 1000;
|
|
509
|
-
if (readTime >= Date.now() - 1000) {
|
|
510
|
-
// To avoid the error of: The requested 'read_time' cannot be in the future
|
|
511
|
-
return {};
|
|
512
|
-
}
|
|
513
|
-
return { readTime };
|
|
514
|
-
}
|
|
515
502
|
}
|
|
516
503
|
/**
|
|
517
504
|
* https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
|
|
@@ -3,6 +3,7 @@ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
|
|
|
3
3
|
import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js';
|
|
4
4
|
import { createCommonLoggerAtLevel } from '@naturalcycles/js-lib/log';
|
|
5
5
|
import { pRetry } from '@naturalcycles/js-lib/promise/pRetry.js';
|
|
6
|
+
import { getRunQueryOptions } from './query.util.js';
|
|
6
7
|
export class DatastoreStreamReadable extends Readable {
|
|
7
8
|
q;
|
|
8
9
|
table;
|
|
@@ -39,11 +40,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
39
40
|
batchSize,
|
|
40
41
|
highWaterMark,
|
|
41
42
|
};
|
|
42
|
-
this.dsOpt =
|
|
43
|
-
if (opt.readAt) {
|
|
44
|
-
// Datastore expects UnixTimestamp in milliseconds
|
|
45
|
-
this.dsOpt.readTime = opt.readAt * 1000;
|
|
46
|
-
}
|
|
43
|
+
this.dsOpt = getRunQueryOptions(opt);
|
|
47
44
|
const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel);
|
|
48
45
|
this.logger = logger;
|
|
49
46
|
this.originalLimit = q.limitVal;
|
|
@@ -82,7 +79,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
82
79
|
return;
|
|
83
80
|
}
|
|
84
81
|
if (this.paused) {
|
|
85
|
-
this.logger.
|
|
82
|
+
this.logger.debug(`_read #${this.countReads}, queryIsRunning: ${this.queryIsRunning}, unpausing stream`);
|
|
86
83
|
this.paused = false;
|
|
87
84
|
}
|
|
88
85
|
if (this.queryIsRunning) {
|
|
@@ -121,7 +118,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
121
118
|
const rows = res[0];
|
|
122
119
|
const info = res[1];
|
|
123
120
|
this.rowsRetrieved += rows.length;
|
|
124
|
-
logger.
|
|
121
|
+
logger.debug(`${table} got ${rows.length} rows in ${_ms(queryTook)}, ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(this.totalWait)}`);
|
|
125
122
|
this.endCursor = info.endCursor;
|
|
126
123
|
this.queryIsRunning = false; // ready to take more _reads
|
|
127
124
|
this.lastQueryDone = Date.now();
|
|
@@ -150,7 +147,7 @@ export class DatastoreStreamReadable extends Readable {
|
|
|
150
147
|
logger.debug(`${table} stream is already paused`);
|
|
151
148
|
}
|
|
152
149
|
else {
|
|
153
|
-
logger.
|
|
150
|
+
logger.debug(`${table} pausing the stream`);
|
|
154
151
|
this.paused = true;
|
|
155
152
|
}
|
|
156
153
|
}
|
package/dist/query.util.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { type Query } from '@google-cloud/datastore';
|
|
2
|
+
import type { RunQueryOptions } from '@google-cloud/datastore/build/src/query.js';
|
|
2
3
|
import type { DBQuery } from '@naturalcycles/db-lib';
|
|
3
4
|
import type { ObjectWithId } from '@naturalcycles/js-lib/types';
|
|
5
|
+
import type { DatastoreDBReadOptions } from './datastore.model.js';
|
|
4
6
|
export declare function dbQueryToDatastoreQuery<ROW extends ObjectWithId>(dbQuery: Readonly<DBQuery<ROW>>, emptyQuery: Query): Query;
|
|
7
|
+
export declare function getRunQueryOptions(opt: DatastoreDBReadOptions): RunQueryOptions;
|
package/dist/query.util.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PropertyFilter } from '@google-cloud/datastore';
|
|
2
|
+
import { _round } from '@naturalcycles/js-lib';
|
|
2
3
|
const FNAME_MAP = {
|
|
3
4
|
id: '__key__',
|
|
4
5
|
};
|
|
@@ -47,3 +48,15 @@ export function dbQueryToDatastoreQuery(dbQuery, emptyQuery) {
|
|
|
47
48
|
}
|
|
48
49
|
return q;
|
|
49
50
|
}
|
|
51
|
+
export function getRunQueryOptions(opt) {
|
|
52
|
+
if (!opt.readAt)
|
|
53
|
+
return {};
|
|
54
|
+
// Datastore expects UnixTimestamp in milliseconds
|
|
55
|
+
// Datastore requires the timestamp to be rounded to the whole minutes
|
|
56
|
+
let readTime = _round(opt.readAt, 60) * 1000;
|
|
57
|
+
if (readTime >= Date.now() - 1000) {
|
|
58
|
+
// To avoid the error of: The requested 'read_time' cannot be in the future
|
|
59
|
+
readTime -= 60_000;
|
|
60
|
+
}
|
|
61
|
+
return { readTime };
|
|
62
|
+
}
|
package/package.json
CHANGED
package/src/datastore.db.ts
CHANGED
|
@@ -15,7 +15,6 @@ import type {
|
|
|
15
15
|
RunQueryResult,
|
|
16
16
|
} from '@naturalcycles/db-lib'
|
|
17
17
|
import { BaseCommonDB, commonDBFullSupport } from '@naturalcycles/db-lib'
|
|
18
|
-
import { _round } from '@naturalcycles/js-lib'
|
|
19
18
|
import { _chunk } from '@naturalcycles/js-lib/array/array.util.js'
|
|
20
19
|
import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js'
|
|
21
20
|
import { _assert } from '@naturalcycles/js-lib/error/assert.js'
|
|
@@ -47,7 +46,7 @@ import type {
|
|
|
47
46
|
} from './datastore.model.js'
|
|
48
47
|
import { DatastoreType } from './datastore.model.js'
|
|
49
48
|
import { DatastoreStreamReadable } from './datastoreStreamReadable.js'
|
|
50
|
-
import { dbQueryToDatastoreQuery } from './query.util.js'
|
|
49
|
+
import { dbQueryToDatastoreQuery, getRunQueryOptions } from './query.util.js'
|
|
51
50
|
|
|
52
51
|
// Datastore (also Firestore and other Google APIs) supports max 500 of items when saving/deleting, etc.
|
|
53
52
|
const MAX_ITEMS = 500
|
|
@@ -146,7 +145,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
146
145
|
const keys = ids.map(id => this.key(ds, table, id))
|
|
147
146
|
let rows: any[]
|
|
148
147
|
|
|
149
|
-
const dsOpt =
|
|
148
|
+
const dsOpt = getRunQueryOptions(opt)
|
|
150
149
|
|
|
151
150
|
if (this.cfg.timeout) {
|
|
152
151
|
// First try
|
|
@@ -216,7 +215,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
216
215
|
): Promise<StringMap<ROW[]>> {
|
|
217
216
|
const result: StringMap<ROW[]> = {}
|
|
218
217
|
const ds = this.ds()
|
|
219
|
-
const dsOpt =
|
|
218
|
+
const dsOpt = getRunQueryOptions(opt)
|
|
220
219
|
const keys: Key[] = []
|
|
221
220
|
for (const [table, ids] of _stringMapEntries(map)) {
|
|
222
221
|
result[table] = []
|
|
@@ -260,7 +259,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
260
259
|
|
|
261
260
|
const ds = this.ds()
|
|
262
261
|
const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table))
|
|
263
|
-
const dsOpt =
|
|
262
|
+
const dsOpt = getRunQueryOptions(opt)
|
|
264
263
|
const qr = await this.runDatastoreQuery<ROW>(q, dsOpt)
|
|
265
264
|
|
|
266
265
|
// Special case when projection query didn't specify 'id'
|
|
@@ -278,7 +277,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
278
277
|
const ds = this.ds()
|
|
279
278
|
const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table))
|
|
280
279
|
const aq = ds.createAggregationQuery(q).count('count')
|
|
281
|
-
const dsOpt =
|
|
280
|
+
const dsOpt = getRunQueryOptions(opt)
|
|
282
281
|
const [entities] = await ds.runAggregationQuery(aq, dsOpt)
|
|
283
282
|
return entities[0]?.count
|
|
284
283
|
}
|
|
@@ -313,7 +312,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
313
312
|
|
|
314
313
|
const readable = opt.experimentalCursorStream
|
|
315
314
|
? new DatastoreStreamReadable<ROW>(q, opt)
|
|
316
|
-
: ds.runQueryStream(q,
|
|
315
|
+
: ds.runQueryStream(q, getRunQueryOptions(opt))
|
|
317
316
|
|
|
318
317
|
return Pipeline.from<ROW>(readable).mapSync(r => this.mapId<ROW>(r))
|
|
319
318
|
}
|
|
@@ -383,7 +382,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
383
382
|
|
|
384
383
|
const ds = this.ds()
|
|
385
384
|
const datastoreQuery = dbQueryToDatastoreQuery(q.select([]), ds.createQuery(q.table))
|
|
386
|
-
const dsOpt =
|
|
385
|
+
const dsOpt = getRunQueryOptions(opt)
|
|
387
386
|
const { rows } = await this.runDatastoreQuery<ObjectWithId>(datastoreQuery, dsOpt)
|
|
388
387
|
return await this.deleteByIds(
|
|
389
388
|
q.table,
|
|
@@ -680,20 +679,6 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
680
679
|
this.cfg.logger.error(err)
|
|
681
680
|
}
|
|
682
681
|
}
|
|
683
|
-
|
|
684
|
-
private getRunQueryOptions(opt: DatastoreDBReadOptions): RunQueryOptions {
|
|
685
|
-
if (!opt.readAt) return {}
|
|
686
|
-
|
|
687
|
-
// Datastore expects UnixTimestamp in milliseconds
|
|
688
|
-
// Datastore requires the timestamp to be rounded to the whole minutes
|
|
689
|
-
const readTime = _round(opt.readAt, 60) * 1000
|
|
690
|
-
if (readTime >= Date.now() - 1000) {
|
|
691
|
-
// To avoid the error of: The requested 'read_time' cannot be in the future
|
|
692
|
-
return {}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
return { readTime }
|
|
696
|
-
}
|
|
697
682
|
}
|
|
698
683
|
|
|
699
684
|
/**
|
|
@@ -12,6 +12,7 @@ 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'
|
|
14
14
|
import type { DatastoreDBStreamOptions } from './datastore.model.js'
|
|
15
|
+
import { getRunQueryOptions } from './query.util.js'
|
|
15
16
|
|
|
16
17
|
export class DatastoreStreamReadable<T = any> extends Readable implements ReadableTyped<T> {
|
|
17
18
|
private readonly table: string
|
|
@@ -53,12 +54,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
53
54
|
batchSize,
|
|
54
55
|
highWaterMark,
|
|
55
56
|
}
|
|
56
|
-
this.dsOpt =
|
|
57
|
-
if (opt.readAt) {
|
|
58
|
-
// Datastore expects UnixTimestamp in milliseconds
|
|
59
|
-
this.dsOpt.readTime = opt.readAt * 1000
|
|
60
|
-
}
|
|
61
|
-
|
|
57
|
+
this.dsOpt = getRunQueryOptions(opt)
|
|
62
58
|
const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel)
|
|
63
59
|
this.logger = logger
|
|
64
60
|
this.originalLimit = q.limitVal
|
|
@@ -112,7 +108,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
112
108
|
}
|
|
113
109
|
|
|
114
110
|
if (this.paused) {
|
|
115
|
-
this.logger.
|
|
111
|
+
this.logger.debug(
|
|
116
112
|
`_read #${this.countReads}, queryIsRunning: ${this.queryIsRunning}, unpausing stream`,
|
|
117
113
|
)
|
|
118
114
|
this.paused = false
|
|
@@ -162,7 +158,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
162
158
|
const info: RunQueryInfo = res[1]
|
|
163
159
|
|
|
164
160
|
this.rowsRetrieved += rows.length
|
|
165
|
-
logger.
|
|
161
|
+
logger.debug(
|
|
166
162
|
`${table} got ${rows.length} rows in ${_ms(queryTook)}, ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(
|
|
167
163
|
this.totalWait,
|
|
168
164
|
)}`,
|
|
@@ -201,7 +197,7 @@ export class DatastoreStreamReadable<T = any> extends Readable implements Readab
|
|
|
201
197
|
if (this.paused) {
|
|
202
198
|
logger.debug(`${table} stream is already paused`)
|
|
203
199
|
} else {
|
|
204
|
-
logger.
|
|
200
|
+
logger.debug(`${table} pausing the stream`)
|
|
205
201
|
this.paused = true
|
|
206
202
|
}
|
|
207
203
|
}
|
package/src/query.util.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { PropertyFilter, type Query } from '@google-cloud/datastore'
|
|
2
|
+
import type { RunQueryOptions } from '@google-cloud/datastore/build/src/query.js'
|
|
2
3
|
import type { DBQuery, DBQueryFilterOperator } from '@naturalcycles/db-lib'
|
|
4
|
+
import { _round } from '@naturalcycles/js-lib'
|
|
3
5
|
import type { ObjectWithId, StringMap } from '@naturalcycles/js-lib/types'
|
|
6
|
+
import type { DatastoreDBReadOptions } from './datastore.model.js'
|
|
4
7
|
|
|
5
8
|
const FNAME_MAP: StringMap = {
|
|
6
9
|
id: '__key__',
|
|
@@ -64,3 +67,17 @@ export function dbQueryToDatastoreQuery<ROW extends ObjectWithId>(
|
|
|
64
67
|
|
|
65
68
|
return q
|
|
66
69
|
}
|
|
70
|
+
|
|
71
|
+
export function getRunQueryOptions(opt: DatastoreDBReadOptions): RunQueryOptions {
|
|
72
|
+
if (!opt.readAt) return {}
|
|
73
|
+
|
|
74
|
+
// Datastore expects UnixTimestamp in milliseconds
|
|
75
|
+
// Datastore requires the timestamp to be rounded to the whole minutes
|
|
76
|
+
let readTime = _round(opt.readAt, 60) * 1000
|
|
77
|
+
if (readTime >= Date.now() - 1000) {
|
|
78
|
+
// To avoid the error of: The requested 'read_time' cannot be in the future
|
|
79
|
+
readTime -= 60_000
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { readTime }
|
|
83
|
+
}
|