@based/db 0.0.68 → 0.0.70

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.
Files changed (74) hide show
  1. package/README.md +6 -1
  2. package/dist/lib/darwin_aarch64/include/selva/fields.h +0 -9
  3. package/dist/lib/darwin_aarch64/include/selva_error.h +4 -1
  4. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  5. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  6. package/dist/lib/darwin_aarch64/libnode-v24.node +0 -0
  7. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  8. package/dist/lib/linux_aarch64/include/selva/fields.h +0 -9
  9. package/dist/lib/linux_aarch64/include/selva_error.h +4 -1
  10. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  11. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  12. package/dist/lib/linux_aarch64/libnode-v24.node +0 -0
  13. package/dist/lib/linux_aarch64/libselva.so +0 -0
  14. package/dist/lib/linux_x86_64/include/selva/fields.h +0 -9
  15. package/dist/lib/linux_x86_64/include/selva_error.h +4 -1
  16. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  17. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  18. package/dist/lib/linux_x86_64/libnode-v24.node +0 -0
  19. package/dist/lib/linux_x86_64/libselva.so +0 -0
  20. package/dist/src/client/modify/alias.js +4 -0
  21. package/dist/src/client/modify/binary.d.ts +1 -1
  22. package/dist/src/client/modify/binary.js +22 -7
  23. package/dist/src/client/modify/create.js +91 -39
  24. package/dist/src/client/modify/fixed.d.ts +3 -3
  25. package/dist/src/client/modify/fixed.js +80 -20
  26. package/dist/src/client/modify/json.js +7 -0
  27. package/dist/src/client/modify/modify.js +3 -3
  28. package/dist/src/client/modify/references/edge.js +3 -3
  29. package/dist/src/client/modify/string.d.ts +1 -1
  30. package/dist/src/client/modify/string.js +17 -7
  31. package/dist/src/client/modify/text.d.ts +1 -1
  32. package/dist/src/client/modify/text.js +27 -15
  33. package/dist/src/client/modify/types.d.ts +2 -1
  34. package/dist/src/client/modify/types.js +6 -0
  35. package/dist/src/client/modify/update.js +5 -1
  36. package/dist/src/client/query/display.js +1 -1
  37. package/dist/src/client/query/filter/createFixedFilterBuffer.js +3 -0
  38. package/dist/src/client/query/filter/createReferenceFilter.js +3 -0
  39. package/dist/src/client/query/filter/createVariableFilterBuffer.js +21 -19
  40. package/dist/src/client/query/read/read.js +9 -10
  41. package/dist/src/native.d.ts +1 -0
  42. package/dist/src/native.js +3 -0
  43. package/dist/src/server/IoWorker.d.ts +16 -0
  44. package/dist/src/server/IoWorker.js +32 -3
  45. package/dist/src/server/QueryWorker.js +2 -2
  46. package/dist/src/server/blocks.d.ts +3 -1
  47. package/dist/src/server/blocks.js +31 -7
  48. package/dist/src/server/index.d.ts +1 -1
  49. package/dist/src/server/index.js +8 -11
  50. package/dist/src/server/migrate/index.js +25 -11
  51. package/dist/src/server/migrate/worker.js +70 -62
  52. package/dist/src/server/save.d.ts +7 -1
  53. package/dist/src/server/save.js +107 -50
  54. package/dist/src/server/schema.d.ts +1 -1
  55. package/dist/src/server/schema.js +6 -2
  56. package/dist/src/server/start.js +11 -5
  57. package/dist/src/server/tree.d.ts +11 -0
  58. package/dist/src/server/tree.js +0 -1
  59. package/dist/src/server/workers/DbWorker.d.ts +3 -2
  60. package/dist/src/server/workers/DbWorker.js +2 -1
  61. package/dist/src/server/workers/io_worker.js +22 -17
  62. package/dist/src/server/workers/io_worker_types.d.ts +9 -1
  63. package/dist/src/server/workers/worker.js +11 -3
  64. package/dist/src/types.d.ts +1 -0
  65. package/dist/src/types.js +1 -0
  66. package/dist/src/utils.js +1 -1
  67. package/package.json +5 -3
  68. package/dist/lib/darwin_aarch64/libjemalloc_selva.so.2 +0 -0
  69. package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
  70. package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
  71. package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
  72. package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
  73. package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
  74. package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
