@naturalcycles/datastore-lib 3.18.3 → 3.19.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.
- package/dist/datastore.db.js +28 -16
- package/package.json +1 -1
- package/src/datastore.db.ts +30 -18
package/dist/datastore.db.js
CHANGED
|
@@ -60,25 +60,31 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
|
|
|
60
60
|
return [];
|
|
61
61
|
const keys = ids.map(id => this.key(table, id));
|
|
62
62
|
let rows;
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
if (this.cfg.timeout) {
|
|
64
|
+
// First try
|
|
65
|
+
try {
|
|
65
66
|
const r = await (0, js_lib_1.pTimeout)(this.ds().get(keys), {
|
|
66
67
|
timeout: this.cfg.timeout,
|
|
67
68
|
name: `datastore.getByIds(${table})`,
|
|
68
69
|
});
|
|
69
70
|
rows = r[0];
|
|
70
71
|
}
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
catch {
|
|
73
|
+
this.cfg.logger.log('datastore recreated on error');
|
|
74
|
+
// This is to debug "GCP Datastore Timeout issue"
|
|
75
|
+
const datastoreLib = require('@google-cloud/datastore');
|
|
76
|
+
const DS = datastoreLib.Datastore;
|
|
77
|
+
this.cachedDatastore = new DS(this.cfg);
|
|
78
|
+
// Second try (will throw)
|
|
79
|
+
const r = await (0, js_lib_1.pTimeout)(this.ds().get(keys), {
|
|
80
|
+
timeout: this.cfg.timeout,
|
|
81
|
+
name: `datastore.getByIds(${table}) second try`,
|
|
82
|
+
});
|
|
83
|
+
rows = r[0];
|
|
73
84
|
}
|
|
74
85
|
}
|
|
75
|
-
|
|
76
|
-
this.
|
|
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;
|
|
86
|
+
else {
|
|
87
|
+
rows = (await this.ds().get(keys))[0];
|
|
82
88
|
}
|
|
83
89
|
return (rows
|
|
84
90
|
.map(r => this.mapId(r))
|
|
@@ -137,12 +143,12 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
|
|
|
137
143
|
*/
|
|
138
144
|
async saveBatch(table, rows, opt = {}) {
|
|
139
145
|
const entities = rows.map(obj => this.toDatastoreEntity(table, obj, opt.excludeFromIndexes));
|
|
140
|
-
const save = (0, js_lib_1.
|
|
146
|
+
const save = (0, js_lib_1.pRetryFn)(async (batch) => {
|
|
141
147
|
await (opt.tx || this.ds()).save(batch);
|
|
142
148
|
}, {
|
|
143
149
|
// Here we retry the GOAWAY errors that are somewhat common for Datastore
|
|
144
150
|
// Currently only retrying them here in .saveBatch(), cause probably they're only thrown when saving
|
|
145
|
-
predicate: err => RETRY_ON.some(s => err?.message
|
|
151
|
+
predicate: err => RETRY_ON.some(s => err?.message?.includes(s)),
|
|
146
152
|
name: `DatastoreLib.saveBatch(${table})`,
|
|
147
153
|
maxAttempts: 5,
|
|
148
154
|
delay: 5000,
|
|
@@ -153,13 +159,19 @@ class DatastoreDB extends db_lib_1.BaseCommonDB {
|
|
|
153
159
|
logger: this.cfg.logger,
|
|
154
160
|
});
|
|
155
161
|
try {
|
|
156
|
-
|
|
162
|
+
const chunks = (0, js_lib_1._chunk)(entities, MAX_ITEMS);
|
|
163
|
+
if (chunks.length === 1) {
|
|
164
|
+
// Not using pMap in hope to preserve stack trace
|
|
165
|
+
await save(chunks[0]);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
await (0, js_lib_1.pMap)(chunks, async (batch) => await save(batch));
|
|
169
|
+
}
|
|
157
170
|
}
|
|
158
171
|
catch (err) {
|
|
159
172
|
// console.log(`datastore.save ${kind}`, { obj, entity })
|
|
160
173
|
this.cfg.logger.error(`error in DatastoreLib.saveBatch for ${table} (${rows.length} rows)`, err);
|
|
161
|
-
|
|
162
|
-
return await Promise.reject(err);
|
|
174
|
+
throw err;
|
|
163
175
|
}
|
|
164
176
|
}
|
|
165
177
|
async deleteByQuery(q, opt) {
|
package/package.json
CHANGED
package/src/datastore.db.ts
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
JsonSchemaObject,
|
|
18
18
|
JsonSchemaString,
|
|
19
19
|
pMap,
|
|
20
|
-
pRetry,
|
|
21
20
|
_assert,
|
|
22
21
|
_chunk,
|
|
23
22
|
_omit,
|
|
@@ -25,6 +24,7 @@ import {
|
|
|
25
24
|
CommonLogger,
|
|
26
25
|
commonLoggerMinLevel,
|
|
27
26
|
pTimeout,
|
|
27
|
+
pRetryFn,
|
|
28
28
|
} from '@naturalcycles/js-lib'
|
|
29
29
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
30
30
|
import { boldWhite } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
@@ -118,25 +118,31 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
118
118
|
const keys = ids.map(id => this.key(table, id))
|
|
119
119
|
let rows: any[]
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
if (this.cfg.timeout) {
|
|
122
|
+
// First try
|
|
123
|
+
try {
|
|
123
124
|
const r = await pTimeout(this.ds().get(keys), {
|
|
124
125
|
timeout: this.cfg.timeout,
|
|
125
126
|
name: `datastore.getByIds(${table})`,
|
|
126
127
|
})
|
|
127
128
|
rows = r[0]
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
} catch (err) {
|
|
132
|
-
this.cfg.logger.log('datastore recreated on error')
|
|
129
|
+
} catch {
|
|
130
|
+
this.cfg.logger.log('datastore recreated on error')
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
// This is to debug "GCP Datastore Timeout issue"
|
|
133
|
+
const datastoreLib = require('@google-cloud/datastore')
|
|
134
|
+
const DS = datastoreLib.Datastore as typeof Datastore
|
|
135
|
+
this.cachedDatastore = new DS(this.cfg)
|
|
138
136
|
|
|
139
|
-
|
|
137
|
+
// Second try (will throw)
|
|
138
|
+
const r = await pTimeout(this.ds().get(keys), {
|
|
139
|
+
timeout: this.cfg.timeout,
|
|
140
|
+
name: `datastore.getByIds(${table}) second try`,
|
|
141
|
+
})
|
|
142
|
+
rows = r[0]
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
rows = (await this.ds().get(keys))[0]
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
return (
|
|
@@ -237,14 +243,14 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
237
243
|
this.toDatastoreEntity(table, obj, opt.excludeFromIndexes as string[]),
|
|
238
244
|
)
|
|
239
245
|
|
|
240
|
-
const save =
|
|
246
|
+
const save = pRetryFn(
|
|
241
247
|
async (batch: DatastorePayload<ROW>[]) => {
|
|
242
248
|
await (opt.tx || this.ds()).save(batch)
|
|
243
249
|
},
|
|
244
250
|
{
|
|
245
251
|
// Here we retry the GOAWAY errors that are somewhat common for Datastore
|
|
246
252
|
// Currently only retrying them here in .saveBatch(), cause probably they're only thrown when saving
|
|
247
|
-
predicate: err => RETRY_ON.some(s =>
|
|
253
|
+
predicate: err => RETRY_ON.some(s => err?.message?.includes(s)),
|
|
248
254
|
name: `DatastoreLib.saveBatch(${table})`,
|
|
249
255
|
maxAttempts: 5,
|
|
250
256
|
delay: 5000,
|
|
@@ -257,15 +263,21 @@ export class DatastoreDB extends BaseCommonDB implements CommonDB {
|
|
|
257
263
|
)
|
|
258
264
|
|
|
259
265
|
try {
|
|
260
|
-
|
|
266
|
+
const chunks = _chunk(entities, MAX_ITEMS)
|
|
267
|
+
if (chunks.length === 1) {
|
|
268
|
+
// Not using pMap in hope to preserve stack trace
|
|
269
|
+
await save(chunks[0]!)
|
|
270
|
+
} else {
|
|
271
|
+
await pMap(chunks, async batch => await save(batch))
|
|
272
|
+
}
|
|
261
273
|
} catch (err) {
|
|
262
274
|
// console.log(`datastore.save ${kind}`, { obj, entity })
|
|
263
275
|
this.cfg.logger.error(
|
|
264
276
|
`error in DatastoreLib.saveBatch for ${table} (${rows.length} rows)`,
|
|
265
277
|
err,
|
|
266
278
|
)
|
|
267
|
-
|
|
268
|
-
|
|
279
|
+
|
|
280
|
+
throw err
|
|
269
281
|
}
|
|
270
282
|
}
|
|
271
283
|
|