@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.
@@ -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
@@ -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 = this.getRunQueryOptions(opt);
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 = this.getRunQueryOptions(opt);
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 = this.getRunQueryOptions(opt);
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 = this.getRunQueryOptions(opt);
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, this.getRunQueryOptions(opt));
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 = this.getRunQueryOptions(opt);
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.log(`_read #${this.countReads}, queryIsRunning: ${this.queryIsRunning}, unpausing stream`);
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.log(`${table} got ${rows.length} rows in ${_ms(queryTook)}, ${this.rowsRetrieved} rowsRetrieved, totalWait: ${_ms(this.totalWait)}`);
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.log(`${table} pausing the stream`);
150
+ logger.debug(`${table} pausing the stream`);
154
151
  this.paused = true;
155
152
  }
156
153
  }
@@ -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;
@@ -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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
3
  "type": "module",
4
- "version": "4.18.3",
4
+ "version": "4.18.5",
5
5
  "description": "Opinionated library to work with Google Datastore, implements CommonDB",
6
6
  "dependencies": {
7
7
  "@google-cloud/datastore": "^10",
@@ -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 = this.getRunQueryOptions(opt)
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 = this.getRunQueryOptions(opt)
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 = this.getRunQueryOptions(opt)
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 = this.getRunQueryOptions(opt)
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, this.getRunQueryOptions(opt))
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 = this.getRunQueryOptions(opt)
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.log(
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.log(
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.log(`${table} pausing the stream`)
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
+ }