@naturalcycles/db-lib 8.58.0 → 8.59.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.
@@ -3,6 +3,7 @@ import { ZlibOptions } from 'node:zlib';
3
3
  import { AsyncMapper, ErrorMode, UnixTimestampNumber, StringMap } from '@naturalcycles/js-lib';
4
4
  import { NDJsonStats, TransformLogProgressOptions, TransformMapOptions } from '@naturalcycles/nodejs-lib';
5
5
  import { CommonDB } from '../common.db';
6
+ import { DBQuery } from '../index';
6
7
  export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
7
8
  /**
8
9
  * DB to dump data from.
@@ -40,6 +41,12 @@ export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
40
41
  * If set - will do "incremental backup" (not full), only for entities that updated >= `sinceUpdated` (on a per table basis)
41
42
  */
42
43
  sinceUpdatedPerTable?: StringMap<UnixTimestampNumber>;
44
+ /**
45
+ * By default, dbPipelineBackup creates a Query based on sinceUpdated.
46
+ * But if queryPerTable is set for a table - it will override the Query that is ran for that table
47
+ * (and ignore sinceUpdated, sinceUpdatedPerTable, limit, and any other properties that modify the query).
48
+ */
49
+ queryPerTable?: StringMap<DBQuery>;
43
50
  /**
44
51
  * Directory path to store dumped files. Will create `${tableName}.ndjson` (or .ndjson.gz if gzip=true) files.
45
52
  * All parent directories will be created.
@@ -67,6 +74,11 @@ export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
67
74
  * Default mappers will be "passthroughMapper" (pass all data as-is).
68
75
  */
69
76
  mapperPerTable?: StringMap<AsyncMapper>;
77
+ /**
78
+ * If defined - it'll use that `logEvery` for that table.
79
+ * Default logEvery is 1000.
80
+ */
81
+ logEveryPerTable?: StringMap<number>;
70
82
  /**
71
83
  * You can alter default `transformMapOptions` here.
72
84
  *
@@ -18,7 +18,7 @@ const index_1 = require("../index");
18
18
  * Optionally you can provide mapperPerTable and @param transformMapOptions (one for all mappers) - it will run for each table.
19
19
  */
