@naturalcycles/datastore-lib 4.15.1 → 4.16.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.
@@ -4,7 +4,7 @@ import { BaseCommonDB } from '@naturalcycles/db-lib';
4
4
  import type { JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib/json-schema';
5
5
  import type { CommonLogger } from '@naturalcycles/js-lib/log';
6
6
  import { type ObjectWithId, type StringMap } from '@naturalcycles/js-lib/types';
7
- import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream';
7
+ import { Pipeline } from '@naturalcycles/nodejs-lib/stream';
8
8
  import type { DatastoreDBCfg, DatastoreDBOptions, DatastoreDBReadOptions, DatastoreDBSaveOptions, DatastoreDBStreamOptions, DatastorePropertyStats, DatastoreStats } from './datastore.model.js';
9
9
  /**
10
10
  * Datastore API:
@@ -31,7 +31,7 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
31
31
  runQuery<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, opt?: DatastoreDBReadOptions): Promise<RunQueryResult<ROW>>;
32
32
  runQueryCount<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, opt?: DatastoreDBReadOptions): Promise<number>;
33
33
  private runDatastoreQuery;
34
- streamQuery<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, _opt?: DatastoreDBStreamOptions): ReadableTyped<ROW>;
34
+ streamQuery<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, _opt?: DatastoreDBStreamOptions): Pipeline<ROW>;
35
35
  /**
36
36
  * Returns saved entities with generated id/updated/created (non-mutating!)
37
37
  */
@@ -1,7 +1,7 @@
1
- import { Transform } from 'node:stream';
2
1
  import { BaseCommonDB, commonDBFullSupport } from '@naturalcycles/db-lib';
3
2
  import { _round } from '@naturalcycles/js-lib';
4
3
  import { _chunk } from '@naturalcycles/js-lib/array/array.util.js';
4
+ import { _ms } from '@naturalcycles/js-lib/datetime/time.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
7
  import { _omit } from '@naturalcycles/js-lib/object/object.util.js';
@@ -10,6 +10,7 @@ import { pRetry, pRetryFn } from '@naturalcycles/js-lib/promise/pRetry.js';
10
10
  import { pTimeout } from '@naturalcycles/js-lib/promise/pTimeout.js';
11
11
  import { _stringMapEntries, _stringMapValues, } from '@naturalcycles/js-lib/types';
12
12
  import { boldWhite } from '@naturalcycles/nodejs-lib/colors';
13
+ import { Pipeline } from '@naturalcycles/nodejs-lib/stream';
13
14
  import { DatastoreType } from './datastore.model.js';
14
15
  import { DatastoreStreamReadable } from './datastoreStreamReadable.js';
15
16
  import { dbQueryToDatastoreQuery } from './query.util.js';
@@ -112,7 +113,7 @@ export class DatastoreDB extends BaseCommonDB {
112
113
  // Not a timeout error, re-throw
113
114
  throw err;
114
115
  }
115
- this.cfg.logger.log('datastore recreated on error');
116
+ this.cfg.logger.log(`datastore recreated on timeout (${_ms(this.cfg.timeout)}) while loading ${table}`);
116
117
  // This is to debug "GCP Datastore Timeout issue"
117
118
  const datastoreLib = await this.getDatastoreLib();
118
119
  const DS = datastoreLib.Datastore;
@@ -209,26 +210,18 @@ export class DatastoreDB extends BaseCommonDB {
209
210
  };
210
211
  }
211
212
  streamQuery(dbQuery, _opt) {
212
- const transform = new Transform({
213
- objectMode: true,
214
- transform: (chunk, _, cb) => {
215
- cb(null, this.mapId(chunk));
216
- },
217
- });
218
- void this.ds().then(async (ds) => {
213
+ return Pipeline.fromAsyncReadable(async () => {
214
+ const ds = await this.ds();
219
215
  const q = dbQueryToDatastoreQuery(dbQuery, ds.createQuery(dbQuery.table), await this.getPropertyFilter());
220
216
  const opt = {
221
217
  logger: this.cfg.logger,
222
218
  ...this.cfg.streamOptions,
223
219
  ..._opt,
224
220
  };
225
- (opt.experimentalCursorStream
221
+ return opt.experimentalCursorStream
226
222
  ? new DatastoreStreamReadable(q, opt)
227
- : ds.runQueryStream(q, this.getRunQueryOptions(opt)))
228
- .on('error', err => transform.destroy(err))
229
- .pipe(transform);
230
- });
231
- return transform;
223
+ : ds.runQueryStream(q, this.getRunQueryOptions(opt));
224
+ }).mapSync(r => this.mapId(r));
232
225
  }
