@naturalcycles/datastore-lib 3.25.4 → 3.26.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.
@@ -48,7 +48,7 @@ export declare class DatastoreDB extends BaseCommonDB implements CommonDB {
48
48
  getStats(table: string): Promise<DatastoreStats | undefined>;
49
49
  getStatsCount(table: string): Promise<number | undefined>;
50
50
  getTableProperties(table: string): Promise<DatastorePropertyStats[]>;
51
- mapId<T = any>(o: any, preserveKey?: boolean): T;
51
+ mapId<T extends ObjectWithId>(o: any, preserveKey?: boolean): T;
52
52
  toDatastoreEntity<T = any>(kind: string, o: T & {
53
53
  id?: string | number;
54
54
  }, excludeFromIndexes?: string[]): DatastorePayload<T>;
@@ -10,7 +10,14 @@ const DatastoreStreamReadable_1 = require("./DatastoreStreamReadable");
10
10
  const query_util_1 = require("./query.util");
11
11
  // Datastore (also Firestore and other Google APIs) supports max 500 of items when saving/deleting, etc.
12
12
  const MAX_ITEMS = 500;
13
- const RETRY_ON = ['GOAWAY', 'UNAVAILABLE', 'UNKNOWN', 'DEADLINE_EXCEEDED', 'much contention'];
13
+ const RETRY_ON = [
14
+ 'GOAWAY',
15
+ 'UNAVAILABLE',
16
+ 'UNKNOWN',
17
+ 'DEADLINE_EXCEEDED',
18
+ 'much contention',
19
+ 'timeout',
20
+ ].map(s => s.toLowerCase());
14
21
  // Examples of errors:
15
22
  // UNKNOWN: Stream removed
16
23
  const methodMap = {
@@ -80,9 +87,10 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
80
87
  const DS = datastoreLib.Datastore;
81
88
  this.cachedDatastore = new DS(this.cfg);
82
89
  // Second try (will throw)
83
- const r = await (0, js_lib_1.pTimeout)(() => this.ds().get(keys), {
90
+ const r = await (0, js_lib_1.pRetry)(() => this.ds().get(keys), {
91
+ ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
92
+ maxAttempts: 3,
84
93
  timeout: this.cfg.timeout,
85
- name: `datastore.getByIds(${table}) second try`,
86
94
  errorData: {
87
95
  // This error will be grouped ACROSS all endpoints and usages
88
96
  fingerprint: ['DATASTORE_TIMEOUT'],
@@ -92,7 +100,9 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
92
100
  }
93
101
  }
94
102
  else {
95
- rows = (await this.ds().get(keys))[0];
103
+ rows = await (0, js_lib_1.pRetry)(async () => {
104
+ return (await this.ds().get(keys))[0];
105
+ }, this.getPRetryOptions(`datastore.getByIds(${table})`));
96
106
  }
97
107
  return (rows
98
108
  .map(r => this.mapId(r))
@@ -101,7 +111,7 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
101
111
  .sort((a, b) => (a.id > b.id ? 1 : -1)));
102
112
  }
103
113
  getQueryKind(q) {
104
- if (!q || !q.kinds || !q.kinds.length)
114
+ if (!q?.kinds?.length)
105
115
  return ''; // should never be the case, but
106
116
  return q.kinds[0];
107
117
  }
@@ -246,7 +256,7 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
246
256
  }
247
257
  async getStatsCount(table) {
248
258
  const stats = await this.getStats(table);
249
- return stats && stats.count;
259
+ return stats?.count;
250
260
  }
251
261
  async getTableProperties(table) {
252
262
  const q = this.ds()
@@ -350,11 +360,9 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
350
360
  }
351
361
  else if (dtype === datastore_model_1.DatastoreType.NULL) {
352
362
  // check, maybe we can just skip this type and do nothing?
353
- if (!s.properties[name]) {
354
- s.properties[name] = {
355
- type: 'null',
356
- };
357
- }
363
+ s.properties[name] ||= {
364
+ type: 'null',
365
+ };
358
366
  }
359
367
  else {
360
368
  throw new Error(`Unknown Datastore Type '${stats.property_type}' for ${table}.${name}`);
@@ -364,11 +372,12 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
364
372
  }
365
373
  getPRetryOptions(name) {
366
374
  return {
367
- predicate: err => RETRY_ON.some(s => err?.message?.includes(s)),
375
+ predicate: err => RETRY_ON.some(s => err?.message?.toLowerCase()?.includes(s)),
368
376
  name,
377
+ timeout: 10000,
369
378
  maxAttempts: 5,
370
379
  delay: 5000,
371
- delayMultiplier: 2,
380
+ delayMultiplier: 1.5,
372
381
  logFirstAttempt: false,
373
382
  logFailures: true,
374
383
  // logAll: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
- "version": "3.25.4",
3
+ "version": "3.26.1",
4
4
  "description": "Opinionated library to work with Google Datastore",
5
5
  "scripts": {
6
6
  "prepare": "husky install"
@@ -47,7 +47,14 @@ import { dbQueryToDatastoreQuery } from './query.util'
47
47
  // Datastore (also Firestore and other Google APIs) supports max 500 of items when saving/deleting, etc.
48
48
  const MAX_ITEMS = 500
49
49
 
50
- const RETRY_ON = ['GOAWAY', 'UNAVAILABLE', 'UNKNOWN', 'DEADLINE_EXCEEDED', 'much contention']
50
+ const RETRY_ON = [
51
+ 'GOAWAY',
52
+ 'UNAVAILABLE',
53
+ 'UNKNOWN',
54
+ 'DEADLINE_EXCEEDED',
55
+ 'much contention',
56
+ 'timeout',
57
+ ].map(s => s.toLowerCase())
51
58
  // Examples of errors:
52
59
  // UNKNOWN: Stream removed
53
60
 
@@ -144,9 +151,10 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
144
151
  this.cachedDatastore = new DS(this.cfg)
145
152
 
146
153
  // Second try (will throw)
147
- const r = await pTimeout(() => this.ds().get(keys), {
154
+ const r = await pRetry(() => this.ds().get(keys), {
155
+ ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
156
+ maxAttempts: 3,
148
157
  timeout: this.cfg.timeout,
149
- name: `datastore.getByIds(${table}) second try`,
150
158
  errorData: {
151
159
  // This error will be grouped ACROSS all endpoints and usages
152
160
  fingerprint: ['DATASTORE_TIMEOUT'],
@@ -155,7 +163,9 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
155
163
  rows = r[0]
156
164
  }
157
165
  } else {
158
- rows = (await this.ds().get(keys))[0]
166
+ rows = await pRetry(async () => {
167
+ return (await this.ds().get(keys))[0]
168
+ }, this.getPRetryOptions(`datastore.getByIds(${table})`))
159
169
  }
160
170
 
161
171
  return (
@@ -168,7 +178,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
168
178
  }
169
179
 
170
180
  getQueryKind(q: Query): string {
171
- if (!q || !q.kinds || !q.kinds.length) return '' // should never be the case, but
181
+ if (!q?.kinds?.length) return '' // should never be the case, but
172
182
  return q.kinds[0]!
173
183
  }
174
184
 
@@ -380,7 +390,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
380
390
 
381
391
  async getStatsCount(table: string): Promise<number | undefined> {
382
392
  const stats = await this.getStats(table)
383
- return stats && stats.count
393
+ return stats?.count
384
394
  }
385
395
 
386
396
  async getTableProperties(table: string): Promise<DatastorePropertyStats[]> {
@@ -391,7 +401,7 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
391
401
  return stats
392
402
  }
393
403
 
394
- mapId<T = any>(o: any, preserveKey = false): T {
404
+ mapId<T extends ObjectWithId>(o: any, preserveKey = false): T {
395
405
  if (!o) return o
396
406
  const r = {
397
407
  ...o,
@@ -497,11 +507,9 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
497
507
  s.properties[name] = {} as JsonSchemaAny
498
508
  } else if (dtype === DatastoreType.NULL) {
499
509
  // check, maybe we can just skip this type and do nothing?
500
- if (!s.properties[name]) {
501
- s.properties[name] = {
502
- type: 'null',
503
- } as JsonSchemaNull
504
- }
510
+ s.properties[name] ||= {
511
+ type: 'null',
512
+ } as JsonSchemaNull
505
513
  } else {
506
514
  throw new Error(
507
515
  `Unknown Datastore Type '${stats.property_type}' for ${table}.${name as string}`,
@@ -514,11 +522,12 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
514
522
 
515
523
  private getPRetryOptions(name: string): PRetryOptions {
516
524
  return {
517
- predicate: err => RETRY_ON.some(s => err?.message?.includes(s)),
525
+ predicate: err => RETRY_ON.some(s => err?.message?.toLowerCase()?.includes(s)),
518
526
  name,
527
+ timeout: 10_000,
519
528
  maxAttempts: 5,
520
529
  delay: 5000,
521
- delayMultiplier: 2,
530
+ delayMultiplier: 1.5,
522
531
  logFirstAttempt: false,
523
532
  logFailures: true,
524
533
  // logAll: true,