@naturalcycles/datastore-lib 3.30.2 → 3.31.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.
@@ -1,5 +1,6 @@
1
+ import { Transaction } from '@google-cloud/datastore';
1
2
  import type { Datastore, Key, Query } from '@google-cloud/datastore';
2
- import { BaseCommonDB, CommonDB, DBQuery, DBTransaction, RunQueryResult } from '@naturalcycles/db-lib';
3
+ import { BaseCommonDB, CommonDB, CommonDBSupport, DBQuery, DBTransaction, RunQueryResult } from '@naturalcycles/db-lib';
3
4
  import { ObjectWithId, JsonSchemaObject, JsonSchemaRootObject, CommonLogger } from '@naturalcycles/js-lib';
4
5
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
5
6
  import { DatastoreDBCfg, DatastoreDBOptions, DatastoreDBSaveOptions, DatastoreDBStreamOptions, DatastorePayload, DatastorePropertyStats, DatastoreStats } from './datastore.model';
@@ -9,6 +10,7 @@ import { DatastoreDBCfg, DatastoreDBOptions, DatastoreDBSaveOptions, DatastoreDB
9
10
  * https://cloud.google.com/datastore/docs/datastore-api-tutorial
10
11
  */
11
12
  export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
13
+ support: CommonDBSupport;
12
14
  constructor(cfg?: DatastoreDBCfg);
13
15
  cfg: DatastoreDBCfg & {
14
16
  logger: CommonLogger;
@@ -20,8 +22,7 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
20
22
  protected KEY: symbol;
21
23
  ds(): Datastore;
22
24
  ping(): Promise<void>;
23
- getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: DatastoreDBOptions): Promise<ROW[]>;
24
- getQueryKind(q: Query): string;
25
+ getByIds<ROW extends ObjectWithId>(table: string, ids: string[], _opt?: DatastoreDBOptions): Promise<ROW[]>;
25
26
  runQuery<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, _opt?: DatastoreDBOptions): Promise<RunQueryResult<ROW>>;
26
27
  runQueryCount<ROW extends ObjectWithId>(dbQuery: DBQuery<ROW>, _opt?: DatastoreDBOptions): Promise<number>;
27
28
  runDatastoreQuery<ROW extends ObjectWithId>(q: Query): Promise<RunQueryResult<ROW>>;
@@ -36,11 +37,8 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
36
37
  * Limitation: Datastore's delete returns void, so we always return all ids here as "deleted"
37
38
  * regardless if they were actually deleted or not.
38
39
  */
39
- deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: DatastoreDBOptions): Promise<number>;
40
- /**
41
- * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
42
- */
43
- commitTransaction(_tx: DBTransaction, opt?: DatastoreDBSaveOptions): Promise<void>;
40
+ deleteByIds(table: string, ids: string[], opt?: DatastoreDBOptions): Promise<number>;
41
+ createTransaction(): Promise<DatastoreDBTransaction>;
44
42
  getAllStats(): Promise<DatastoreStats[]>;