233
226
  // https://github.com/GoogleCloudPlatform/nodejs-getting-started/blob/master/2-structured-data/books/model-datastore.js
234
227
  /**
@@ -1,5 +1,5 @@
1
1
  import type { CommonKeyValueDB, IncrementTuple, KeyValueDBTuple } from '@naturalcycles/db-lib/kv';
2
- import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream';
2
+ import type { Pipeline } from '@naturalcycles/nodejs-lib/stream';
3
3
  import { DatastoreDB } from './datastore.db.js';
4
4
  import type { DatastoreDBCfg } from './datastore.model.js';
5
5
  export interface DatastoreKeyValueDBCfg extends DatastoreDBCfg {
@@ -14,9 +14,9 @@ export declare class DatastoreKeyValueDB implements CommonKeyValueDB {
14
14
  getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]>;
15
15
  deleteByIds(table: string, ids: string[]): Promise<void>;
16
16
  saveBatch(table: string, entries: KeyValueDBTuple[]): Promise<void>;
17
- streamIds(table: string, limit?: number): ReadableTyped<string>;
18
- streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
19
- streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
17
+ streamIds(table: string, limit?: number): Pipeline<string>;
18
+ streamValues(table: string, limit?: number): Pipeline<Buffer>;
19
+ streamEntries(table: string, limit?: number): Pipeline<KeyValueDBTuple>;
20
20
  count(table: string): Promise<number>;
21
21
  incrementBatch(_table: string, _entries: IncrementTuple[]): Promise<IncrementTuple[]>;
22
22
  }
@@ -33,10 +33,7 @@ export class DatastoreKeyValueDB {
33
33
  const q = DBQuery.create(table)
34
34
  .select(['id'])
35
35
  .limit(limit || 0);
36
- return (this.db
37
- .streamQuery(q)
38
- // .on('error', err => stream.emit('error', err))
39
- .map(r => r.id));
36
+ return this.db.streamQuery(q).mapSync(r => r.id);
40
37
  }
41
38
  streamValues(table, limit) {
42
39
  // `select v` doesn't work for some reason
@@ -44,14 +41,11 @@ export class DatastoreKeyValueDB {
44
41
  return (this.db
45
42
  .streamQuery(q)
46
43
  // .on('error', err => stream.emit('error', err))
47
- .map(r => r.v));
44
+ .mapSync(r => r.v));
48
45
  }
49
46
  streamEntries(table, limit) {
50
47
  const q = DBQuery.create(table).limit(limit || 0);
51
- return (this.db
52
- .streamQuery(q)
53
- // .on('error', err => stream.emit('error', err))
54
- .map(r => [r.id, r.v]));
48
+ return this.db.streamQuery(q).mapSync(r => [r.id, r.v]);
55
49
  }
56
50
  async count(table) {
57
51
  const q = DBQuery.create(table);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
3
  "type": "module",
4
- "version": "4.15.1",
4
+ "version": "4.16.1",
5
5
  "description": "Opinionated library to work with Google Datastore, implements CommonDB",
6
6
  "dependencies": {
7
7
  "@google-cloud/datastore": "^10",
@@ -1,4 +1,3 @@
1
- import { Transform } from 'node:stream'
2
1
  import type { Datastore, Key, PropertyFilter, Query, Transaction } from '@google-cloud/datastore'
3
2
  import type { RunQueryOptions } from '@google-cloud/datastore/build/src/query.js'
4
3
  import type {
@@ -17,6 +16,7 @@ import type {
17
16
  import { BaseCommonDB, commonDBFullSupport } from '@naturalcycles/db-lib'
18
17
  import { _round } from '@naturalcycles/js-lib'
19
18
  import { _chunk } from '@naturalcycles/js-lib/array/array.util.js'
19
+ import { _ms } from '@naturalcycles/js-lib/datetime/time.util.js'
20
20
  import { _assert } from '@naturalcycles/js-lib/error/assert.js'
21
21
  import { _errorDataAppend, TimeoutError } from '@naturalcycles/js-lib/error/error.util.js'
22
22
  import type {
@@ -41,7 +41,7 @@ import {
41
41
  type StringMap,
42
42
  } from '@naturalcycles/js-lib/types'
43
43
  import { boldWhite } from '@naturalcycles/nodejs-lib/colors'
44
- import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
44
+ import { Pipeline } from '@naturalcycles/nodejs-lib/stream'
45
45
  import type {
46
46
  DatastoreDBCfg,
47
47
  DatastoreDBOptions,
@@ -183,7 +183,9 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
183
183
  throw err
184
184
  }
185
185
 
186
- this.cfg.logger.log('datastore recreated on error')
186
+ this.cfg.logger.log(
187
+ `datastore recreated on timeout (${_ms(this.cfg.timeout)}) while loading ${table}`,
188
+ )
187
189
 
188
190
  // This is to debug "GCP Datastore Timeout issue"
189
191
  const datastoreLib = await this.getDatastoreLib()
@@ -327,15 +329,10 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
327
329
  override streamQuery<ROW extends ObjectWithId>(
328
330
  dbQuery: DBQuery<ROW>,
329
331
  _opt?: DatastoreDBStreamOptions,
330
- ): ReadableTyped<ROW> {
331
- const transform = new Transform({
332
- objectMode: true,
333
- transform: (chunk, _, cb) => {
334
- cb(null, this.mapId(chunk))
335
- },
336
- })
332
+ ): Pipeline<ROW> {
333
+ return Pipeline.fromAsyncReadable<ROW>(async () => {
334
+ const ds = await this.ds()
337
335
 
338
- void this.ds().then(async ds => {
339
336
  const q = dbQueryToDatastoreQuery(
340
337
  dbQuery,
341
338
  ds.createQuery(dbQuery.table),
@@ -348,15 +345,10 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
348
345
  ..._opt,
349
346
  }
350
347
 
351
- ;(opt.experimentalCursorStream
348
+ return opt.experimentalCursorStream
352
349
  ? new DatastoreStreamReadable<ROW>(q, opt)
353
- : (ds.runQueryStream(q, this.getRunQueryOptions(opt)) as ReadableTyped<ROW>)
354
- )
355
- .on('error', err => transform.destroy(err))
356
- .pipe(transform)
357
- })
358
-
359
- return transform
350
+ : ds.runQueryStream(q, this.getRunQueryOptions(opt))
351
+ }).mapSync(r => this.mapId<ROW>(r))
360
352
  }
361
353
 
362
354
  // https://github.com/GoogleCloudPlatform/nodejs-getting-started/blob/master/2-structured-data/books/model-datastore.js
@@ -3,7 +3,7 @@ import type { CommonKeyValueDB, IncrementTuple, KeyValueDBTuple } from '@natural
3
3
  import { commonKeyValueDBFullSupport } from '@naturalcycles/db-lib/kv'
4
4
  import { AppError } from '@naturalcycles/js-lib/error/error.util.js'
5
5
  import type { ObjectWithId } from '@naturalcycles/js-lib/types'
6
- import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
6
+ import type { Pipeline } from '@naturalcycles/nodejs-lib/stream'
7
7
  import { DatastoreDB } from './datastore.db.js'
8
8
  import type { DatastoreDBCfg } from './datastore.model.js'
9
9
 
@@ -52,20 +52,15 @@ export class DatastoreKeyValueDB implements CommonKeyValueDB {
52
52
  )
53
53
  }
54
54
 
55
- streamIds(table: string, limit?: number): ReadableTyped<string> {
55
+ streamIds(table: string, limit?: number): Pipeline<string> {
56
56
  const q = DBQuery.create<ObjectWithId>(table)
57
57
  .select(['id'])
58
58
  .limit(limit || 0)
59
59
 
60
- return (
61
- this.db
62
- .streamQuery(q)
63
- // .on('error', err => stream.emit('error', err))
64
- .map(r => r.id)
65
- )
60
+ return this.db.streamQuery(q).mapSync(r => r.id)
66
61
  }
67
62
 
68
- streamValues(table: string, limit?: number): ReadableTyped<Buffer> {
63
+ streamValues(table: string, limit?: number): Pipeline<Buffer> {
69
64
  // `select v` doesn't work for some reason
70
65
  const q = DBQuery.create<KVObject>(table).limit(limit || 0)
71
66
 
@@ -73,19 +68,14 @@ export class DatastoreKeyValueDB implements CommonKeyValueDB {
73
68
  this.db
74
69
  .streamQuery(q)
75
70
  // .on('error', err => stream.emit('error', err))
76
- .map(r => r.v)
71
+ .mapSync(r => r.v)
77
72
  )
78
73
  }
79
74
 
80
- streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple> {
75
+ streamEntries(table: string, limit?: number): Pipeline<KeyValueDBTuple> {
81
76
  const q = DBQuery.create<KVObject>(table).limit(limit || 0)
82
77
 
83
- return (
84
- this.db
85
- .streamQuery(q)
86
- // .on('error', err => stream.emit('error', err))
87
- .map(r => [r.id, r.v])
88
- )
78
+ return this.db.streamQuery(q).mapSync(r => [r.id, r.v])
89
79
  }
90
80
 
91
81
  async count(table: string): Promise<number> {