@@ -69,6 +69,9 @@ const readAggregate = (q, result, offset, len) => {
69
69
  return results;
70
70
  };
71
71
  const addField = (p, value, item, defaultOnly = false, lang = 0) => {
72
+ if (p.transform) {
73
+ value = p.transform('read', value);
74
+ }
72
75
  let i = p.__isEdge === true ? 1 : 0;
73
76
  // TODO OPTMIZE
74
77
  const path = lang ? [...p.path, inverseLangMap.get(lang)] : p.path;
@@ -215,21 +218,17 @@ const handleUndefinedProps = (id, q, item) => {
215
218
  }
216
219
  }
217
220
  }
218
- // else if (prop.typeIndex === BINARY) {
219
- // addField(prop, prop.default, item)
220
- // }
221
221
  else if (prop.typeIndex === TEXT ||
222
222
  prop.typeIndex === STRING ||
223
223
  prop.typeIndex === ALIAS) {
224
224
  addField(prop, '', item);
225
225
  }
226
- // else if (prop.typeIndex === JSON) {
227
- // // addField(prop, null, item)
228
- // } else {
229
- // // if (prop.default !== undefined) {
230
- // // addField(prop, '', item)
231
- // // }
232
- // }
226
+ else if (prop.typeIndex === JSON) {
227
+ addField(prop, null, item);
228
+ }
229
+ else if (prop.typeIndex === BINARY) {
230
+ addField(prop, new Uint8Array(), item);
231
+ }
233
232
  }
234
233
  }
235
234
  };
@@ -24,6 +24,7 @@ declare const native: {
24
24
  equals: (a: Uint8Array, b: Uint8Array) => boolean;
25
25
  membarSyncRead: () => void;
26
26
  membarSyncWrite: () => void;
27
+ selvaStrerror: (err: number) => any;
27
28
  colvecTest: (dbCtx: any, typeId: number, field: number, nodeId: number, len: number) => any;
28
29
  };
29
30
  export default native;
