@naturalcycles/db-lib 10.48.0 → 10.49.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.
@@ -143,11 +143,11 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
143
143
  * const storageRow = await dao.dbmToStorageRow(dbm)
144
144
  * await db.saveBatch(table, [storageRow])
145
145
  */
146
- dbmToStorageRow(dbm: DBM): Promise<ObjectWithId>;
146
+ dbmToStorageRow(dbm: DBM): ObjectWithId;
147
147
  /**
148
148
  * Converts multiple DBMs to storage rows.
149
149
  */
150
- dbmsToStorageRows(dbms: DBM[]): Promise<ObjectWithId[]>;
150
+ dbmsToStorageRows(dbms: DBM[]): ObjectWithId[];
151
151
  /**
152
152
  * Converts a storage row back to a DBM, applying decompression if needed.
153
153
  *
@@ -157,17 +157,19 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
157
157
  * const rows = await db.getByIds(table, ids)
158
158
  * const dbms = await Promise.all(rows.map(row => dao.storageRowToDBM(row)))
159
159
  */
160
- storageRowToDBM(row: ObjectWithId): Promise<DBM>;
160
+ storageRowToDBM(row: ObjectWithId): DBM;
161
161
  /**
162
162
  * Converts multiple storage rows to DBMs.
163
163
  */
164
- storageRowsToDBMs(rows: ObjectWithId[]): Promise<DBM[]>;
164
+ storageRowsToDBM(rows: ObjectWithId[]): DBM[];
165
+ /**
166
+ * Mutates `dbm`.
167
+ */
165
168
  private compress;
166
- private decompress;
167
169
  /**
168
170
  * Mutates `dbm`.
169
171
  */
170
- private decompressSync;
172
+ private decompress;
171
173
  anyToDBM(dbm: undefined, opt?: CommonDaoOptions): null;
172
174
  anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM;
173
175
  anyToDBMs(rows: DBM[], opt?: CommonDaoOptions): DBM[];
