@naturalcycles/datastore-lib 3.39.1 → 3.39.3

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.
@@ -11,7 +11,7 @@ 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
13
  // It's an empyrical value, but anything less than infinity is better than infinity
14
- const DATASTORE_RECOMMENDED_CONCURRENCY = 16;
14
+ const DATASTORE_RECOMMENDED_CONCURRENCY = 8;
15
15
  const RETRY_ON = [
16
16
  'GOAWAY',
17
17
  'UNAVAILABLE',
@@ -86,23 +86,33 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
86
86
  });
87
87
  rows = r[0];
88
88
  }
89
- catch {
89
+ catch (err) {
90
+ if (!(err instanceof js_lib_1.TimeoutError)) {
91
+ // Not a timeout error, re-throw
92
+ throw err;
93
+ }
90
94
  this.cfg.logger.log('datastore recreated on error');
91
95
  // This is to debug "GCP Datastore Timeout issue"
92
96
  const datastoreLib = require('@google-cloud/datastore');
93
97
  const DS = datastoreLib.Datastore;
94
98
  this.cachedDatastore = new DS(this.cfg);
95
99
  // Second try (will throw)
96
- const r = await (0, js_lib_1.pRetry)(() => (opt.tx?.tx || this.ds()).get(keys, dsOpt), {
97
- ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
98
- maxAttempts: 3,
99
- timeout: this.cfg.timeout,
100
- errorData: {
101
- // This error will be grouped ACROSS all endpoints and usages
102
- fingerprint: [DATASTORE_TIMEOUT],
103
- },
104
- });
105
- rows = r[0];
100
+ try {
101
+ const r = await (0, js_lib_1.pRetry)(() => (opt.tx?.tx || this.ds()).get(keys, dsOpt), {
102
+ ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
103
+ maxAttempts: 3,
104
+ timeout: this.cfg.timeout,
105
+ });
106
+ rows = r[0];
107
+ }
108
+ catch (err) {
109
+ if (err instanceof js_lib_1.TimeoutError) {
110
+ (0, js_lib_1._errorDataAppend)(err, {
111
+ fingerprint: [DATASTORE_TIMEOUT],
112
+ });
113
+ }
114
+ throw err;
115
+ }
106
116
  }
107
117
  }
108
118
  else {
@@ -189,6 +199,11 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
189
199
  }
190
200
  }
191
201
  catch (err) {
202
+ if (err instanceof js_lib_1.TimeoutError) {
203
+ (0, js_lib_1._errorDataAppend)(err, {
204
+ fingerprint: [DATASTORE_TIMEOUT],
205
+ });
206
+ }
192
207
  // console.log(`datastore.save ${kind}`, { obj, entity })
193
208
  this.cfg.logger.error(`error in DatastoreLib.saveBatch for ${table} (${rows.length} rows)`, err);
194
209
  throw err;
@@ -379,9 +394,10 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
379
394
  logFailures: true,
380
395
  // logAll: true,
381
396
  logger: this.cfg.logger,
382
- errorData: {
383
- fingerprint: [DATASTORE_TIMEOUT],
384
- },
397
+ // not appending fingerprint here, otherwise it would just group all kinds of errors, not just Timeout errors
398
+ // errorData: {
399
+ // fingerprint: [DATASTORE_TIMEOUT],
400
+ // },
385
401
  };
386
402
  }
387
403
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
- "version": "3.39.1",
3
+ "version": "3.39.3",
4
4
  "description": "Opinionated library to work with Google Datastore",
5
5
  "scripts": {
6
6
  "prepare": "husky",
@@ -11,15 +11,15 @@
11
11
  "lbt": "dev-lib lbt"
12
12
  },
13
13
  "dependencies": {
14
- "@google-cloud/datastore": "^9.0.0",
15
- "@naturalcycles/db-lib": "^9.0.0",
16
- "@naturalcycles/js-lib": "^14.116.0",
17
- "@naturalcycles/nodejs-lib": "^13.1.0"
14
+ "@google-cloud/datastore": "^9",
15
+ "@naturalcycles/db-lib": "^9",
16
+ "@naturalcycles/js-lib": "^14",
17
+ "@naturalcycles/nodejs-lib": "^13"
18
18
  },
19
19
  "devDependencies": {
20
- "@naturalcycles/dev-lib": "^15.2.0",
21
- "@types/node": "^22.0.0",
22
- "jest": "^29.0.3"
20
+ "@naturalcycles/dev-lib": "^15",
21
+ "@types/node": "^22",
22
+ "jest": "^29"
23
23
  },