@@ -100,6 +100,9 @@ const native = {
100
100
  membarSyncWrite: () => {
101
101
  db.membarSyncWrite();
102
102
  },
103
+ selvaStrerror: (err) => {
104
+ return db.selvaStrerror(err);
105
+ },
103
106
  colvecTest: (dbCtx, typeId, field, nodeId, len) => {
104
107
  return db.colvecTest(dbCtx, typeId, field, nodeId, len);
105
108
  }
@@ -3,6 +3,22 @@ import { DbServer } from './index.js';
3
3
  export declare class IoWorker extends DbWorker {
4
4
  constructor(address: BigInt, db: DbServer);
5
5
  handleMsg(_buf: any): void;
6
+ private cb;
7
+ /**
8
+ * Save given blocks and return errors and hashes in an array.
9
+ * @returns [[4 bytes err], [16 bytes hash]][] with the same length as blocks.
10
+ */
11
+ saveBlocks(blocks: {
12
+ filepath: string;
13
+ typeId: number;
14
+ start: number;
15
+ }[]): Promise<Uint8Array>;
6
16
  loadBlock(filepath: string): Promise<void>;
17
+ /**
18
+ * Save a block and discard it from memory "atomically".
19
+ * Note that this worker doesn't give any protection from other threads
20
+ * accessing the block concurrently, and it must be coordinated in the
21
+ * main thread.
22
+ */
7
23
  unloadBlock(filepath: string, typeId: number, start: number): Promise<Uint8Array>;
8
24
  }
@@ -1,5 +1,6 @@
1
1
  import { DbWorker } from './workers/DbWorker.js';
2
2
  import { DECODER, readInt32 } from '@saulx/utils';
3
+ import native from '../native.js';
3
4
  export class IoWorker extends DbWorker {
4
5
  constructor(address, db) {
5
6
  const onExit = (_code) => {
@@ -9,27 +10,55 @@ export class IoWorker extends DbWorker {
9
10
  }
10
11
  handleMsg(_buf) {
11
12
  }
13
+ cb = (resolve) => {
14
+ this.db.activeReaders++;
15
+ this.resolvers.push((r) => {
16
+ this.db.activeReaders--;
17
+ resolve(r);
18
+ //this.db.onQueryEnd()
19
+ });
20
+ };
21
+ /**
22
+ * Save given blocks and return errors and hashes in an array.
23
+ * @returns [[4 bytes err], [16 bytes hash]][] with the same length as blocks.
24
+ */
25
+ async saveBlocks(blocks) {
26
+ const job = {
27
+ type: 'save',
28
+ blocks,
29
+ };
30
+ this.channel.postMessage(job);
31
+ const resBufP = new Promise(this.cb);
32
+ resBufP.then(() => this.db.onQueryEnd());
33
+ return resBufP;
34
+ }
12
35
  async loadBlock(filepath) {
13
36
  const job = {
14
37
  type: 'load',
15
- filepath
38
+ filepath,
16
39
  };
17
40
  const resBuf = await this.call(job);
18
41
  if (resBuf.length) {
19
42
  throw new Error(DECODER.decode(resBuf));
20
43
  }
21
44
  }
45
+ /**
46
+ * Save a block and discard it from memory "atomically".
47
+ * Note that this worker doesn't give any protection from other threads
48
+ * accessing the block concurrently, and it must be coordinated in the
49
+ * main thread.
50
+ */
22
51
  async unloadBlock(filepath, typeId, start) {
23
52
  const job = {
24
53
  type: 'unload',
25
54
  filepath,
26
55
  typeId,
27
- start
56
+ start,
28
57
  };
29
58
  const resBuf = await this.call(job);
30
59
  const err = readInt32(resBuf, 0);
31
60
  if (err) {
32
- throw new Error(`selva error: ${err}`);
61
+ throw new Error(native.selvaStrerror(err));
33
62
  }
34
63
  // Note that this shares the original buffer which may not be 100% optimal,
35
64
  // as the first 4 bytes are no longer needed.
@@ -8,11 +8,11 @@ export class QueryWorker extends DbWorker {
8
8
  super(address, db, onExit, 'query_worker.js');
9
9
  }
10
10
  handleMsg(_buf) {
11
- this.db.processingQueries--;
11
+ this.db.activeReaders--;
12
12
  this.db.onQueryEnd();
13
13
  }
14
14
  callback = (resolve) => {
15
- this.db.processingQueries++;
15
+ this.db.activeReaders++;
16
16
  this.resolvers.push(resolve);
17
17
  };
18
18
  getQueryBuf(buf) {
@@ -1,11 +1,13 @@
1
1
  import { SchemaTypeDef } from '@based/schema/def';
2
2
  import { DbServer } from './index.js';
3
+ import { IoJobSave } from './workers/io_worker_types.js';
3
4
  /**
4
5
  * Save a block.
5
6
  */
6
7
  export declare function saveBlock(db: DbServer, typeId: number, start: number, end: number): void;
8
+ export declare function saveBlocks(db: DbServer, blocks: IoJobSave['blocks']): Promise<void>;
7
9
  /**
8
- * Load a block (typically of a partial type) back to memory.
10
+ * Load an existing block (typically of a partial type) back to memory.
9
11
  */
10
12
  export declare function loadBlock(db: DbServer, def: SchemaTypeDef, start: number): Promise<void>;
11
13
  /**
@@ -1,7 +1,8 @@
1
1
  import native from '../native.js';
2
2
  import { join } from 'node:path';
3
- import { equals } from '@saulx/utils';
3
+ import { equals, readInt32 } from '@saulx/utils';
4
4
  import { VerifTree, destructureTreeKey, makeTreeKey, } from './tree.js';
5
+ const SELVA_ENOENT = -8;
5
6
  /**
6
7
  * Save a block.
7
8
  */
@@ -11,20 +12,43 @@ export function saveBlock(db, typeId, start, end) {
11
12
  const file = VerifTree.blockSdbFile(typeId, start, end);
12
13
  const path = join(db.fileSystemPath, file);
13
14
  const err = native.saveBlock(path, typeId, start, db.dbCtxExternal, hash);
14
- if (err == -8) {
15
- // TODO ENOENT
15
+ if (err == SELVA_ENOENT) {
16
+ // Generally we don't nor can't remove blocks from verifTree before we
17
+ // attempt to access them.
16
18
  db.verifTree.remove(mtKey);
17
19
  }
18
20
  else if (err) {
19
- // TODO print the error string
20
- console.error(`Save ${typeId}:${start}-${end} failed: ${err}`);
21
+ db.emit('error', `Save ${typeId}:${start}-${end} failed: ${native.selvaStrerror(err)}`);
21
22
  }
22
23
  else {
23
24
  db.verifTree.update(mtKey, hash);
24
25
  }
25
26
  }
27
+ export async function saveBlocks(db, blocks) {
28
+ const res = await db.ioWorker.saveBlocks(blocks);
29
+ if (res.byteOffset !== 0)
30
+ throw new Error('Unexpected offset');
31
+ // if (res.byteLength / 20 !== blocks.length) throw new Error('Invalid res size')
32
+ for (let i = 0; i < blocks.length; i++) {
33
+ const block = blocks[i];
34
+ const key = makeTreeKey(block.typeId, block.start);
35
+ const err = readInt32(res, i * 20);
36
+ const hash = new Uint8Array(res.buffer, i * 20 + 4, 16);
37
+ if (err === SELVA_ENOENT) {
38
+ // Generally we don't nor can't remove blocks from verifTree before we
39
+ // attempt to access them.
40
+ db.verifTree.remove(key);
41
+ }
42
+ else if (err) {
43
+ db.emit('error', `Save ${block.typeId}:${block.start} failed: ${native.selvaStrerror(err)}`);
44
+ }
45
+ else {
46
+ db.verifTree.update(key, hash);
47
+ }
48
+ }
49
+ }
26
50
  /**
27
- * Load a block (typically of a partial type) back to memory.
51
+ * Load an existing block (typically of a partial type) back to memory.
28
52
  */
29
53
  export async function loadBlock(db, def, start) {
30
54
  const key = makeTreeKey(def.id, start);
@@ -72,7 +96,7 @@ export async function unloadBlock(db, def, start) {
72
96
  }
73
97
  catch (e) {
74
98
  // TODO Proper logging
75
- // TODO err == -8 == SELVA_ENOENT => db.verifTree.remove(key) ??
99
+ // TODO SELVA_ENOENT => db.verifTree.remove(key) ??
76
100
  console.error(`Save ${typeId}:${start}-${end} failed`);
77
101
  console.error(e);
78
102
  }
@@ -26,7 +26,7 @@ export declare class DbServer extends DbShared {
26
26
  ioWorker: IoWorker;
27
27
  workers: QueryWorker[];
28
28
  availableWorkerIndex: number;
29
- processingQueries: number;
29
+ activeReaders: number;
30
30
  modifyQueue: Uint8Array[];
31
31
  queryQueue: Map<Function, Uint8Array>;
32
32
  stopped: boolean;
@@ -31,12 +31,12 @@ export class DbServer extends DbShared {
31
31
  migrating = null;
32
32
  saveInProgress = false;
33
33
  fileSystemPath;
34
- verifTree;
34
+ verifTree; // should be updated only when saving/loading
35
35
  dirtyRanges = new Set();
36
36
  ioWorker;
37
37
  workers = [];
38
38
  availableWorkerIndex = -1;
39
- processingQueries = 0; // semaphore for locking writes
39
+ activeReaders = 0; // processing queries or other DB reads
40
40
  modifyQueue = [];
41
41
  queryQueue = new Map();
42
42
  stopped; // = true does not work
@@ -58,7 +58,7 @@ export class DbServer extends DbShared {
58
58
  return start(this, opts);
59
59
  }
60
60
  save(opts) {
61
- return save(this, false, opts?.forceFullDump ?? false);
61
+ return save(this, opts);
62
62
  }
63
63
  async loadBlock(typeName, nodeId) {
64
64
  const def = this.schemaTypesParsed[typeName];
@@ -68,10 +68,6 @@ export class DbServer extends DbShared {
68
68
  const typeId = def.id;
69
69
  const key = makeTreeKeyFromNodeId(typeId, def.blockCapacity, nodeId);
70
70
  const [, start] = destructureTreeKey(key);
71
- const block = this.verifTree.getBlock(key);
72
- if (!block) {
73
- throw new Error('Block not found');
74
- }
75
71
  await loadBlock(this, def, start);
76
72
  }
77
73
  async unloadBlock(typeName, nodeId) {
@@ -103,7 +99,7 @@ export class DbServer extends DbShared {
103
99
  for (const lang in this.sortIndexes[type][field][start]) {
104
100
  const sortIndex = this.sortIndexes[type][field][start][lang];
105
101
  sortIndex.cnt /= 2;
106
- if (sortIndex.cnt < 1 && !this.processingQueries) {
102
+ if (sortIndex.cnt < 1 && !this.activeReaders) {
107
103
  native.destroySortIndex(sortIndex.buf, this.dbCtxExternal);
108
104
  delete this.sortIndexes[type][field][start][lang];
109
105
  }
@@ -299,7 +295,7 @@ export class DbServer extends DbShared {
299
295
  def.lastId = lastId + offset;
300
296
  offsets[typeId] = offset;
301
297
  }
302
- if (this.processingQueries) {
298
+ if (this.activeReaders) {
303
299
  this.modifyQueue.push(new Uint8Array(bufWithHash));
304
300
  }
305
301
  else {
@@ -387,7 +383,7 @@ export class DbServer extends DbShared {
387
383
  const start = readUint16(sort, 3);
388
384
  let sortIndex = this.getSortIndex(typeId, field, start, 0);
389
385
  if (!sortIndex) {
390
- if (this.processingQueries) {
386
+ if (this.activeReaders) {
391
387
  return new Promise((resolve) => {
392
388
  this.addToQueryQueue(resolve, buf);
393
389
  });
@@ -411,7 +407,7 @@ export class DbServer extends DbShared {
411
407
  }
412
408
  }
413
409
  onQueryEnd() {
414
- if (this.processingQueries === 0) {
410
+ if (this.activeReaders === 0) {
415
411
  if (this.modifyQueue.length) {
416
412
  const modifyQueue = this.modifyQueue;
417
413
  this.modifyQueue = [];
@@ -454,6 +450,7 @@ export class DbServer extends DbShared {
454
450
  await this.save();
455
451
  }
456
452
  await this.ioWorker.terminate();
453
+ this.ioWorker = null;
457
454
  await Promise.all(this.workers.map((worker) => worker.terminate()));
458
455
  this.workers = [];
459
456
  native.stop(this.dbCtxExternal);
@@ -7,6 +7,7 @@ import { foreachDirtyBlock } from '../blocks.js';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { setNativeSchema, setSchemaOnServer, writeSchemaFile, } from '../schema.js';
9
9
  import { setToAwake, waitUntilSleeping } from './utils.js';
10
+ import { serialize } from '@based/schema';
10
11
  const __filename = fileURLToPath(import.meta.url);
11
12
  const __dirname = dirname(__filename);
12
13
  const workerPath = join(__dirname, 'worker.js');
@@ -74,8 +75,14 @@ export const migrate = async (server, fromSchema, toSchema, transform) => {
74
75
  isDbMigrateWorker: true,
75
76
  from: fromAddress,
76
77
  to: toAddress,
77
- fromSchema,
78
- toSchema,
78
+ fromSchema: serialize(fromSchema, {
79
+ stripMetaInformation: true,
80
+ stripTransform: true,
81
+ }),
82
+ toSchema: serialize(toSchema, {
83
+ stripMetaInformation: true,
84
+ stripTransform: true,
85
+ }),
79
86
  channel: port2,
80
87
  workerState,
81
88
  transformFns,
@@ -83,14 +90,17 @@ export const migrate = async (server, fromSchema, toSchema, transform) => {
83
90
  transferList: [port2],
84
91
  });
85
92
  // handle?
86
- worker.on('error', (err) => {
87
- killed = true;
88
- console.error(`Error in migration ${err.message}`);
93
+ const errorPromise = new Promise((resolve) => {
94
+ worker.once('error', (err) => {
95
+ killed = true;
96
+ console.error(`Error in migration ${err.message}, aborting migration`);
97
+ resolve();
98
+ });
89
99
  });
90
100
  // Block handling
91
101
  let i = 0;
92
102
  let rangesToMigrate = [];
93
- await save(server, false, false, true);
103
+ await save(server, { skipMigrationCheck: true });
94
104
  server.verifTree.foreachBlock((block) => {
95
105
  const [typeId, start] = destructureTreeKey(block.key);
96
106
  const def = server.schemaTypesParsedById[typeId];
@@ -103,13 +113,13 @@ export const migrate = async (server, fromSchema, toSchema, transform) => {
103
113
  break;
104
114
  }
105
115
  // block modifies
106
- server.processingQueries++;
116
+ server.activeReaders++;
107
117
  const leafData = rangesToMigrate[i++];
108
118
  port1.postMessage(leafData);
109
119
  setToAwake(workerState, true);
110
- await waitUntilSleeping(workerState);
120
+ await Promise.race([errorPromise, waitUntilSleeping(workerState)]);
111
121
  // exec queued modifies
112
- server.processingQueries--;
122
+ server.activeReaders--;
113
123
  server.onQueryEnd();
114
124
  if (i === rangesToMigrate.length) {
115
125
  if (server.dirtyRanges.size) {
@@ -149,14 +159,18 @@ export const migrate = async (server, fromSchema, toSchema, transform) => {
149
159
  // -----------------------------------------
150
160
  tmpDb.server.dbCtxExternal = fromCtx;
151
161
  // TODO makes this SYNC
152
- const promises = server.workers.map((worker) => worker.updateCtx(toAddress));
162
+ const promises = [server.ioWorker, ...server.workers].map((worker) => worker.updateCtx(toAddress));
153
163
  promises.push(tmpDb.destroy(), worker.terminate());
154
164
  await Promise.all(promises);
155
165
  if (abort()) {
156
166
  return;
157
167
  }
158
168
  native.membarSyncRead();
159
- await save(server, false, true, true);
169
+ await save(server, {
170
+ forceFullDump: true,
171
+ skipDirtyCheck: true,
172
+ skipMigrationCheck: true,
173
+ });
160
174
  await writeSchemaFile(server, toSchema);
161
175
  server.migrating = 0;
162
176
  process.nextTick(() => server.emit('schema', server.schema));
@@ -6,6 +6,7 @@ import { isTypedArray } from 'node:util/types';
6
6
  import { setSchemaOnServer } from '../schema.js';
7
7
  import { setToSleep } from './utils.js';
8
8
  import { setLocalClientSchema } from '../../client/setLocalClientSchema.js';
9
+ import { deSerialize } from '@based/schema';
9
10
  if (isMainThread) {
10
11
  console.warn('running worker.ts in mainthread');
11
12
  }
@@ -41,80 +42,87 @@ else if (workerData?.isDbMigrateWorker) {
41
42
  };
42
43
  fromDb.server.dbCtxExternal = fromCtx;
43
44
  toDb.server.dbCtxExternal = toCtx;
44
- setSchemaOnServer(fromDb.server, fromSchema);
45
- setSchemaOnServer(toDb.server, toSchema);
45
+ setSchemaOnServer(fromDb.server, deSerialize(fromSchema));
46
+ setSchemaOnServer(toDb.server, deSerialize(toSchema));
46
47
  setLocalClientSchema(fromDb.client, fromDb.server.schema);
47
48
  setLocalClientSchema(toDb.client, toDb.server.schema);
48
- const map = {};
49
- for (const type in fromDb.server.schemaTypesParsed) {
50
- const { id, props } = fromDb.server.schemaTypesParsed[type];
51
- const include = Object.keys(props);
52
- let i = include.length;
53
- while (i--) {
54
- const path = include[i];
55
- if (props[path].typeIndex === REFERENCE ||
56
- props[path].typeIndex === REFERENCES) {
57
- include[i] = `${path}.id`;
58
- if (props[path].edges) {
59
- for (const key in props[path].edges) {
60
- const prop = props[path].edges[key];
61
- if (prop.typeIndex === REFERENCE || prop.typeIndex === REFERENCES) {
62
- include.push(`${path}.${key}.id`);
63
- }
64
- else {
65
- include.push(`${path}.${key}`);
49
+ try {
50
+ const map = {};
51
+ for (const type in fromDb.server.schemaTypesParsed) {
52
+ const { id, props } = fromDb.server.schemaTypesParsed[type];
53
+ const include = Object.keys(props);
54
+ let i = include.length;
55
+ while (i--) {
56
+ const path = include[i];
57
+ if (props[path].typeIndex === REFERENCE ||
58
+ props[path].typeIndex === REFERENCES) {
59
+ include[i] = `${path}.id`;
60
+ if (props[path].edges) {
61
+ for (const key in props[path].edges) {
62
+ const prop = props[path].edges[key];
63
+ if (prop.typeIndex === REFERENCE ||
64
+ prop.typeIndex === REFERENCES) {
65
+ include.push(`${path}.${key}.id`);
66
+ }
67
+ else {
68
+ include.push(`${path}.${key}`);
69
+ }
66
70
  }
67
71
  }
68
72
  }
69
73
  }
74
+ map[id] = { type, include };
70
75
  }
71
- map[id] = { type, include };
72
- }
73
- for (const type in transformFns) {
74
- const fnOrNull = transformFns[type];
75
- transformFns[type] = eval(`(${fnOrNull})`);
76
- }
77
- while (true) {
78
- let msg;
79
- while ((msg = receiveMessageOnPort(channel))) {
80
- const leafData = msg.message;
81
- const { type, include } = map[leafData.typeId];
82
- const typeTransformFn = transformFns[type];
83
- if (typeTransformFn) {
84
- const nodes = fromDb
85
- .query(type)
86
- .include(include)
87
- .range(leafData.start - 1, leafData.end)
88
- ._getSync(fromCtx);
89
- for (const node of nodes) {
90
- const res = typeTransformFn(node);
91
- if (res === null) {
92
- continue;
93
- }
94
- if (Array.isArray(res)) {
95
- toDb.create(res[0], res[1] || node, { unsafe: true });
96
- }
97
- else {
98
- toDb.create(type, res || node, { unsafe: true });
76
+ for (const type in transformFns) {
77
+ const fnOrNull = transformFns[type];
78
+ transformFns[type] = eval(`(${fnOrNull})`);
79
+ }
80
+ while (true) {
81
+ let msg;
82
+ while ((msg = receiveMessageOnPort(channel))) {
83
+ const leafData = msg.message;
84
+ const { type, include } = map[leafData.typeId];
85
+ const typeTransformFn = transformFns[type];
86
+ if (typeTransformFn) {
87
+ const nodes = fromDb
88
+ .query(type)
89
+ .include(include)
90
+ .range(leafData.start - 1, leafData.end)
91
+ ._getSync(fromCtx);
92
+ for (const node of nodes) {
93
+ const res = typeTransformFn(node);
94
+ if (res === null) {
95
+ continue;
96
+ }
97
+ if (Array.isArray(res)) {
98
+ toDb.create(res[0], res[1] || node, { unsafe: true });
99
+ }
100
+ else {
101
+ toDb.create(type, res || node, { unsafe: true });
102
+ }
99
103
  }
100
104
  }
101
- }
102
- else if (type in toDb.server.schemaTypesParsed) {
103
- const nodes = fromDb
104
- .query(type)
105
- .include(include)
106
- .range(leafData.start - 1, leafData.end)
107
- ._getSync(fromCtx);
108
- for (const node of nodes) {
109
- toDb.create(type, node, { unsafe: true });
105
+ else if (type in toDb.server.schemaTypesParsed) {
106
+ const nodes = fromDb
107
+ .query(type)
108
+ .include(include)
109
+ .range(leafData.start - 1, leafData.end)
110
+ ._getSync(fromCtx);
111
+ for (const node of nodes) {
112
+ toDb.create(type, node, { unsafe: true });
113
+ }
110
114
  }
111
115
  }
116
+ await toDb.drain();
117
+ native.membarSyncWrite();
118
+ // WE ARE ONLY GOING TO SEND { type: lastNodeId }
119
+ channel.postMessage(cp(toDb.server.schemaTypesParsed));
120
+ setToSleep(workerState);
112
121
  }
113
- await toDb.drain();
114
- native.membarSyncWrite();
115
- // WE ARE ONLY GOING TO SEND { type: lastNodeId }
116
- channel.postMessage(cp(toDb.server.schemaTypesParsed));
117
- setToSleep(workerState);
122
+ }
123
+ catch (e) {
124
+ console.error(e);
125
+ throw e;
118
126
  }
119
127
  }
120
128
  else {
@@ -19,5 +19,11 @@ export type Writelog = {
19
19
  [t: number]: RangeDump[];
20
20
  };
21
21
  };
22
- export declare function save<T extends boolean>(db: DbServer, sync?: T, forceFullDump?: boolean, skipMigrationCheck?: boolean): T extends true ? void : Promise<void>;
22
+ type SaveOpts = {
23
+ forceFullDump?: boolean;
24
+ skipDirtyCheck?: boolean;
25
+ skipMigrationCheck?: boolean;
26
+ };
27
+ export declare function saveSync(db: DbServer, opts?: SaveOpts): void;
28
+ export declare function save(db: DbServer, opts?: SaveOpts): Promise<void>;
23
29
  export {};