@@ -7,7 +7,7 @@ import { _filterUndefinedValues, _objectAssignExact, _omitWithUndefined, _pick,
7
7
  import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
8
8
  import { _objectKeys, _passthroughPredicate, _stringMapEntries, _stringMapValues, _typeCast, } from '@naturalcycles/js-lib/types';
9
9
  import { stringId } from '@naturalcycles/nodejs-lib';
10
- import { decompressZstdOrInflateToString, decompressZstdOrInflateToStringSync, zstdCompress, } from '@naturalcycles/nodejs-lib/zip';
10
+ import { zip2 } from '@naturalcycles/nodejs-lib/zip';
11
11
  import { DBLibError } from '../cnst.js';
12
12
  import { RunnableDBQuery } from '../query/dbQuery.js';
13
13
  import { CommonDaoTransaction } from './commonDaoTransaction.js';
@@ -105,7 +105,7 @@ export class CommonDao {
105
105
  return [];
106
106
  const table = opt.table || this.cfg.table;
107
107
  const rows = await (opt.tx || this.cfg.db).getByIds(table, ids, opt);
108
- return await this.storageRowsToDBMs(rows);
108
+ return this.storageRowsToDBM(rows);
109
109
  }
110
110
  async getBy(by, value, limit = 0, opt) {
111
111
  return await this.query().filterEq(by, value).limit(limit).runQuery(opt);
@@ -148,7 +148,7 @@ export class CommonDao {
148
148
  q.table = opt.table || q.table;
149
149
  const { rows: rawRows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
150
150
  const isPartialQuery = !!q._selectedFieldNames;
151
- const rows = isPartialQuery ? rawRows : await this.storageRowsToDBMs(rawRows);
151
+ const rows = isPartialQuery ? rawRows : this.storageRowsToDBM(rawRows);
152
152
  const bms = isPartialQuery ? rows : this.dbmsToBM(rows, opt);
153
153
  return {
154
154
  rows: bms,
@@ -164,7 +164,7 @@ export class CommonDao {
164
164
  q.table = opt.table || q.table;
165
165
  const { rows: rawRows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
166
166
  const isPartialQuery = !!q._selectedFieldNames;
167
- const rows = isPartialQuery ? rawRows : await this.storageRowsToDBMs(rawRows);
167
+ const rows = isPartialQuery ? rawRows : this.storageRowsToDBM(rawRows);
168
168
  const dbms = isPartialQuery ? rows : this.anyToDBMs(rows, opt);
169
169
  return { rows: dbms, ...queryResult };
170
170
  }
@@ -178,10 +178,7 @@ export class CommonDao {
178
178
  q.table = opt.table || q.table;
179
179
  let pipeline = this.cfg.db.streamQuery(q, opt);
180
180
  if (this.cfg.compress?.keys.length) {
181
- pipeline = pipeline.map(async row => await this.storageRowToDBM(row), {
182
- // lowered, to reduce the total buffer size a bit for uncompressed objects
183
- highWaterMark: 16,
184
- });
181
+ pipeline = pipeline.mapSync(row => this.storageRowToDBM(row));
185
182
  }
186
183
  const isPartialQuery = !!q._selectedFieldNames;
187
184
  if (isPartialQuery)
@@ -195,10 +192,7 @@ export class CommonDao {
195
192
  q.table = opt.table || q.table;
196
193
  let pipeline = this.cfg.db.streamQuery(q, opt);
197
194
  if (this.cfg.compress?.keys.length) {
198
- pipeline = pipeline.map(async row => await this.storageRowToDBM(row), {
199
- // lowered, to reduce the total buffer size a bit for uncompressed objects
200
- highWaterMark: 16,
201
- });
195
+ pipeline = pipeline.mapSync(row => this.storageRowToDBM(row));
202
196
  }
203
197
  const isPartialQuery = !!q._selectedFieldNames;
204
198
  if (isPartialQuery)
@@ -357,7 +351,7 @@ export class CommonDao {
357
351
  this.cfg.hooks.beforeSave?.(dbm);
358
352
  const table = opt.table || this.cfg.table;
359
353
  const saveOptions = this.prepareSaveOptions(opt);
360
- const row = await this.dbmToStorageRow(dbm);
354
+ const row = this.dbmToStorageRow(dbm);
361
355
  await (opt.tx || this.cfg.db).saveBatch(table, [row], saveOptions);
362
356
  if (saveOptions.assignGeneratedIds) {
363
357
  bm.id = dbm.id;
@@ -371,7 +365,7 @@ export class CommonDao {
371
365
  this.cfg.hooks.beforeSave?.(validDbm);
372
366
  const table = opt.table || this.cfg.table;
373
367
  const saveOptions = this.prepareSaveOptions(opt);
374
- const row = await this.dbmToStorageRow(validDbm);
368
+ const row = this.dbmToStorageRow(validDbm);
375
369
  await (opt.tx || this.cfg.db).saveBatch(table, [row], saveOptions);
376
370
  if (saveOptions.assignGeneratedIds) {
377
371
  dbm.id = validDbm.id;
@@ -389,7 +383,7 @@ export class CommonDao {
389
383
  }
390
384
  const table = opt.table || this.cfg.table;
391
385
  const saveOptions = this.prepareSaveOptions(opt);
392
- const rows = await this.dbmsToStorageRows(dbms);
386
+ const rows = this.dbmsToStorageRows(dbms);
393
387
  await (opt.tx || this.cfg.db).saveBatch(table, rows, saveOptions);
394
388
  if (saveOptions.assignGeneratedIds) {
395
389
  dbms.forEach((dbm, i) => (bms[i].id = dbm.id));
@@ -407,7 +401,7 @@ export class CommonDao {
407
401
  }
408
402
  const table = opt.table || this.cfg.table;
409
403
  const saveOptions = this.prepareSaveOptions(opt);
410
- const rows = await this.dbmsToStorageRows(validDbms);
404
+ const rows = this.dbmsToStorageRows(validDbms);
411
405
  await (opt.tx || this.cfg.db).saveBatch(table, rows, saveOptions);
412
406
  if (saveOptions.assignGeneratedIds) {
413
407
  validDbms.forEach((dbm, i) => (dbms[i].id = dbm.id));
@@ -457,7 +451,7 @@ export class CommonDao {
457
451
  this.assignIdCreatedUpdated(bm, opt);
458
452
  const dbm = this.bmToDBM(bm, opt);
459
453
  beforeSave?.(dbm);
460
- return await this.dbmToStorageRow(dbm);
454
+ return this.dbmToStorageRow(dbm);
461
455
  }, { errorMode })
462
456
  .chunk(chunkSize)
463
457
  .map(async batch => {
@@ -606,20 +600,24 @@ export class CommonDao {
606
600
  * const storageRow = await dao.dbmToStorageRow(dbm)
607
601
  * await db.saveBatch(table, [storageRow])
608
602
  */
609
- async dbmToStorageRow(dbm) {
603
+ dbmToStorageRow(dbm) {
610
604
  if (!this.cfg.compress?.keys.length)
611
605
  return dbm;
612
606
  const row = { ...dbm };
613
- await this.compress(row);
607
+ this.compress(row);
614
608
  return row;
615
609
  }
616
610
  /**
617
611
  * Converts multiple DBMs to storage rows.
618
612
  */
619
- async dbmsToStorageRows(dbms) {
613
+ dbmsToStorageRows(dbms) {
620
614
  if (!this.cfg.compress?.keys.length)
621
615
  return dbms;
622
- return await pMap(dbms, async dbm => await this.dbmToStorageRow(dbm));
616
+ return dbms.map(dbm => {
617
+ const row = { ...dbm };
618
+ this.compress(row);
619
+ return row;
620
+ });
623
621
  }
624
622
  /**
625
623
  * Converts a storage row back to a DBM, applying decompression if needed.
@@ -630,67 +628,46 @@ export class CommonDao {
630
628
  * const rows = await db.getByIds(table, ids)
631
629
  * const dbms = await Promise.all(rows.map(row => dao.storageRowToDBM(row)))
632
630
  */
633
- async storageRowToDBM(row) {
631
+ storageRowToDBM(row) {
634
632
  if (!this.cfg.compress?.keys.length)
635
633
  return row;
636
634
  const dbm = { ...row };
637
- if (this.cfg.compress.syncMode) {
638
- this.decompressSync(dbm);
639
- }
640
- else {
641
- await this.decompress(dbm);
642
- }
635
+ this.decompress(dbm);
643
636
  return dbm;
644
637
  }
645
638
  /**
646
639
  * Converts multiple storage rows to DBMs.
647
640
  */
648
- async storageRowsToDBMs(rows) {
641
+ storageRowsToDBM(rows) {
649
642
  if (!this.cfg.compress?.keys.length)
650
643
  return rows;
651
- if (this.cfg.compress.syncMode) {
652
- return rows.map(row => {
653
- const dbm = { ...row };
654
- this.decompressSync(dbm);
655
- return dbm;
656
- });
657
- }
658
- return await pMap(rows, async row => await this.storageRowToDBM(row));
644
+ return rows.map(row => {
645
+ const dbm = { ...row };
646
+ this.decompress(dbm);
647
+ return dbm;
648
+ });
659
649
  }
660
650
  /**
661
651
  * Mutates `dbm`.
662
652
  */
663
- async compress(dbm) {
653
+ compress(dbm) {
664
654
  if (!this.cfg.compress?.keys.length)
665
655
  return; // No compression requested
666
656
  const { keys, level = 1 } = this.cfg.compress;
667
657
  const properties = _pick(dbm, keys);
668
658
  const bufferString = JSON.stringify(properties);
669
- const __compressed = await zstdCompress(bufferString, level);
659
+ const __compressed = zip2.zstdCompressSync(bufferString, level);
670
660
  _omitWithUndefined(dbm, _objectKeys(properties), { mutate: true });
671
661
  Object.assign(dbm, { __compressed });
672
662
  }
673
663
  /**
674
664
  * Mutates `dbm`.
675
665
  */
676
- async decompress(dbm) {
677
- _typeCast(dbm);
678
- if (!Buffer.isBuffer(dbm.__compressed))
679
- return; // No compressed data
680
- // todo: stop supporting Inflate when we are sure that we have migrated everything to zstd
681
- const bufferString = await decompressZstdOrInflateToString(dbm.__compressed);
682
- const properties = JSON.parse(bufferString);
683
- dbm.__compressed = undefined;
684
- Object.assign(dbm, properties);
685
- }
686
- /**
687
- * Mutates `dbm`.
688
- */
689
- decompressSync(dbm) {
666
+ decompress(dbm) {
690
667
  _typeCast(dbm);
691
668
  if (!Buffer.isBuffer(dbm.__compressed))
692
669
  return; // No compressed data
693
- const bufferString = decompressZstdOrInflateToStringSync(dbm.__compressed);
670
+ const bufferString = zip2.zstdDecompressToStringSync(dbm.__compressed);
694
671
  const properties = JSON.parse(bufferString);
695
672
  dbm.__compressed = undefined;
696
673
  Object.assign(dbm, properties);
@@ -793,7 +770,7 @@ export class CommonDao {
793
770
  // todo: support tx
794
771
  const dbmsByTable = await db.multiGet(idsByTable, opt);
795
772
  const dbmByTableById = CommonDao.multiGetMapByTableById(dbmsByTable);
796
- return (await CommonDao.prepareMultiGetOutput(inputMap, dbmByTableById, opt));
773
+ return CommonDao.prepareMultiGetOutput(inputMap, dbmByTableById, opt);
797
774
  }
798
775
  static prepareMultiGetIds(inputMap) {
799
776
  const idSetByTable = {};
@@ -830,17 +807,17 @@ export class CommonDao {
830
807
  }
831
808
  return dbmByTableById;
832
809
  }
833
- static async prepareMultiGetOutput(inputMap, dbmByTableById, opt = {}) {
810
+ static prepareMultiGetOutput(inputMap, dbmByTableById, opt = {}) {
834
811
  const bmsByProp = {};
835
812
  // Loop over input props again, to produce the output of the same shape as requested
836
- await pMap(_stringMapEntries(inputMap), async ([prop, input]) => {
813
+ for (const [prop, input] of _stringMapEntries(inputMap)) {
837
814
  const { dao } = input;
838
815
  const { table } = dao.cfg;
839
816
  if ('id' in input) {
840
817
  // Singular
841
818
  const row = dbmByTableById[table][input.id];
842
819
  // Decompress before converting to BM
843
- const dbm = row ? await dao.storageRowToDBM(row) : undefined;
820
+ const dbm = row ? dao.storageRowToDBM(row) : undefined;
844
821
  bmsByProp[prop] = dao.dbmToBM(dbm, opt) || null;
845
822
  }
846
823
  else {
@@ -849,10 +826,10 @@ export class CommonDao {
849
826
  // Without filtering - every prop will get ALL rows from that table.
850
827
  const rows = input.ids.map(id => dbmByTableById[table][id]).filter(_isTruthy);
851
828
  // Decompress before converting to BM
852
- const dbms = await dao.storageRowsToDBMs(rows);
829
+ const dbms = dao.storageRowsToDBM(rows);
853
830
  bmsByProp[prop] = dao.dbmsToBM(dbms, opt);
854
831
  }
855
- });
832
+ }
856
833
  return bmsByProp;
857
834
  }
858
835
  /**
@@ -883,7 +860,7 @@ export class CommonDao {
883
860
  return;
884
861
  const { db } = inputs[0].dao.cfg;
885
862
  const dbmsByTable = {};
886
- await pMap(inputs, async input => {
863
+ for (const input of inputs) {
887
864
  const { dao } = input;
888
865
  const { table } = dao.cfg;
889
866
  dbmsByTable[table] ||= [];
@@ -903,7 +880,7 @@ export class CommonDao {
903
880
  dao.assignIdCreatedUpdated(row, opt);
904
881
  const dbm = dao.bmToDBM(row, opt);
905
882
  dao.cfg.hooks.beforeSave?.(dbm);
906
- const storageRow = await dao.dbmToStorageRow(dbm);
883
+ const storageRow = dao.dbmToStorageRow(dbm);
907
884
  dbmsByTable[table].push(storageRow);
908
885
  }
909
886
  else {
@@ -913,10 +890,10 @@ export class CommonDao {
913
890
  if (dao.cfg.hooks.beforeSave) {
914
891
  dbms.forEach(dbm => dao.cfg.hooks.beforeSave(dbm));
915
892
  }
916
- const storageRows = await dao.dbmsToStorageRows(dbms);
893
+ const storageRows = dao.dbmsToStorageRows(dbms);
917
894
  dbmsByTable[table].push(...storageRows);
918
895
  }
919
- });
896
+ }
920
897
  await db.multiSave(dbmsByTable);
921
898
  }
922
899
  async createTransaction(opt) {
@@ -185,12 +185,6 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
185
185
  * Undefined will default to level 1 (not the 3, which is the zstd default)
186
186
  */
187
187
  level?: Integer;
188
- /**
189
- * When enabled, zstd decompression will be performed synchronously.
190
- *
191
- * @experimental
192
- */
193
- syncMode?: boolean;
194
188
  };
195
189
  }
196
190
  /**
@@ -28,8 +28,8 @@ export interface CommonKeyValueDaoCfg<V> {
28
28
  }
29
29
  export type CommonKeyValueDaoSaveOptions = CommonKeyValueDBSaveBatchOptions;
30
30
  export interface CommonKeyValueDaoTransformer<V> {
31
- valueToBuffer: (v: V) => Promise<Buffer>;
32
- bufferToValue: (buf: Buffer) => Promise<V>;
31
+ valueToBuffer: (v: V) => Buffer;
32
+ bufferToValue: (buf: Buffer) => V;
33
33
  }
34
34
  /**
35
35
  * @deprecated use zstd instead, gzip is obsolete
@@ -1,20 +1,19 @@
1
1
  import { AppError } from '@naturalcycles/js-lib/error/error.util.js';
2
- import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
3
2
  import { SKIP } from '@naturalcycles/js-lib/types';
4
- import { decompressZstdOrInflateToString, deflateString, inflateToString, zstdCompress, zstdDecompressToString, } from '@naturalcycles/nodejs-lib/zip';
3
+ import { zip2 } from '@naturalcycles/nodejs-lib/zip';
5
4
  /**
6
5
  * @deprecated use zstd instead, gzip is obsolete
7
6
  */
8
7
  export function commonKeyValueDaoDeflatedJsonTransformer() {
9
8
  return {
10
- valueToBuffer: async v => await deflateString(JSON.stringify(v)),
11
- bufferToValue: async buf => JSON.parse(await inflateToString(buf)),
9
+ valueToBuffer: v => zip2.deflateSync(JSON.stringify(v)),
10
+ bufferToValue: buf => JSON.parse(zip2.inflateToStringSync(buf)),
12
11
  };
13
12
  }
14
13
  export function commonKeyValueDaoZstdJsonTransformer(level) {
15
14
  return {
16
- valueToBuffer: async v => await zstdCompress(JSON.stringify(v), level),
17
- bufferToValue: async buf => JSON.parse(await zstdDecompressToString(buf)),
15
+ valueToBuffer: v => zip2.zstdCompressSync(JSON.stringify(v), level),
16
+ bufferToValue: buf => JSON.parse(zip2.zstdDecompressToStringSync(buf)),
18
17
  };
19
18
  }
20
19
  /**
@@ -23,8 +22,8 @@ export function commonKeyValueDaoZstdJsonTransformer(level) {
23
22
  */
24
23
  export function commonKeyValueDaoCompressedTransformer() {
25
24
  return {
26
- valueToBuffer: async v => await zstdCompress(JSON.stringify(v)),
27
- bufferToValue: async buf => JSON.parse(await decompressZstdOrInflateToString(buf)),
25
+ valueToBuffer: v => zip2.zstdCompressSync(JSON.stringify(v)),
26
+ bufferToValue: buf => JSON.parse(zip2.decompressZstdOrInflateToStringSync(buf)),
28
27
  };
29
28
  }
30
29
  // todo: logging
@@ -81,10 +80,7 @@ export class CommonKeyValueDao {
81
80
  const entries = await this.cfg.db.getByIds(this.cfg.table, ids);
82
81
  if (!this.cfg.transformer)
83
82
  return entries;
84
- return await pMap(entries, async ([id, raw]) => [
85
- id,
86
- await this.cfg.transformer.bufferToValue(raw),
87
- ]);
83
+ return entries.map(([id, raw]) => [id, this.cfg.transformer.bufferToValue(raw)]);
88
84
  }
89
85
  async getByIdsAsBuffer(ids) {
90
86
  return await this.cfg.db.getByIds(this.cfg.table, ids);
@@ -99,7 +95,7 @@ export class CommonKeyValueDao {
99
95
  rawEntries = entries;
100
96
  }
101
97
  else {
102
- rawEntries = await pMap(entries, async ([id, v]) => [id, await transformer.valueToBuffer(v)]);
98
+ rawEntries = entries.map(([id, v]) => [id, transformer.valueToBuffer(v)]);
103
99
  }
104
100
  await this.cfg.db.saveBatch(this.cfg.table, rawEntries, opt);
105
101
  }
@@ -117,30 +113,30 @@ export class CommonKeyValueDao {
117
113
  if (!transformer) {
118
114
  return this.cfg.db.streamValues(this.cfg.table, limit);
119
115
  }
120
- return this.cfg.db.streamValues(this.cfg.table, limit).map(async buf => {
116
+ return this.cfg.db.streamValues(this.cfg.table, limit).mapSync(buf => {
121
117
  try {
122
- return await transformer.bufferToValue(buf);
118
+ return transformer.bufferToValue(buf);
123
119
  }
124
120
  catch (err) {
125
121
  this.cfg.logger.error(err);
126
122
  return SKIP;
127
123
  }
128
- }, { concurrency: 32 });
124
+ });
129
125
  }
130
126
  streamEntries(limit) {
131
127
  const { transformer } = this.cfg;
132
128
  if (!transformer) {
133
129
  return this.cfg.db.streamEntries(this.cfg.table, limit);
134
130
  }
135
- return this.cfg.db.streamEntries(this.cfg.table, limit).map(async ([id, buf]) => {
131
+ return this.cfg.db.streamEntries(this.cfg.table, limit).mapSync(([id, buf]) => {
136
132
  try {
137
- return [id, await transformer.bufferToValue(buf)];
133
+ return [id, transformer.bufferToValue(buf)];
138
134
  }
139
135
  catch (err) {
140
136
  this.cfg.logger.error(err);
141
137
  return SKIP;
142
138
  }
143
- }, { concurrency: 32 });
139
+ });
144
140
  }
145
141
  async getAllKeys(limit) {
146
142
  return await this.streamIds(limit).toArray();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/db-lib",
3
3
  "type": "module",
4
- "version": "10.48.0",
4
+ "version": "10.49.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@naturalcycles/nodejs-lib": "^15"
@@ -224,12 +224,6 @@ export interface CommonDaoCfg<
224
224
  * Undefined will default to level 1 (not the 3, which is the zstd default)
225
225
  */
226
226
  level?: Integer
227
- /**
228
- * When enabled, zstd decompression will be performed synchronously.
229
- *
230
- * @experimental
231
- */
232
- syncMode?: boolean
233
227
  }
234
228
  }
235
229
 
@@ -27,11 +27,7 @@ import type {
27
27
  import { stringId } from '@naturalcycles/nodejs-lib'
28
28
  import type { JsonSchema } from '@naturalcycles/nodejs-lib/ajv'
29
29
  import type { Pipeline } from '@naturalcycles/nodejs-lib/stream'
30
- import {
31
- decompressZstdOrInflateToString,
32
- decompressZstdOrInflateToStringSync,
33
- zstdCompress,
34
- } from '@naturalcycles/nodejs-lib/zip'
30
+ import { zip2 } from '@naturalcycles/nodejs-lib/zip'
35
31
  import { DBLibError } from '../cnst.js'
36
32
  import type {
37
33
  CommonDBSaveOptions,
@@ -159,7 +155,7 @@ export class CommonDao<
159
155
  if (!ids.length) return []
160
156
  const table = opt.table || this.cfg.table
161
157
  const rows = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids, opt)
162
- return await this.storageRowsToDBMs(rows)
158
+ return this.storageRowsToDBM(rows)
163
159
  }
164
160
 
165
161
  async getBy(by: keyof DBM, value: any, limit = 0, opt?: CommonDaoReadOptions): Promise<BM[]> {
@@ -220,7 +216,7 @@ export class CommonDao<
220
216
  q.table = opt.table || q.table
221
217
  const { rows: rawRows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
222
218
  const isPartialQuery = !!q._selectedFieldNames
223
- const rows = isPartialQuery ? rawRows : await this.storageRowsToDBMs(rawRows)
219
+ const rows = isPartialQuery ? rawRows : this.storageRowsToDBM(rawRows)
224
220
  const bms = isPartialQuery ? (rows as any[]) : this.dbmsToBM(rows, opt)
225
221
  return {
226
222
  rows: bms,
@@ -241,7 +237,7 @@ export class CommonDao<
241
237
  q.table = opt.table || q.table
242
238
  const { rows: rawRows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
243
239
  const isPartialQuery = !!q._selectedFieldNames
244
- const rows = isPartialQuery ? rawRows : await this.storageRowsToDBMs(rawRows)
240
+ const rows = isPartialQuery ? rawRows : this.storageRowsToDBM(rawRows)
245
241
  const dbms = isPartialQuery ? rows : this.anyToDBMs(rows, opt)
246
242
  return { rows: dbms, ...queryResult }
247
243
  }
@@ -258,10 +254,7 @@ export class CommonDao<
258
254
  let pipeline = this.cfg.db.streamQuery<DBM>(q, opt)
259
255
 
260
256
  if (this.cfg.compress?.keys.length) {
261
- pipeline = pipeline.map(async row => await this.storageRowToDBM(row), {
262
- // lowered, to reduce the total buffer size a bit for uncompressed objects
263
- highWaterMark: 16,
264
- })
257
+ pipeline = pipeline.mapSync(row => this.storageRowToDBM(row))
265
258
  }
266
259
 
267
260
  const isPartialQuery = !!q._selectedFieldNames
@@ -279,10 +272,7 @@ export class CommonDao<
279
272
  let pipeline = this.cfg.db.streamQuery<DBM>(q, opt)
280
273
 
281
274
  if (this.cfg.compress?.keys.length) {
282
- pipeline = pipeline.map(async row => await this.storageRowToDBM(row), {
283
- // lowered, to reduce the total buffer size a bit for uncompressed objects
284
- highWaterMark: 16,
285
- })
275
+ pipeline = pipeline.mapSync(row => this.storageRowToDBM(row))
286
276
  }
287
277
 
288
278
  const isPartialQuery = !!q._selectedFieldNames
@@ -481,7 +471,7 @@ export class CommonDao<
481
471
  const table = opt.table || this.cfg.table
482
472
  const saveOptions = this.prepareSaveOptions(opt)
483
473
 
484
- const row = await this.dbmToStorageRow(dbm)
474
+ const row = this.dbmToStorageRow(dbm)
485
475
  await (opt.tx || this.cfg.db).saveBatch(table, [row], saveOptions)
486
476
 
487
477
  if (saveOptions.assignGeneratedIds) {
@@ -499,7 +489,7 @@ export class CommonDao<
499
489
  const table = opt.table || this.cfg.table
500
490
  const saveOptions = this.prepareSaveOptions(opt)
501
491
 
502
- const row = await this.dbmToStorageRow(validDbm)
492
+ const row = this.dbmToStorageRow(validDbm)
503
493
  await (opt.tx || this.cfg.db).saveBatch(table, [row], saveOptions)
504
494
 
505
495
  if (saveOptions.assignGeneratedIds) {
@@ -520,7 +510,7 @@ export class CommonDao<
520
510
  const table = opt.table || this.cfg.table
521
511
  const saveOptions = this.prepareSaveOptions(opt)
522
512
 
523
- const rows = await this.dbmsToStorageRows(dbms)
513
+ const rows = this.dbmsToStorageRows(dbms)
524
514
  await (opt.tx || this.cfg.db).saveBatch(table, rows, saveOptions)
525
515
 
526
516
  if (saveOptions.assignGeneratedIds) {
@@ -544,7 +534,7 @@ export class CommonDao<
544
534
  const table = opt.table || this.cfg.table
545
535
  const saveOptions = this.prepareSaveOptions(opt)
546
536
 
547
- const rows = await this.dbmsToStorageRows(validDbms)
537
+ const rows = this.dbmsToStorageRows(validDbms)
548
538
  await (opt.tx || this.cfg.db).saveBatch(table, rows, saveOptions)
549
539
 
550
540
  if (saveOptions.assignGeneratedIds) {
@@ -612,7 +602,7 @@ export class CommonDao<
612
602
  this.assignIdCreatedUpdated(bm, opt)
613
603
  const dbm = this.bmToDBM(bm, opt)
614
604
  beforeSave?.(dbm)
615
- return await this.dbmToStorageRow(dbm)
605
+ return this.dbmToStorageRow(dbm)
616
606
  },
617
607
  { errorMode },
618
608
  )
@@ -806,19 +796,23 @@ export class CommonDao<
806
796
  * const storageRow = await dao.dbmToStorageRow(dbm)
807
797
  * await db.saveBatch(table, [storageRow])
808
798
  */
809
- async dbmToStorageRow(dbm: DBM): Promise<ObjectWithId> {
799
+ dbmToStorageRow(dbm: DBM): ObjectWithId {
810
800
  if (!this.cfg.compress?.keys.length) return dbm
811
801
  const row = { ...dbm }
812
- await this.compress(row)
802
+ this.compress(row)
813
803
  return row
814
804
  }
815
805
 
816
806
  /**
817
807
  * Converts multiple DBMs to storage rows.
818
808
  */
819
- async dbmsToStorageRows(dbms: DBM[]): Promise<ObjectWithId[]> {
809
+ dbmsToStorageRows(dbms: DBM[]): ObjectWithId[] {
820
810
  if (!this.cfg.compress?.keys.length) return dbms
821
- return await pMap(dbms, async dbm => await this.dbmToStorageRow(dbm))
811
+ return dbms.map(dbm => {
812
+ const row = { ...dbm }
813
+ this.compress(row)
814
+ return row
815
+ })
822
816
  }
823
817
 
824
818
  /**
@@ -830,42 +824,35 @@ export class CommonDao<
830
824
  * const rows = await db.getByIds(table, ids)
831
825
  * const dbms = await Promise.all(rows.map(row => dao.storageRowToDBM(row)))
832
826
  */
833
- async storageRowToDBM(row: ObjectWithId): Promise<DBM> {
827
+ storageRowToDBM(row: ObjectWithId): DBM {
834
828
  if (!this.cfg.compress?.keys.length) return row as DBM
835
829
  const dbm = { ...(row as DBM) }
836
- if (this.cfg.compress.syncMode) {
837
- this.decompressSync(dbm)
838
- } else {
839
- await this.decompress(dbm)
840
- }
830
+ this.decompress(dbm)
841
831
  return dbm
842
832
  }
843
833
 
844
834
  /**
845
835
  * Converts multiple storage rows to DBMs.
846
836
  */
847
- async storageRowsToDBMs(rows: ObjectWithId[]): Promise<DBM[]> {
837
+ storageRowsToDBM(rows: ObjectWithId[]): DBM[] {
848
838
  if (!this.cfg.compress?.keys.length) return rows as DBM[]
849
- if (this.cfg.compress.syncMode) {
850
- return rows.map(row => {
851
- const dbm = { ...(row as DBM) }
852
- this.decompressSync(dbm)
853
- return dbm
854
- })
855
- }
856
- return await pMap(rows, async row => await this.storageRowToDBM(row))
839
+ return rows.map(row => {
840
+ const dbm = { ...(row as DBM) }
841
+ this.decompress(dbm)
842
+ return dbm
843
+ })
857
844
  }
858
845
 
859
846
  /**
860
847
  * Mutates `dbm`.
861
848
  */
862
- private async compress(dbm: DBM): Promise<void> {
849
+ private compress(dbm: DBM): void {
863
850
  if (!this.cfg.compress?.keys.length) return // No compression requested
864
851
 
865
852
  const { keys, level = 1 } = this.cfg.compress
866
853
  const properties = _pick(dbm, keys)
867
854
  const bufferString = JSON.stringify(properties)
868
- const __compressed = await zstdCompress(bufferString, level)
855
+ const __compressed = zip2.zstdCompressSync(bufferString, level)
869
856
  _omitWithUndefined(dbm as any, _objectKeys(properties), { mutate: true })
870
857
  Object.assign(dbm, { __compressed })
871
858
  }
@@ -873,25 +860,11 @@ export class CommonDao<
873
860
  /**
874
861
  * Mutates `dbm`.
875
862
  */
876
- private async decompress(dbm: DBM): Promise<void> {
863
+ private decompress(dbm: DBM): void {
877
864
  _typeCast<Compressed<DBM>>(dbm)
878
865
  if (!Buffer.isBuffer(dbm.__compressed)) return // No compressed data
879
866
 
880
- // todo: stop supporting Inflate when we are sure that we have migrated everything to zstd
881
- const bufferString = await decompressZstdOrInflateToString(dbm.__compressed)
882
- const properties = JSON.parse(bufferString)
883
- dbm.__compressed = undefined
884
- Object.assign(dbm, properties)
885
- }
886
-
887
- /**
888
- * Mutates `dbm`.
889
- */
890
- private decompressSync(dbm: DBM): void {
891
- _typeCast<Compressed<DBM>>(dbm)
892
- if (!Buffer.isBuffer(dbm.__compressed)) return // No compressed data
893
-
894
- const bufferString = decompressZstdOrInflateToStringSync(dbm.__compressed)
867
+ const bufferString = zip2.zstdDecompressToStringSync(dbm.__compressed)
895
868
  const properties = JSON.parse(bufferString)
896
869
  dbm.__compressed = undefined
897
870
  Object.assign(dbm, properties)
@@ -1029,7 +1002,7 @@ export class CommonDao<
1029
1002
 
1030
1003
  const dbmByTableById = CommonDao.multiGetMapByTableById(dbmsByTable)
1031
1004
 
1032
- return (await CommonDao.prepareMultiGetOutput(inputMap, dbmByTableById, opt)) as any
1005
+ return CommonDao.prepareMultiGetOutput(inputMap, dbmByTableById, opt) as any
1033
1006
  }
1034
1007
 
1035
1008
  private static prepareMultiGetIds(
@@ -1075,22 +1048,22 @@ export class CommonDao<
1075
1048
  return dbmByTableById
1076
1049
  }
1077
1050
 
1078
- private static async prepareMultiGetOutput(
1051
+ private static prepareMultiGetOutput(
1079
1052
  inputMap: StringMap<DaoWithIds<AnyDao> | DaoWithId<AnyDao>>,
1080
1053
  dbmByTableById: StringMap<StringMap<ObjectWithId>>,
1081
1054
  opt: CommonDaoReadOptions = {},
1082
- ): Promise<StringMap<unknown>> {
1055
+ ): StringMap<unknown> {
1083
1056
  const bmsByProp: StringMap<unknown> = {}
1084
1057
 
1085
1058
  // Loop over input props again, to produce the output of the same shape as requested
1086
- await pMap(_stringMapEntries(inputMap), async ([prop, input]) => {
1059
+ for (const [prop, input] of _stringMapEntries(inputMap)) {
1087
1060
  const { dao } = input
1088
1061
  const { table } = dao.cfg
1089
1062
  if ('id' in input) {
1090
1063
  // Singular
1091
1064
  const row = dbmByTableById[table]![input.id]
1092
1065
  // Decompress before converting to BM
1093
- const dbm = row ? await dao.storageRowToDBM(row) : undefined
1066
+ const dbm = row ? dao.storageRowToDBM(row) : undefined
1094
1067
  bmsByProp[prop] = dao.dbmToBM(dbm, opt) || null
1095
1068
  } else {
1096
1069
  // Plural
@@ -1098,10 +1071,10 @@ export class CommonDao<
1098
1071
  // Without filtering - every prop will get ALL rows from that table.
1099
1072
  const rows = input.ids.map(id => dbmByTableById[table]![id]).filter(_isTruthy)
1100
1073
  // Decompress before converting to BM
1101
- const dbms = await dao.storageRowsToDBMs(rows)
1074
+ const dbms = dao.storageRowsToDBM(rows)
1102
1075
  bmsByProp[prop] = dao.dbmsToBM(dbms, opt)
1103
1076
  }
1104
- })
1077
+ }
1105
1078
 
1106
1079
  return bmsByProp as any
1107
1080
  }
@@ -1140,7 +1113,7 @@ export class CommonDao<
1140
1113
  if (!inputs.length) return
1141
1114
  const { db } = inputs[0]!.dao.cfg
1142
1115
  const dbmsByTable: StringMap<any[]> = {}
1143
- await pMap(inputs, async input => {
1116
+ for (const input of inputs) {
1144
1117
  const { dao } = input
1145
1118
  const { table } = dao.cfg
1146
1119
  dbmsByTable[table] ||= []
@@ -1163,7 +1136,7 @@ export class CommonDao<
1163
1136
  dao.assignIdCreatedUpdated(row, opt)
1164
1137
  const dbm = dao.bmToDBM(row, opt)
1165
1138
  dao.cfg.hooks!.beforeSave?.(dbm)
1166
- const storageRow = await dao.dbmToStorageRow(dbm)
1139
+ const storageRow = dao.dbmToStorageRow(dbm)
1167
1140
  dbmsByTable[table].push(storageRow)
1168
1141
  } else {
1169
1142
  // Plural
@@ -1172,10 +1145,10 @@ export class CommonDao<
1172
1145
  if (dao.cfg.hooks!.beforeSave) {
1173
1146
  dbms.forEach(dbm => dao.cfg.hooks!.beforeSave!(dbm))
1174
1147
  }
1175
- const storageRows = await dao.dbmsToStorageRows(dbms)
1148
+ const storageRows = dao.dbmsToStorageRows(dbms)
1176
1149
  dbmsByTable[table].push(...storageRows)
1177
1150
  }
1178
- })
1151
+ }
1179
1152
 
1180
1153
  await db.multiSave(dbmsByTable)
1181
1154
  }
@@ -1,16 +1,9 @@
1
1
  import { AppError } from '@naturalcycles/js-lib/error/error.util.js'
2
2
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
3
- import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
4
3
  import { SKIP } from '@naturalcycles/js-lib/types'
5
4
  import type { Integer, KeyValueTuple } from '@naturalcycles/js-lib/types'
6
5
  import type { Pipeline } from '@naturalcycles/nodejs-lib/stream'
7
- import {
8
- decompressZstdOrInflateToString,
9
- deflateString,
10
- inflateToString,
11
- zstdCompress,
12
- zstdDecompressToString,
13
- } from '@naturalcycles/nodejs-lib/zip'
6
+ import { zip2 } from '@naturalcycles/nodejs-lib/zip'
14
7
  import type { CommonDaoLogLevel } from '../commondao/common.dao.model.js'
15
8
  import type { CommonDBCreateOptions } from '../db.model.js'
16
9
  import type {
@@ -52,8 +45,8 @@ export interface CommonKeyValueDaoCfg<V> {
52
45
  export type CommonKeyValueDaoSaveOptions = CommonKeyValueDBSaveBatchOptions
53
46
 
54
47
  export interface CommonKeyValueDaoTransformer<V> {
55
- valueToBuffer: (v: V) => Promise<Buffer>
56
- bufferToValue: (buf: Buffer) => Promise<V>
48
+ valueToBuffer: (v: V) => Buffer
49
+ bufferToValue: (buf: Buffer) => V
57
50
  }
58
51
 
59
52
  /**
@@ -63,8 +56,8 @@ export function commonKeyValueDaoDeflatedJsonTransformer<
63
56
  T = any,
64
57
  >(): CommonKeyValueDaoTransformer<T> {
65
58
  return {
66
- valueToBuffer: async v => await deflateString(JSON.stringify(v)),
67
- bufferToValue: async buf => JSON.parse(await inflateToString(buf)),
59
+ valueToBuffer: v => zip2.deflateSync(JSON.stringify(v)),
60
+ bufferToValue: buf => JSON.parse(zip2.inflateToStringSync(buf)),
68
61
  }
69
62
  }
70
63
 
@@ -72,8 +65,8 @@ export function commonKeyValueDaoZstdJsonTransformer<T = any>(
72
65
  level: Integer | undefined, // defaults to 3
73
66
  ): CommonKeyValueDaoTransformer<T> {
74
67
  return {
75
- valueToBuffer: async v => await zstdCompress(JSON.stringify(v), level),
76
- bufferToValue: async buf => JSON.parse(await zstdDecompressToString(buf)),
68
+ valueToBuffer: v => zip2.zstdCompressSync(JSON.stringify(v), level),
69
+ bufferToValue: buf => JSON.parse(zip2.zstdDecompressToStringSync(buf)),
77
70
  }
78
71
  }
79
72
 
@@ -83,8 +76,8 @@ export function commonKeyValueDaoZstdJsonTransformer<T = any>(
83
76
  */
84
77
  export function commonKeyValueDaoCompressedTransformer<T = any>(): CommonKeyValueDaoTransformer<T> {
85
78
  return {
86
- valueToBuffer: async v => await zstdCompress(JSON.stringify(v)),
87
- bufferToValue: async buf => JSON.parse(await decompressZstdOrInflateToString(buf)),
79
+ valueToBuffer: v => zip2.zstdCompressSync(JSON.stringify(v)),
80
+ bufferToValue: buf => JSON.parse(zip2.decompressZstdOrInflateToStringSync(buf)),
88
81
  }
89
82
  }
90
83
 
@@ -155,10 +148,7 @@ export class CommonKeyValueDao<K extends string = string, V = Buffer> {
155
148
  const entries = await this.cfg.db.getByIds(this.cfg.table, ids)
156
149
  if (!this.cfg.transformer) return entries as any
157
150
 
158
- return await pMap(entries, async ([id, raw]) => [
159
- id,
160
- await this.cfg.transformer!.bufferToValue(raw),
161
- ])
151
+ return entries.map(([id, raw]) => [id, this.cfg.transformer!.bufferToValue(raw)])
162
152
  }
163
153
 
164
154
  async getByIdsAsBuffer(ids: K[]): Promise<KeyValueDBTuple[]> {
@@ -179,7 +169,7 @@ export class CommonKeyValueDao<K extends string = string, V = Buffer> {
179
169
  if (!transformer) {
180
170
  rawEntries = entries as any
181
171
  } else {
182
- rawEntries = await pMap(entries, async ([id, v]) => [id, await transformer.valueToBuffer(v)])
172
+ rawEntries = entries.map(([id, v]) => [id, transformer.valueToBuffer(v)])
183
173
  }
184
174
 
185
175
  await this.cfg.db.saveBatch(this.cfg.table, rawEntries, opt)
@@ -204,17 +194,14 @@ export class CommonKeyValueDao<K extends string = string, V = Buffer> {
204
194
  return this.cfg.db.streamValues(this.cfg.table, limit) as Pipeline<V>
205
195
  }
206
196
 
207
- return this.cfg.db.streamValues(this.cfg.table, limit).map(
208
- async buf => {
209
- try {
210
- return await transformer.bufferToValue(buf)
211
- } catch (err) {
212
- this.cfg.logger.error(err)
213
- return SKIP
214
- }
215
- },
216
- { concurrency: 32 },
217
- )
197
+ return this.cfg.db.streamValues(this.cfg.table, limit).mapSync(buf => {
198
+ try {
199
+ return transformer.bufferToValue(buf)
200
+ } catch (err) {
201
+ this.cfg.logger.error(err)
202
+ return SKIP
203
+ }
204
+ })
218
205
  }
219
206
 
220
207
  streamEntries(limit?: number): Pipeline<KeyValueTuple<K, V>> {
@@ -224,17 +211,14 @@ export class CommonKeyValueDao<K extends string = string, V = Buffer> {
224
211
  return this.cfg.db.streamEntries(this.cfg.table, limit) as Pipeline<KeyValueTuple<K, V>>
225
212
  }
226
213
 
227
- return this.cfg.db.streamEntries(this.cfg.table, limit).map(
228
- async ([id, buf]) => {
229
- try {
230
- return [id as K, await transformer.bufferToValue(buf)]
231
- } catch (err) {
232
- this.cfg.logger.error(err)
233
- return SKIP
234
- }
235
- },
236
- { concurrency: 32 },
237
- )
214
+ return this.cfg.db.streamEntries(this.cfg.table, limit).mapSync(([id, buf]) => {
215
+ try {
216
+ return [id as K, transformer.bufferToValue(buf)]
217
+ } catch (err) {
218
+ this.cfg.logger.error(err)
219
+ return SKIP
220
+ }
221
+ })
238
222
  }
239
223
 
240
224
  async getAllKeys(limit?: number): Promise<K[]> {