24
24
  "files": [
25
25
  "dist",
@@ -32,7 +32,7 @@
32
32
  "main": "dist/index.js",
33
33
  "types": "dist/index.d.ts",
34
34
  "engines": {
35
- "node": ">=20.13.0"
35
+ "node": ">=22.12.0"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"
@@ -19,6 +19,7 @@ import {
19
19
  import {
20
20
  _assert,
21
21
  _chunk,
22
+ _errorDataAppend,
22
23
  _omit,
23
24
  CommonLogger,
24
25
  commonLoggerMinLevel,
@@ -35,6 +36,7 @@ import {
35
36
  pRetryFn,
36
37
  PRetryOptions,
37
38
  pTimeout,
39
+ TimeoutError,
38
40
  } from '@naturalcycles/js-lib'
39
41
  import { boldWhite, ReadableTyped } from '@naturalcycles/nodejs-lib'
40
42
  import {
@@ -54,7 +56,7 @@ import { dbQueryToDatastoreQuery } from './query.util'
54
56
  // Datastore (also Firestore and other Google APIs) supports max 500 of items when saving/deleting, etc.
55
57
  const MAX_ITEMS = 500
56
58
  // It's an empyrical value, but anything less than infinity is better than infinity
57
- const DATASTORE_RECOMMENDED_CONCURRENCY = 16
59
+ const DATASTORE_RECOMMENDED_CONCURRENCY = 8
58
60
 
59
61
  const RETRY_ON = [
60
62
  'GOAWAY',
@@ -160,7 +162,12 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
160
162
  },
161
163
  )
162
164
  rows = r[0]
163
- } catch {
165
+ } catch (err) {
166
+ if (!(err instanceof TimeoutError)) {
167
+ // Not a timeout error, re-throw
168
+ throw err
169
+ }
170
+
164
171
  this.cfg.logger.log('datastore recreated on error')
165
172
 
166
173
  // This is to debug "GCP Datastore Timeout issue"
@@ -169,19 +176,24 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
169
176
  this.cachedDatastore = new DS(this.cfg)
170
177
 
171
178
  // Second try (will throw)
172
- const r = await pRetry(
173
- () => ((opt.tx as DatastoreDBTransaction)?.tx || this.ds()).get(keys, dsOpt),
174
- {
175
- ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
176
- maxAttempts: 3,
177
- timeout: this.cfg.timeout,
178
- errorData: {
179
- // This error will be grouped ACROSS all endpoints and usages
180
- fingerprint: [DATASTORE_TIMEOUT],
179
+ try {
180
+ const r = await pRetry(
181
+ () => ((opt.tx as DatastoreDBTransaction)?.tx || this.ds()).get(keys, dsOpt),
182
+ {
183
+ ...this.getPRetryOptions(`datastore.getByIds(${table}) second try`),
184
+ maxAttempts: 3,
185
+ timeout: this.cfg.timeout,
181
186
  },
182
- },
183
- )
184
- rows = r[0]
187
+ )
188
+ rows = r[0]
189
+ } catch (err) {
190
+ if (err instanceof TimeoutError) {
191
+ _errorDataAppend(err, {
192
+ fingerprint: [DATASTORE_TIMEOUT],
193
+ })
194
+ }
195
+ throw err
196
+ }
185
197
  }
186
198
  } else {
187
199
  rows = await pRetry(
@@ -319,6 +331,12 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
319
331
  })
320
332
  }
321
333
  } catch (err) {
334
+ if (err instanceof TimeoutError) {
335
+ _errorDataAppend(err, {
336
+ fingerprint: [DATASTORE_TIMEOUT],
337
+ })
338
+ }
339
+
322
340
  // console.log(`datastore.save ${kind}`, { obj, entity })
323
341
  this.cfg.logger.error(
324
342
  `error in DatastoreLib.saveBatch for ${table} (${rows.length} rows)`,
@@ -556,9 +574,10 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
556
574
  logFailures: true,
557
575
  // logAll: true,
558
576
  logger: this.cfg.logger,
559
- errorData: {
560
- fingerprint: [DATASTORE_TIMEOUT],
561
- },
577
+ // not appending fingerprint here, otherwise it would just group all kinds of errors, not just Timeout errors
578
+ // errorData: {
579
+ // fingerprint: [DATASTORE_TIMEOUT],
580
+ // },
562
581
  }
563
582
  }
564
583