@naturalcycles/datastore-lib 3.17.2 → 3.18.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.
@@ -35,8 +35,12 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
35
35
  const datastoreLib = require('@google-cloud/datastore');
36
36
  const DS = datastoreLib.Datastore;
37
37
  (_a = this.cfg).projectId || (_a.projectId = this.cfg.credentials?.project_id || process.env['GOOGLE_CLOUD_PROJECT']);
38
- (0, js_lib_1._assert)(this.cfg.projectId, '"projectId" is not set for DatastoreDB');
39
- this.cfg.logger.log(`DatastoreDB connected to ${(0, colors_1.boldWhite)(this.cfg.projectId)}`);
38
+ if (this.cfg.projectId) {
39
+ this.cfg.logger.log(`DatastoreDB connected to ${(0, colors_1.boldWhite)(this.cfg.projectId)}`);
40
+ }
41
+ else if (process.env['GOOGLE_APPLICATION_CREDENTIALS']) {
42
+ this.cfg.logger.log(`DatastoreDB connected via GOOGLE_APPLICATION_CREDENTIALS`);
43
+ }
40
44
  if (this.cfg.useLegacyGRPC) {
41
45
  this.cfg.grpc = require('grpc');
42
46
  }
@@ -55,9 +59,29 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
55
59
  if (!ids.length)
56
60
  return [];
57
61
  const keys = ids.map(id => this.key(table, id));
58
- const [entities] = await this.ds().get(keys);
59
- return (entities
60
- .map(e => this.mapId(e))
62
+ let rows;
63
+ try {
64
+ if (this.cfg.timeout) {
65
+ const r = await (0, js_lib_1.pTimeout)(this.ds().get(keys), {
66
+ timeout: this.cfg.timeout,
67
+ name: `datastore.getByIds(${table})`,
68
+ });
69
+ rows = r[0];
70
+ }
71
+ else {
72
+ rows = (await this.ds().get(keys))[0];
73
+ }
74
+ }
75
+ catch (err) {
76
+ this.cfg.logger.log('datastore recreated on error');
77
+ // This is to debug "GCP Datastore Timeout issue"
78
+ const datastoreLib = require('@google-cloud/datastore');
79
+ const DS = datastoreLib.Datastore;
80
+ this.cachedDatastore = new DS(this.cfg);
81
+ throw err;
82
+ }
83
+ return (rows
84
+ .map(r => this.mapId(r))
61
85
  // Seems like datastore .get() method doesn't return items properly sorted by input ids, so we gonna sort them here
62
86
  // same ids are not expected here
63
87
  .sort((a, b) => (a.id > b.id ? 1 : -1)));
@@ -34,6 +34,13 @@ export interface DatastoreDBCfg extends DatastoreOptions {
34
34
  * Default to `console`
35
35
  */
36
36
  logger?: CommonLogger;
37
+ /**
38
+ * Experimental option, currently only applies to `getByIds`.
39
+ * Applies pTimeout to Datastore operation, re-creates Datastore on any error.
40
+ *
41
+ * @experimental
42
+ */
43
+ timeout?: number;
37
44
  }
38
45
  export interface DatastoreCredentials {
39
46
  type?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/datastore-lib",
3
- "version": "3.17.2",
3
+ "version": "3.18.3",
4
4
  "description": "Opinionated library to work with Google Datastore",
5
5
  "scripts": {
6
6
  "prepare": "husky install"
@@ -17,7 +17,7 @@
17
17
  "devDependencies": {
18
18
  "@google-cloud/datastore": "^6.0.0",
19
19
  "@naturalcycles/dev-lib": "^12.0.1",
20
- "@types/node": "^16.0.0",
20
+ "@types/node": "^17.0.8",
21
21
  "jest": "^27.0.4"
22
22
  },
23
23
  "files": [
@@ -24,6 +24,7 @@ import {
24
24
  JsonSchemaRootObject,
25
25
  CommonLogger,
26
26
  commonLoggerMinLevel,
27
+ pTimeout,
27
28
  } from '@naturalcycles/js-lib'
28
29
  import { ReadableTyped } from '@naturalcycles/nodejs-lib'
29
30
  import { boldWhite } from '@naturalcycles/nodejs-lib/dist/colors'
@@ -83,9 +84,11 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
83
84
  const DS = datastoreLib.Datastore as typeof Datastore
84
85
  this.cfg.projectId ||= this.cfg.credentials?.project_id || process.env['GOOGLE_CLOUD_PROJECT']
85
86
 
86
- _assert(this.cfg.projectId, '"projectId" is not set for DatastoreDB')
87
-
88
- this.cfg.logger.log(`DatastoreDB connected to ${boldWhite(this.cfg.projectId)}`)
87
+ if (this.cfg.projectId) {
88
+ this.cfg.logger.log(`DatastoreDB connected to ${boldWhite(this.cfg.projectId)}`)
89
+ } else if (process.env['GOOGLE_APPLICATION_CREDENTIALS']) {
90
+ this.cfg.logger.log(`DatastoreDB connected via GOOGLE_APPLICATION_CREDENTIALS`)
91
+ }
89
92
 
90
93
  if (this.cfg.useLegacyGRPC) {
91
94
  this.cfg.grpc = require('grpc')
@@ -113,11 +116,32 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
113
116
  ): Promise<ROW[]> {
114
117
  if (!ids.length) return []
115
118
  const keys = ids.map(id => this.key(table, id))
116
- const [entities] = await this.ds().get(keys)
119
+ let rows: any[]
120
+
121
+ try {
122
+ if (this.cfg.timeout) {
123
+ const r = await pTimeout(this.ds().get(keys), {
124
+ timeout: this.cfg.timeout,
125
+ name: `datastore.getByIds(${table})`,
126
+ })
127
+ rows = r[0]
128
+ } else {
129
+ rows = (await this.ds().get(keys))[0]
130
+ }
131
+ } catch (err) {
132
+ this.cfg.logger.log('datastore recreated on error')
133
+
134
+ // This is to debug "GCP Datastore Timeout issue"
135
+ const datastoreLib = require('@google-cloud/datastore')
136
+ const DS = datastoreLib.Datastore as typeof Datastore
137
+ this.cachedDatastore = new DS(this.cfg)
138
+
139
+ throw err
140
+ }
117
141
 
118
142
  return (
119
- (entities as any[])
120
- .map(e => this.mapId<ROW>(e))
143
+ rows
144
+ .map(r => this.mapId<ROW>(r))
121
145
  // Seems like datastore .get() method doesn't return items properly sorted by input ids, so we gonna sort them here
122
146
  // same ids are not expected here
123
147
  .sort((a, b) => (a.id > b.id ? 1 : -1))
@@ -41,6 +41,14 @@ export interface DatastoreDBCfg extends DatastoreOptions {
41
41
  * Default to `console`
42
42
  */
43
43
  logger?: CommonLogger
44
+
45
+ /**
46
+ * Experimental option, currently only applies to `getByIds`.
47
+ * Applies pTimeout to Datastore operation, re-creates Datastore on any error.
48
+ *
49
+ * @experimental
50
+ */
51
+ timeout?: number
44
52
  }
45
53
 
46
54
  export interface DatastoreCredentials {