45
43
  /**
46
44
  * Returns undefined e.g when Table is non-existing
@@ -60,3 +58,14 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
60
58
  getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
61
59
  private getPRetryOptions;
62
60
  }
61
+ /**
62
+ * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
63
+ */
64
+ export declare class DatastoreDBTransaction implements DBTransaction {
65
+ db: DatastoreDB;
66
+ tx: Transaction;
67
+ private constructor();
68
+ static create(db: DatastoreDB): Promise<DatastoreDBTransaction>;
69
+ commit(): Promise<void>;
70
+ rollback(): Promise<void>;
71
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DatastoreDB = void 0;
3
+ exports.DatastoreDBTransaction = exports.DatastoreDB = void 0;
4
4
  const node_stream_1 = require("node:stream");
5
5
  const datastore_1 = require("@google-cloud/datastore");
6
6
  const db_lib_1 = require("@naturalcycles/db-lib");
@@ -35,6 +35,10 @@ const methodMap = {
35
35
  class DatastoreDB extends db_lib_1.BaseCommonDB {
36
36
  constructor(cfg = {}) {
37
37
  super();
38
+ this.support = {
39
+ ...db_lib_1.commonDBFullSupport,
40
+ updateByQuery: false,
41
+ };
38
42
  this.cfg = {
39
43
  logger: console,
40
44
  ...cfg,
@@ -109,11 +113,10 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
109
113
  // same ids are not expected here
110
114
  .sort((a, b) => (a.id > b.id ? 1 : -1)));
111
115
  }
112
- getQueryKind(q) {
113
- if (!q?.kinds?.length)
114
- return ''; // should never be the case, but
115
- return q.kinds[0];
116
- }
116
+ // getQueryKind(q: Query): string {
117
+ // if (!q?.kinds?.length) return '' // should never be the case, but
118
+ // return q.kinds[0]!
119
+ // }
117
120
  async runQuery(dbQuery, _opt) {
118
121
  const idFilter = dbQuery._filters.find(f => f.name === 'id');
119
122
  if (idFilter) {
@@ -172,7 +175,7 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
172
175
  const entities = rows.map(obj => this.toDatastoreEntity(table, obj, opt.excludeFromIndexes));
173
176
  const method = methodMap[opt.saveMethod || 'upsert'] || 'save';
174
177
  const save = (0, js_lib_1.pRetryFn)(async (batch) => {
175
- await (opt.tx || this.ds())[method](batch);
178
+ await (opt.tx?.tx || this.ds())[method](batch);
176
179
  }, this.getPRetryOptions(`DatastoreLib.saveBatch(${table})`));
177
180
  try {
178
181
  const chunks = (0, js_lib_1._chunk)(entities, MAX_ITEMS);
@@ -206,38 +209,13 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
206
209
  */
207
210
  async deleteByIds(table, ids, opt = {}) {
208
211
  const keys = ids.map(id => this.key(table, id));
212
+ await (0, js_lib_1.pMap)((0, js_lib_1._chunk)(keys, MAX_ITEMS),
209
213
  // eslint-disable-next-line @typescript-eslint/return-await
210
- await (0, js_lib_1.pMap)((0, js_lib_1._chunk)(keys, MAX_ITEMS), async (batch) => await (opt.tx || this.ds()).delete(batch));
214
+ async (batch) => await (opt.tx?.tx || this.ds()).delete(batch));
211
215
  return ids.length;
212
216
  }
213
- /**
214
- * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
215
- */
216
- async commitTransaction(_tx, opt) {
217
- // Using Retry, because Datastore can throw errors like "too much contention" here
218
- await (0, js_lib_1.pRetry)(async () => {
219
- const tx = this.ds().transaction();
220
- try {
221
- await tx.run();
222
- const ops = (0, db_lib_1.mergeDBOperations)(_tx.ops);
223
- for await (const op of ops) {
224
- if (op.type === 'saveBatch') {
225
- await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt, tx });
226
- }
227
- else if (op.type === 'deleteByIds') {
228
- await this.deleteByIds(op.table, op.ids, { ...op.opt, ...opt, tx });
229
- }
230
- else {
231
- throw new Error(`DBOperation not supported: ${op.type}`);
232
- }
233
- }
234
- await tx.commit();
235
- }
236
- catch (err) {
237
- await tx.rollback();
238
- throw err; // rethrow
239
- }
240
- }, this.getPRetryOptions(`DatastoreLib.commitTransaction`));
217
+ async createTransaction() {
218
+ return await DatastoreDBTransaction.create(this);
241
219
  }
242
220
  async getAllStats() {
243
221
  const q = this.ds().createQuery('__Stat_Kind__');
@@ -393,3 +371,24 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
393
371
  }
394
372
  }
395
373
  exports.DatastoreDB = DatastoreDB;
374
+ /**
375
+ * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
376
+ */
377
+ class DatastoreDBTransaction {
378
+ constructor(db, tx) {
379
+ this.db = db;
380
+ this.tx = tx;
381
+ }
382
+ static async create(db) {
383
+ const tx = db.ds().transaction();
384
+ await tx.run();
385
+ return new DatastoreDBTransaction(db, tx);
386
+ }
387
+ async commit() {
388
+ await this.tx.commit();
389
+ }
390
+ async rollback() {
391
+ await this.tx.rollback();
392
+ }
393
+ }
394
+ exports.DatastoreDBTransaction = DatastoreDBTransaction;
@@ -1,4 +1,4 @@
1
- import type { DatastoreOptions, Key, Transaction } from '@google-cloud/datastore';
1
+ import type { DatastoreOptions, Key } from '@google-cloud/datastore';
2
2
  import { CommonDBOptions, CommonDBSaveOptions } from '@naturalcycles/db-lib';
3
3
  import { CommonLogger, NumberOfSeconds, ObjectWithId } from '@naturalcycles/js-lib';
4
4
  export interface DatastorePayload<T = any> {
@@ -100,10 +100,8 @@ export interface DatastoreDBStreamOptions extends DatastoreDBOptions {
100
100
  maxWait?: NumberOfSeconds;
101
101
  }
102
102
  export interface DatastoreDBOptions extends CommonDBOptions {
103
- tx?: Transaction;
104
103
  }
105
104
  export interface DatastoreDBSaveOptions<ROW extends Partial<ObjectWithId> = any> extends CommonDBSaveOptions<ROW> {
106
- tx?: Transaction;
107
105
  }
108
106
  export interface DatastoreStats {
109
107
  composite_index_count: number;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { DatastoreDB } from './datastore.db';
2
- import { DatastoreCredentials, DatastoreDBCfg, DatastoreDBOptions, DatastoreDBSaveOptions, DatastoreDBStreamOptions, DatastorePayload, DatastorePropertyStats, DatastoreStats, DatastoreType } from './datastore.model';
3
- import { DatastoreKeyValueDB, DatastoreKeyValueDBCfg } from './datastoreKeyValueDB';
4
- export type { DatastorePayload, DatastoreDBCfg, DatastoreKeyValueDBCfg, DatastoreStats, DatastoreCredentials, DatastorePropertyStats, DatastoreDBStreamOptions, DatastoreDBOptions, DatastoreDBSaveOptions, };
5
- export { DatastoreDB, DatastoreType, DatastoreKeyValueDB };
1
+ export * from './datastore.db';
2
+ export * from './datastore.model';
3
+ export * from './datastoreKeyValueDB';
package/dist/index.js CHANGED
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DatastoreKeyValueDB = exports.DatastoreType = exports.DatastoreDB = void 0;
4
- const datastore_db_1 = require("./datastore.db");
5
- Object.defineProperty(exports, "DatastoreDB", { enumerable: true, get: function () { return datastore_db_1.DatastoreDB; } });
6
- const datastore_model_1 = require("./datastore.model");
7
- Object.defineProperty(exports, "DatastoreType", { enumerable: true, get: function () { return datastore_model_1.DatastoreType; } });
8
- const datastoreKeyValueDB_1 = require("./datastoreKeyValueDB");
9
- Object.defineProperty(exports, "DatastoreKeyValueDB", { enumerable: true, get: function () { return datastoreKeyValueDB_1.DatastoreKeyValueDB; } });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./datastore.db"), exports);
5
+ tslib_1.__exportStar(require("./datastore.model"), exports);
6
+ tslib_1.__exportStar(require("./datastoreKeyValueDB"), exports);
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
- "version": "3.30.2",
3
+ "version": "3.31.0",
4
4
  "description": "Opinionated library to work with Google Datastore",
5
5
  "scripts": {
6
6
  "prepare": "husky install"
7
7
  },
8
8
  "dependencies": {
9
9
  "@google-cloud/datastore": "^8.0.0",
10
- "@naturalcycles/db-lib": "^8.46.1",
10
+ "@naturalcycles/db-lib": "^9.0.0",
11
11
  "@naturalcycles/js-lib": "^14.116.0",
12
12
  "@naturalcycles/nodejs-lib": "^13.1.0"
13
13
  },
@@ -1,13 +1,14 @@
1
1
  import { Transform } from 'node:stream'
2
- import { PropertyFilter } from '@google-cloud/datastore'
2
+ import { PropertyFilter, Transaction } from '@google-cloud/datastore'
3
3
  import type { Datastore, Key, Query } from '@google-cloud/datastore'
4
4
  import {
5
5
  BaseCommonDB,
6
6
  CommonDB,
7
+ commonDBFullSupport,
7
8
  CommonDBSaveMethod,
9
+ CommonDBSupport,
8
10
  DBQuery,
9
11
  DBTransaction,
10
- mergeDBOperations,
11
12
  RunQueryResult,
12
13
  } from '@naturalcycles/db-lib'
13
14
  import {
@@ -72,6 +73,11 @@ const methodMap: Record<CommonDBSaveMethod, string> = {
72
73
  * https://cloud.google.com/datastore/docs/datastore-api-tutorial
73
74
  */
74
75
  export class DatastoreDB extends BaseCommonDB implements CommonDB {
76
+ override support: CommonDBSupport = {
77
+ ...commonDBFullSupport,
78
+ updateByQuery: false,
79
+ }
80
+
75
81
  constructor(cfg: DatastoreDBCfg = {}) {
76
82
  super()
77
83
  this.cfg = {
@@ -125,7 +131,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
125
131
 
126
132
  override async getByIds<ROW extends ObjectWithId>(
127
133
  table: string,
128
- ids: ROW['id'][],
134
+ ids: string[],
129
135
  _opt?: DatastoreDBOptions,
130
136
  ): Promise<ROW[]> {
131
137
  if (!ids.length) return []
@@ -178,10 +184,10 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
178
184
  )
179
185
  }
180
186
 
181
- getQueryKind(q: Query): string {
182
- if (!q?.kinds?.length) return '' // should never be the case, but
183
- return q.kinds[0]!
184
- }
187
+ // getQueryKind(q: Query): string {
188
+ // if (!q?.kinds?.length) return '' // should never be the case, but
189
+ // return q.kinds[0]!
190
+ // }
185
191
 
186
192
  override async runQuery<ROW extends ObjectWithId>(
187
193
  dbQuery: DBQuery<ROW>,
@@ -284,7 +290,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
284
290
 
285
291
  const save = pRetryFn(
286
292
  async (batch: DatastorePayload<ROW>[]) => {
287
- await (opt.tx || this.ds())[method](batch)
293
+ await ((opt.tx as DatastoreDBTransaction)?.tx || this.ds())[method](batch)
288
294
  },
289
295
  this.getPRetryOptions(`DatastoreLib.saveBatch(${table})`),
290
296
  )
@@ -331,49 +337,23 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
331
337
  * Limitation: Datastore's delete returns void, so we always return all ids here as "deleted"
332
338
  * regardless if they were actually deleted or not.
333
339
  */
334
- async deleteByIds<ROW extends ObjectWithId>(
340
+ override async deleteByIds(
335
341
  table: string,
336
- ids: ROW['id'][],
342
+ ids: string[],
337
343
  opt: DatastoreDBOptions = {},
338
344
  ): Promise<number> {
339
345
  const keys = ids.map(id => this.key(table, id))
340
- // eslint-disable-next-line @typescript-eslint/return-await
341
- await pMap(_chunk(keys, MAX_ITEMS), async batch => await (opt.tx || this.ds()).delete(batch))
346
+
347
+ await pMap(
348
+ _chunk(keys, MAX_ITEMS),
349
+ // eslint-disable-next-line @typescript-eslint/return-await
350
+ async batch => await ((opt.tx as DatastoreDBTransaction)?.tx || this.ds()).delete(batch),
351
+ )
342
352
  return ids.length
343
353
  }
344
354
 
345
- /**
346
- * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
347
- */
348
- override async commitTransaction(
349
- _tx: DBTransaction,
350
- opt?: DatastoreDBSaveOptions,
351
- ): Promise<void> {
352
- // Using Retry, because Datastore can throw errors like "too much contention" here
353
- await pRetry(async () => {
354
- const tx = this.ds().transaction()
355
-
356
- try {
357
- await tx.run()
358
-
359
- const ops = mergeDBOperations(_tx.ops)
360
-
361
- for await (const op of ops) {
362
- if (op.type === 'saveBatch') {
363
- await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt, tx })
364
- } else if (op.type === 'deleteByIds') {
365
- await this.deleteByIds(op.table, op.ids, { ...op.opt, ...opt, tx })
366
- } else {
367
- throw new Error(`DBOperation not supported: ${(op as any).type}`)
368
- }
369
- }
370
-
371
- await tx.commit()
372
- } catch (err) {
373
- await tx.rollback()
374
- throw err // rethrow
375
- }
376
- }, this.getPRetryOptions(`DatastoreLib.commitTransaction`))
355
+ override async createTransaction(): Promise<DatastoreDBTransaction> {
356
+ return await DatastoreDBTransaction.create(this)
377
357
  }
378
358
 
379
359
  async getAllStats(): Promise<DatastoreStats[]> {
@@ -547,3 +527,26 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
547
527
  }
548
528
  }
549
529
  }
530
+
531
+ /**
532
+ * https://cloud.google.com/datastore/docs/concepts/transactions#datastore-datastore-transactional-update-nodejs
533
+ */
534
+ export class DatastoreDBTransaction implements DBTransaction {
535
+ private constructor(
536
+ public db: DatastoreDB,
537
+ public tx: Transaction,
538
+ ) {}
539
+
540
+ static async create(db: DatastoreDB): Promise<DatastoreDBTransaction> {
541
+ const tx = db.ds().transaction()
542
+ await tx.run()
543
+ return new DatastoreDBTransaction(db, tx)
544
+ }
545
+
546
+ async commit(): Promise<void> {
547
+ await this.tx.commit()
548
+ }
549
+ async rollback(): Promise<void> {
550
+ await this.tx.rollback()
551
+ }
552
+ }
@@ -1,4 +1,4 @@
1
- import type { DatastoreOptions, Key, Transaction } from '@google-cloud/datastore'
1
+ import type { DatastoreOptions, Key } from '@google-cloud/datastore'
2
2
  import { CommonDBOptions, CommonDBSaveOptions } from '@naturalcycles/db-lib'
3
3
  import { CommonLogger, NumberOfSeconds, ObjectWithId } from '@naturalcycles/js-lib'
4
4
 
@@ -114,13 +114,10 @@ export interface DatastoreDBStreamOptions extends DatastoreDBOptions {
114
114
  maxWait?: NumberOfSeconds
115
115
  }
116
116
 
117
- export interface DatastoreDBOptions extends CommonDBOptions {
118
- tx?: Transaction
119
- }
117
+ export interface DatastoreDBOptions extends CommonDBOptions {}
118
+
120
119
  export interface DatastoreDBSaveOptions<ROW extends Partial<ObjectWithId> = any>
121
- extends CommonDBSaveOptions<ROW> {
122
- tx?: Transaction
123
- }
120
+ extends CommonDBSaveOptions<ROW> {}
124
121
 
125
122
  export interface DatastoreStats {
126
123
  composite_index_count: number
package/src/index.ts CHANGED
@@ -1,27 +1,3 @@
1
- import { DatastoreDB } from './datastore.db'
2
- import {
3
- DatastoreCredentials,
4
- DatastoreDBCfg,
5
- DatastoreDBOptions,
6
- DatastoreDBSaveOptions,
7
- DatastoreDBStreamOptions,
8
- DatastorePayload,
9
- DatastorePropertyStats,
10
- DatastoreStats,
11
- DatastoreType,
12
- } from './datastore.model'
13
- import { DatastoreKeyValueDB, DatastoreKeyValueDBCfg } from './datastoreKeyValueDB'
14
-
15
- export type {
16
- DatastorePayload,
17
- DatastoreDBCfg,
18
- DatastoreKeyValueDBCfg,
19
- DatastoreStats,
20
- DatastoreCredentials,
21
- DatastorePropertyStats,
22
- DatastoreDBStreamOptions,
23
- DatastoreDBOptions,
24
- DatastoreDBSaveOptions,
25
- }
26
-
27
- export { DatastoreDB, DatastoreType, DatastoreKeyValueDB }
1
+ export * from './datastore.db'
2
+ export * from './datastore.model'
3
+ export * from './datastoreKeyValueDB'