20
20
  async function dbPipelineBackup(opt) {
21
- const { db, concurrency = 16, limit = 0, outputDirPath, protectFromOverwrite = false, zlibOptions, mapperPerTable = {}, transformMapOptions, errorMode = js_lib_1.ErrorMode.SUPPRESS, emitSchemaFromDB = false, sortObjects = false, } = opt;
21
+ const { db, concurrency = 16, limit = 0, outputDirPath, protectFromOverwrite = false, zlibOptions, mapperPerTable = {}, queryPerTable = {}, logEveryPerTable = {}, transformMapOptions, errorMode = js_lib_1.ErrorMode.SUPPRESS, emitSchemaFromDB = false, sortObjects = false, } = opt;
22
22
  const strict = errorMode !== js_lib_1.ErrorMode.SUPPRESS;
23
23
  const gzip = opt.gzip !== false; // default to true
24
24
  let { tables } = opt;
@@ -28,15 +28,22 @@ async function dbPipelineBackup(opt) {
28
28
  console.log(`${(0, nodejs_lib_1.yellow)(tables.length)} ${(0, nodejs_lib_1.boldWhite)('table(s)')}:\n` + tables.join('\n'));
29
29
  const statsPerTable = {};
30
30
  await (0, js_lib_1.pMap)(tables, async (table) => {
31
- const sinceUpdated = opt.sinceUpdatedPerTable?.[table] || opt.sinceUpdated;
32
- const sinceUpdatedStr = sinceUpdated
33
- ? ' since ' + (0, nodejs_lib_1.grey)((0, js_lib_1.localTime)(sinceUpdated).toPretty())
34
- : '';
35
- console.log(`>> ${(0, nodejs_lib_1.grey)(table)}${sinceUpdatedStr}`);
36
31
  let q = index_1.DBQuery.create(table).limit(limit);
32
+ const sinceUpdated = opt.sinceUpdatedPerTable?.[table] ?? opt.sinceUpdated;
37
33
  if (sinceUpdated) {
38
34
  q = q.filter('updated', '>=', sinceUpdated);
39
35
  }
36
+ if (queryPerTable[table]) {
37
+ // Override the Query with this Query, completely ingoring any of the other query-related options
38
+ q = queryPerTable[table];
39
+ console.log(`>> ${(0, nodejs_lib_1.grey)(table)} ${q.pretty()}`);
40
+ }
41
+ else {
42
+ const sinceUpdatedStr = sinceUpdated
43
+ ? ' since ' + (0, nodejs_lib_1.grey)((0, js_lib_1.localTime)(sinceUpdated).toPretty())
44
+ : '';
45
+ console.log(`>> ${(0, nodejs_lib_1.grey)(table)}${sinceUpdatedStr}`);
46
+ }
40
47
  const filePath = `${outputDirPath}/${table}.ndjson` + (gzip ? '.gz' : '');
41
48
  const schemaFilePath = `${outputDirPath}/${table}.schema.json`;
42
49
  if (protectFromOverwrite && (0, nodejs_lib_1._pathExistsSync)(filePath)) {
@@ -45,7 +52,7 @@ async function dbPipelineBackup(opt) {
45
52
  const started = Date.now();
46
53
  let rows = 0;
47
54
  (0, nodejs_lib_1._ensureFileSync)(filePath);
48
- console.log(`>> ${(0, nodejs_lib_1.grey)(filePath)} started...`);
55
+ // console.log(`>> ${grey(filePath)} started...`)
49
56
  if (emitSchemaFromDB) {
50
57
  const schema = await db.getTableSchema(table);
51
58
  await (0, nodejs_lib_1._writeJson)(schemaFilePath, schema, { spaces: 2 });
@@ -54,8 +61,8 @@ async function dbPipelineBackup(opt) {
54
61
  await (0, nodejs_lib_1._pipeline)([
55
62
  db.streamQuery(q),
56
63
  (0, nodejs_lib_1.transformLogProgress)({
57
- logEvery: 1000,
58
64
  ...opt,
65
+ logEvery: logEveryPerTable[table] ?? opt.logEvery ?? 1000,
59
66
  metric: table,
60
67
  }),
61
68
  (0, nodejs_lib_1.transformMap)(mapperPerTable[table] || js_lib_1._passthroughMapper, {
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "engines": {
41
41
  "node": ">=18.12"
42
42
  },
43
- "version": "8.58.0",
43
+ "version": "8.59.0",
44
44
  "description": "Lowest Common Denominator API to supported Databases",
45
45
  "keywords": [
46
46
  "db",
@@ -76,6 +76,13 @@ export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
76
76
  */
77
77
  sinceUpdatedPerTable?: StringMap<UnixTimestampNumber>
78
78
 
79
+ /**
80
+ * By default, dbPipelineBackup creates a Query based on sinceUpdated.
81
+ * But if queryPerTable is set for a table - it will override the Query that is ran for that table
82
+ * (and ignore sinceUpdated, sinceUpdatedPerTable, limit, and any other properties that modify the query).
83
+ */
84
+ queryPerTable?: StringMap<DBQuery>
85
+
79
86
  /**
80
87
  * Directory path to store dumped files. Will create `${tableName}.ndjson` (or .ndjson.gz if gzip=true) files.
81
88
  * All parent directories will be created.
@@ -108,6 +115,12 @@ export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
108
115
  */
109
116
  mapperPerTable?: StringMap<AsyncMapper>
110
117
 
118
+ /**
119
+ * If defined - it'll use that `logEvery` for that table.
120
+ * Default logEvery is 1000.
121
+ */
122
+ logEveryPerTable?: StringMap<number>
123
+
111
124
  /**
112
125
  * You can alter default `transformMapOptions` here.
113
126
  *
@@ -153,6 +166,8 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
153
166
  protectFromOverwrite = false,
154
167
  zlibOptions,
155
168
  mapperPerTable = {},
169
+ queryPerTable = {},
170
+ logEveryPerTable = {},
156
171
  transformMapOptions,
157
172
  errorMode = ErrorMode.SUPPRESS,
158
173
  emitSchemaFromDB = false,
@@ -176,20 +191,25 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
176
191
  await pMap(
177
192
  tables,
178
193
  async table => {
179
- const sinceUpdated = opt.sinceUpdatedPerTable?.[table] || opt.sinceUpdated
180
-
181
- const sinceUpdatedStr = sinceUpdated
182
- ? ' since ' + grey(localTime(sinceUpdated).toPretty())
183
- : ''
184
-
185
- console.log(`>> ${grey(table)}${sinceUpdatedStr}`)
186
-
187
- let q = DBQuery.create(table).limit(limit)
194
+ let q = DBQuery.create<any>(table).limit(limit)
188
195
 
196
+ const sinceUpdated = opt.sinceUpdatedPerTable?.[table] ?? opt.sinceUpdated
189
197
  if (sinceUpdated) {
190
198
  q = q.filter('updated', '>=', sinceUpdated)
191
199
  }
192
200
 
201
+ if (queryPerTable[table]) {
202
+ // Override the Query with this Query, completely ingoring any of the other query-related options
203
+ q = queryPerTable[table]!
204
+
205
+ console.log(`>> ${grey(table)} ${q.pretty()}`)
206
+ } else {
207
+ const sinceUpdatedStr = sinceUpdated
208
+ ? ' since ' + grey(localTime(sinceUpdated).toPretty())
209
+ : ''
210
+ console.log(`>> ${grey(table)}${sinceUpdatedStr}`)
211
+ }
212
+
193
213
  const filePath = `${outputDirPath}/${table}.ndjson` + (gzip ? '.gz' : '')
194
214
  const schemaFilePath = `${outputDirPath}/${table}.schema.json`
195
215
 
@@ -202,7 +222,7 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
202
222
 
203
223
  _ensureFileSync(filePath)
204
224
 
205
- console.log(`>> ${grey(filePath)} started...`)
225
+ // console.log(`>> ${grey(filePath)} started...`)
206
226
 
207
227
  if (emitSchemaFromDB) {
208
228
  const schema = await db.getTableSchema(table)
@@ -213,8 +233,8 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
213
233
  await _pipeline([
214
234
  db.streamQuery(q),
215
235
  transformLogProgress({
216
- logEvery: 1000,
217
236
  ...opt,
237
+ logEvery: logEveryPerTable[table] ?? opt.logEvery ?? 1000,
218
238
  metric: table,
219
239
  }),
220
240
  transformMap(mapperPerTable[table] || _passthroughMapper, {