@based/db 0.0.1
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/README.md +43 -0
- package/dist/lib/darwin_aarch64/include/cdefs.h +317 -0
- package/dist/lib/darwin_aarch64/include/libdeflate.h +322 -0
- package/dist/lib/darwin_aarch64/include/libdeflate_strings.h +35 -0
- package/dist/lib/darwin_aarch64/include/linker_set.h +109 -0
- package/dist/lib/darwin_aarch64/include/queue.h +627 -0
- package/dist/lib/darwin_aarch64/include/selva/_export.h +7 -0
- package/dist/lib/darwin_aarch64/include/selva/align.h +9 -0
- package/dist/lib/darwin_aarch64/include/selva/backoff_timeout.h +29 -0
- package/dist/lib/darwin_aarch64/include/selva/base64.h +59 -0
- package/dist/lib/darwin_aarch64/include/selva/base64url.h +59 -0
- package/dist/lib/darwin_aarch64/include/selva/bitmap.h +95 -0
- package/dist/lib/darwin_aarch64/include/selva/crc32c.h +17 -0
- package/dist/lib/darwin_aarch64/include/selva/ctime.h +135 -0
- package/dist/lib/darwin_aarch64/include/selva/db.h +284 -0
- package/dist/lib/darwin_aarch64/include/selva/endian.h +301 -0
- package/dist/lib/darwin_aarch64/include/selva/fast_linear_search.h +23 -0
- package/dist/lib/darwin_aarch64/include/selva/fast_memmem.h +11 -0
- package/dist/lib/darwin_aarch64/include/selva/fast_parsei.h +36 -0
- package/dist/lib/darwin_aarch64/include/selva/fields.h +338 -0
- package/dist/lib/darwin_aarch64/include/selva/find.h +47 -0
- package/dist/lib/darwin_aarch64/include/selva/lpf.h +28 -0
- package/dist/lib/darwin_aarch64/include/selva/node_id_set.h +43 -0
- package/dist/lib/darwin_aarch64/include/selva/poptop.h +114 -0
- package/dist/lib/darwin_aarch64/include/selva/queue_r.h +190 -0
- package/dist/lib/darwin_aarch64/include/selva/selva_hash128.h +39 -0
- package/dist/lib/darwin_aarch64/include/selva/selva_lang.h +105 -0
- package/dist/lib/darwin_aarch64/include/selva/selva_math.h +37 -0
- package/dist/lib/darwin_aarch64/include/selva/selva_string.h +672 -0
- package/dist/lib/darwin_aarch64/include/selva/sort.h +119 -0
- package/dist/lib/darwin_aarch64/include/selva/strsearch.h +43 -0
- package/dist/lib/darwin_aarch64/include/selva/timestamp.h +25 -0
- package/dist/lib/darwin_aarch64/include/selva/traverse.h +65 -0
- package/dist/lib/darwin_aarch64/include/selva/types.h +110 -0
- package/dist/lib/darwin_aarch64/include/selva/vector.h +14 -0
- package/dist/lib/darwin_aarch64/include/selva/worker_ctx.h +13 -0
- package/dist/lib/darwin_aarch64/include/selva_error.h +137 -0
- package/dist/lib/darwin_aarch64/include/selva_lang_code.h +157 -0
- package/dist/lib/darwin_aarch64/include/tree.h +852 -0
- package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
- package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.8.0.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.0.8.2.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.0.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
- package/dist/lib/linux_aarch64/include/cdefs.h +317 -0
- package/dist/lib/linux_aarch64/include/libdeflate.h +322 -0
- package/dist/lib/linux_aarch64/include/libdeflate_strings.h +35 -0
- package/dist/lib/linux_aarch64/include/linker_set.h +109 -0
- package/dist/lib/linux_aarch64/include/queue.h +627 -0
- package/dist/lib/linux_aarch64/include/selva/_export.h +7 -0
- package/dist/lib/linux_aarch64/include/selva/align.h +9 -0
- package/dist/lib/linux_aarch64/include/selva/backoff_timeout.h +29 -0
- package/dist/lib/linux_aarch64/include/selva/base64.h +59 -0
- package/dist/lib/linux_aarch64/include/selva/base64url.h +59 -0
- package/dist/lib/linux_aarch64/include/selva/bitmap.h +95 -0
- package/dist/lib/linux_aarch64/include/selva/crc32c.h +17 -0
- package/dist/lib/linux_aarch64/include/selva/ctime.h +135 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +284 -0
- package/dist/lib/linux_aarch64/include/selva/endian.h +301 -0
- package/dist/lib/linux_aarch64/include/selva/fast_linear_search.h +23 -0
- package/dist/lib/linux_aarch64/include/selva/fast_memmem.h +11 -0
- package/dist/lib/linux_aarch64/include/selva/fast_parsei.h +36 -0
- package/dist/lib/linux_aarch64/include/selva/fields.h +338 -0
- package/dist/lib/linux_aarch64/include/selva/find.h +47 -0
- package/dist/lib/linux_aarch64/include/selva/lpf.h +28 -0
- package/dist/lib/linux_aarch64/include/selva/node_id_set.h +43 -0
- package/dist/lib/linux_aarch64/include/selva/poptop.h +114 -0
- package/dist/lib/linux_aarch64/include/selva/queue_r.h +190 -0
- package/dist/lib/linux_aarch64/include/selva/selva_hash128.h +39 -0
- package/dist/lib/linux_aarch64/include/selva/selva_lang.h +105 -0
- package/dist/lib/linux_aarch64/include/selva/selva_math.h +37 -0
- package/dist/lib/linux_aarch64/include/selva/selva_string.h +672 -0
- package/dist/lib/linux_aarch64/include/selva/sort.h +119 -0
- package/dist/lib/linux_aarch64/include/selva/strsearch.h +43 -0
- package/dist/lib/linux_aarch64/include/selva/timestamp.h +25 -0
- package/dist/lib/linux_aarch64/include/selva/traverse.h +65 -0
- package/dist/lib/linux_aarch64/include/selva/types.h +110 -0
- package/dist/lib/linux_aarch64/include/selva/vector.h +14 -0
- package/dist/lib/linux_aarch64/include/selva/worker_ctx.h +13 -0
- package/dist/lib/linux_aarch64/include/selva_error.h +137 -0
- package/dist/lib/linux_aarch64/include/selva_lang_code.h +157 -0
- package/dist/lib/linux_aarch64/include/tree.h +852 -0
- package/dist/lib/linux_aarch64/libdeflate.so +0 -0
- package/dist/lib/linux_aarch64/libjemalloc_selva.so.2 +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so.0 +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so.0.8.2 +0 -0
- package/dist/lib/linux_x86_64/include/cdefs.h +317 -0
- package/dist/lib/linux_x86_64/include/libdeflate.h +322 -0
- package/dist/lib/linux_x86_64/include/libdeflate_strings.h +35 -0
- package/dist/lib/linux_x86_64/include/linker_set.h +109 -0
- package/dist/lib/linux_x86_64/include/queue.h +627 -0
- package/dist/lib/linux_x86_64/include/selva/_export.h +7 -0
- package/dist/lib/linux_x86_64/include/selva/align.h +9 -0
- package/dist/lib/linux_x86_64/include/selva/backoff_timeout.h +29 -0
- package/dist/lib/linux_x86_64/include/selva/base64.h +59 -0
- package/dist/lib/linux_x86_64/include/selva/base64url.h +59 -0
- package/dist/lib/linux_x86_64/include/selva/bitmap.h +95 -0
- package/dist/lib/linux_x86_64/include/selva/crc32c.h +17 -0
- package/dist/lib/linux_x86_64/include/selva/ctime.h +135 -0
- package/dist/lib/linux_x86_64/include/selva/db.h +284 -0
- package/dist/lib/linux_x86_64/include/selva/endian.h +301 -0
- package/dist/lib/linux_x86_64/include/selva/fast_linear_search.h +23 -0
- package/dist/lib/linux_x86_64/include/selva/fast_memmem.h +11 -0
- package/dist/lib/linux_x86_64/include/selva/fast_parsei.h +36 -0
- package/dist/lib/linux_x86_64/include/selva/fields.h +338 -0
- package/dist/lib/linux_x86_64/include/selva/find.h +47 -0
- package/dist/lib/linux_x86_64/include/selva/lpf.h +28 -0
- package/dist/lib/linux_x86_64/include/selva/node_id_set.h +43 -0
- package/dist/lib/linux_x86_64/include/selva/poptop.h +114 -0
- package/dist/lib/linux_x86_64/include/selva/queue_r.h +190 -0
- package/dist/lib/linux_x86_64/include/selva/selva_hash128.h +39 -0
- package/dist/lib/linux_x86_64/include/selva/selva_lang.h +105 -0
- package/dist/lib/linux_x86_64/include/selva/selva_math.h +37 -0
- package/dist/lib/linux_x86_64/include/selva/selva_string.h +672 -0
- package/dist/lib/linux_x86_64/include/selva/sort.h +119 -0
- package/dist/lib/linux_x86_64/include/selva/strsearch.h +43 -0
- package/dist/lib/linux_x86_64/include/selva/timestamp.h +25 -0
- package/dist/lib/linux_x86_64/include/selva/traverse.h +65 -0
- package/dist/lib/linux_x86_64/include/selva/types.h +110 -0
- package/dist/lib/linux_x86_64/include/selva/vector.h +14 -0
- package/dist/lib/linux_x86_64/include/selva/worker_ctx.h +13 -0
- package/dist/lib/linux_x86_64/include/selva_error.h +137 -0
- package/dist/lib/linux_x86_64/include/selva_lang_code.h +157 -0
- package/dist/lib/linux_x86_64/include/tree.h +852 -0
- package/dist/lib/linux_x86_64/libdeflate.so +0 -0
- package/dist/lib/linux_x86_64/libjemalloc_selva.so.2 +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so.0 +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so.0.8.2 +0 -0
- package/dist/src/client/crc32.d.ts +1 -0
- package/dist/src/client/crc32.js +281 -0
- package/dist/src/client/index.d.ts +58 -0
- package/dist/src/client/index.js +120 -0
- package/dist/src/client/modify/ModifyRes.d.ts +26 -0
- package/dist/src/client/modify/ModifyRes.js +98 -0
- package/dist/src/client/modify/alias.d.ts +4 -0
- package/dist/src/client/modify/alias.js +47 -0
- package/dist/src/client/modify/binary.d.ts +6 -0
- package/dist/src/client/modify/binary.js +61 -0
- package/dist/src/client/modify/create.d.ts +4 -0
- package/dist/src/client/modify/create.js +108 -0
- package/dist/src/client/modify/fixed.d.ts +5 -0
- package/dist/src/client/modify/fixed.js +118 -0
- package/dist/src/client/modify/hll.d.ts +4 -0
- package/dist/src/client/modify/hll.js +58 -0
- package/dist/src/client/modify/index.d.ts +4 -0
- package/dist/src/client/modify/index.js +4 -0
- package/dist/src/client/modify/modify.d.ts +5 -0
- package/dist/src/client/modify/modify.js +126 -0
- package/dist/src/client/modify/references/edge.d.ts +6 -0
- package/dist/src/client/modify/references/edge.js +158 -0
- package/dist/src/client/modify/references/reference.d.ts +11 -0
- package/dist/src/client/modify/references/reference.js +92 -0
- package/dist/src/client/modify/references/references.d.ts +17 -0
- package/dist/src/client/modify/references/references.js +271 -0
- package/dist/src/client/modify/remove.d.ts +2 -0
- package/dist/src/client/modify/remove.js +36 -0
- package/dist/src/client/modify/setCursor.d.ts +4 -0
- package/dist/src/client/modify/setCursor.js +36 -0
- package/dist/src/client/modify/string.d.ts +5 -0
- package/dist/src/client/modify/string.js +56 -0
- package/dist/src/client/modify/text.d.ts +5 -0
- package/dist/src/client/modify/text.js +14 -0
- package/dist/src/client/modify/types.d.ts +14 -0
- package/dist/src/client/modify/types.js +12 -0
- package/dist/src/client/modify/update.d.ts +5 -0
- package/dist/src/client/modify/update.js +80 -0
- package/dist/src/client/modify/upsert.d.ts +2 -0
- package/dist/src/client/modify/upsert.js +40 -0
- package/dist/src/client/operations.d.ts +31 -0
- package/dist/src/client/operations.js +110 -0
- package/dist/src/client/query/BasedDbQuery.d.ts +40 -0
- package/dist/src/client/query/BasedDbQuery.js +235 -0
- package/dist/src/client/query/BasedIterable.d.ts +26 -0
- package/dist/src/client/query/BasedIterable.js +113 -0
- package/dist/src/client/query/debug.d.ts +3 -0
- package/dist/src/client/query/debug.js +117 -0
- package/dist/src/client/query/display.d.ts +5 -0
- package/dist/src/client/query/display.js +233 -0
- package/dist/src/client/query/filter/FilterBranch.d.ts +13 -0
- package/dist/src/client/query/filter/FilterBranch.js +29 -0
- package/dist/src/client/query/filter/createFixedFilterBuffer.d.ts +3 -0
- package/dist/src/client/query/filter/createFixedFilterBuffer.js +101 -0
- package/dist/src/client/query/filter/createReferenceFilter.d.ts +2 -0
- package/dist/src/client/query/filter/createReferenceFilter.js +24 -0
- package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -0
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +81 -0
- package/dist/src/client/query/filter/filter.d.ts +10 -0
- package/dist/src/client/query/filter/filter.js +134 -0
- package/dist/src/client/query/filter/operators.d.ts +6 -0
- package/dist/src/client/query/filter/operators.js +98 -0
- package/dist/src/client/query/filter/parseFilterValue.d.ts +2 -0
- package/dist/src/client/query/filter/parseFilterValue.js +99 -0
- package/dist/src/client/query/filter/primitiveFilter.d.ts +4 -0
- package/dist/src/client/query/filter/primitiveFilter.js +47 -0
- package/dist/src/client/query/filter/toBuffer.d.ts +3 -0
- package/dist/src/client/query/filter/toBuffer.js +100 -0
- package/dist/src/client/query/filter/types.d.ts +6 -0
- package/dist/src/client/query/filter/types.js +7 -0
- package/dist/src/client/query/include/props.d.ts +6 -0
- package/dist/src/client/query/include/props.js +44 -0
- package/dist/src/client/query/include/toBuffer.d.ts +3 -0
- package/dist/src/client/query/include/toBuffer.js +82 -0
- package/dist/src/client/query/include/utils.d.ts +6 -0
- package/dist/src/client/query/include/utils.js +41 -0
- package/dist/src/client/query/include/walk.d.ts +3 -0
- package/dist/src/client/query/include/walk.js +70 -0
- package/dist/src/client/query/query.d.ts +10 -0
- package/dist/src/client/query/query.js +11 -0
- package/dist/src/client/query/queryDef.d.ts +3 -0
- package/dist/src/client/query/queryDef.js +54 -0
- package/dist/src/client/query/read/read.d.ts +8 -0
- package/dist/src/client/query/read/read.js +303 -0
- package/dist/src/client/query/registerQuery.d.ts +2 -0
- package/dist/src/client/query/registerQuery.js +31 -0
- package/dist/src/client/query/search/index.d.ts +6 -0
- package/dist/src/client/query/search/index.js +82 -0
- package/dist/src/client/query/sort.d.ts +3 -0
- package/dist/src/client/query/sort.js +18 -0
- package/dist/src/client/query/subscription/index.d.ts +5 -0
- package/dist/src/client/query/subscription/index.js +52 -0
- package/dist/src/client/query/subscription/markers.d.ts +10 -0
- package/dist/src/client/query/subscription/markers.js +213 -0
- package/dist/src/client/query/subscription/run.d.ts +5 -0
- package/dist/src/client/query/subscription/run.js +69 -0
- package/dist/src/client/query/subscription/types.d.ts +33 -0
- package/dist/src/client/query/subscription/types.js +3 -0
- package/dist/src/client/query/thresholds.d.ts +6 -0
- package/dist/src/client/query/thresholds.js +16 -0
- package/dist/src/client/query/toBuffer.d.ts +3 -0
- package/dist/src/client/query/toBuffer.js +229 -0
- package/dist/src/client/query/types.d.ts +88 -0
- package/dist/src/client/query/types.js +15 -0
- package/dist/src/client/query/validation.d.ts +15 -0
- package/dist/src/client/query/validation.js +59 -0
- package/dist/src/client/string.d.ts +5 -0
- package/dist/src/client/string.js +73 -0
- package/dist/src/client/tree.d.ts +1 -0
- package/dist/src/client/tree.js +5 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +85 -0
- package/dist/src/native.d.ts +28 -0
- package/dist/src/native.js +96 -0
- package/dist/src/server/csmt/draw-dot.d.ts +2 -0
- package/dist/src/server/csmt/draw-dot.js +32 -0
- package/dist/src/server/csmt/index.d.ts +4 -0
- package/dist/src/server/csmt/index.js +5 -0
- package/dist/src/server/csmt/match.d.ts +7 -0
- package/dist/src/server/csmt/match.js +10 -0
- package/dist/src/server/csmt/memebership-proof.d.ts +7 -0
- package/dist/src/server/csmt/memebership-proof.js +122 -0
- package/dist/src/server/csmt/tree-utils.d.ts +6 -0
- package/dist/src/server/csmt/tree-utils.js +33 -0
- package/dist/src/server/csmt/tree.d.ts +2 -0
- package/dist/src/server/csmt/tree.js +209 -0
- package/dist/src/server/csmt/types.d.ts +40 -0
- package/dist/src/server/csmt/types.js +2 -0
- package/dist/src/server/index.d.ts +85 -0
- package/dist/src/server/index.js +407 -0
- package/dist/src/server/migrate/index.d.ts +7 -0
- package/dist/src/server/migrate/index.js +108 -0
- package/dist/src/server/migrate/worker.d.ts +1 -0
- package/dist/src/server/migrate/worker.js +81 -0
- package/dist/src/server/save.d.ts +2 -0
- package/dist/src/server/save.js +66 -0
- package/dist/src/server/schema/schema.d.ts +3 -0
- package/dist/src/server/schema/schema.js +4 -0
- package/dist/src/server/schema/selvaBuffer.d.ts +4 -0
- package/dist/src/server/schema/selvaBuffer.js +102 -0
- package/dist/src/server/schema/typeDef.d.ts +6 -0
- package/dist/src/server/schema/typeDef.js +315 -0
- package/dist/src/server/schema/types.d.ts +127 -0
- package/dist/src/server/schema/types.js +113 -0
- package/dist/src/server/schema/utils.d.ts +6 -0
- package/dist/src/server/schema/utils.js +21 -0
- package/dist/src/server/start.d.ts +6 -0
- package/dist/src/server/start.js +86 -0
- package/dist/src/server/tree.d.ts +13 -0
- package/dist/src/server/tree.js +33 -0
- package/dist/src/server/worker.d.ts +1 -0
- package/dist/src/server/worker.js +35 -0
- package/package.json +48 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import native from '../native.js';
|
|
2
|
+
import { rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { getPropType } from '@based/schema';
|
|
5
|
+
import { genRootId } from './schema/utils.js';
|
|
6
|
+
import { updateTypeDefs } from './schema/typeDef.js';
|
|
7
|
+
import { schemaToSelvaBuffer } from './schema/selvaBuffer.js';
|
|
8
|
+
import { start } from './start.js';
|
|
9
|
+
import { foreachDirtyBlock, makeCsmtKey } from './tree.js';
|
|
10
|
+
import { save } from './save.js';
|
|
11
|
+
import { Worker, MessageChannel } from 'node:worker_threads';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { setTimeout } from 'node:timers/promises';
|
|
14
|
+
import { migrate } from './migrate/index.js';
|
|
15
|
+
const SCHEMA_FILE = 'schema.json';
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
const workerPath = join(__dirname, 'worker.js');
|
|
19
|
+
export class DbWorker {
|
|
20
|
+
constructor(address, db) {
|
|
21
|
+
const { port1, port2 } = new MessageChannel();
|
|
22
|
+
this.db = db;
|
|
23
|
+
this.channel = port1;
|
|
24
|
+
this.worker = new Worker(workerPath, {
|
|
25
|
+
workerData: {
|
|
26
|
+
channel: port2,
|
|
27
|
+
address,
|
|
28
|
+
},
|
|
29
|
+
transferList: [port2],
|
|
30
|
+
});
|
|
31
|
+
port1.on('message', (buf) => {
|
|
32
|
+
this.resolvers.shift()(buf);
|
|
33
|
+
this.db.onQueryEnd();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
db;
|
|
37
|
+
channel;
|
|
38
|
+
worker;
|
|
39
|
+
resolvers = [];
|
|
40
|
+
callback = (resolve) => {
|
|
41
|
+
this.db.processingQueries++;
|
|
42
|
+
this.resolvers.push(resolve);
|
|
43
|
+
};
|
|
44
|
+
updateCtx(address) {
|
|
45
|
+
this.channel.postMessage(address);
|
|
46
|
+
return new Promise(this.callback);
|
|
47
|
+
}
|
|
48
|
+
getQueryBuf(buf) {
|
|
49
|
+
this.channel.postMessage(buf);
|
|
50
|
+
return new Promise(this.callback);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class DbServer {
|
|
54
|
+
modifyBuf;
|
|
55
|
+
dbCtxExternal; // pointer to zig dbCtx
|
|
56
|
+
schema = {
|
|
57
|
+
lastId: 1, // we reserve one for root props
|
|
58
|
+
types: {},
|
|
59
|
+
};
|
|
60
|
+
migrating = null;
|
|
61
|
+
schemaTypesParsed = {};
|
|
62
|
+
schemaTypesParsedById = {};
|
|
63
|
+
fileSystemPath;
|
|
64
|
+
maxModifySize;
|
|
65
|
+
merkleTree;
|
|
66
|
+
dirtyRanges = new Set();
|
|
67
|
+
csmtHashFun = native.createHash();
|
|
68
|
+
workers = [];
|
|
69
|
+
availableWorkerIndex = -1;
|
|
70
|
+
processingQueries = 0;
|
|
71
|
+
modifyQueue = [];
|
|
72
|
+
queryQueue = new Map();
|
|
73
|
+
stopped;
|
|
74
|
+
onSchemaChange;
|
|
75
|
+
constructor({ path, maxModifySize = 100 * 1e3 * 1e3, onSchemaChange, }) {
|
|
76
|
+
this.maxModifySize = maxModifySize;
|
|
77
|
+
this.fileSystemPath = path;
|
|
78
|
+
this.sortIndexes = {};
|
|
79
|
+
this.onSchemaChange = onSchemaChange;
|
|
80
|
+
}
|
|
81
|
+
start(opts) {
|
|
82
|
+
return start(this, opts);
|
|
83
|
+
}
|
|
84
|
+
save() {
|
|
85
|
+
return save(this);
|
|
86
|
+
}
|
|
87
|
+
createCsmtHashFun = () => {
|
|
88
|
+
// We can just reuse it as long as we only have one tree.
|
|
89
|
+
this.csmtHashFun.reset();
|
|
90
|
+
return this.csmtHashFun;
|
|
91
|
+
};
|
|
92
|
+
sortIndexes;
|
|
93
|
+
createSortIndex(type, field) {
|
|
94
|
+
const t = this.schemaTypesParsed[type];
|
|
95
|
+
const prop = t.props[field];
|
|
96
|
+
let types = this.sortIndexes[t.id];
|
|
97
|
+
if (!types) {
|
|
98
|
+
types = this.sortIndexes[t.id] = {};
|
|
99
|
+
}
|
|
100
|
+
let fields = types[prop.prop];
|
|
101
|
+
if (!fields) {
|
|
102
|
+
fields = types[prop.prop] = {};
|
|
103
|
+
}
|
|
104
|
+
let sortIndex = fields[prop.start];
|
|
105
|
+
if (sortIndex) {
|
|
106
|
+
return sortIndex;
|
|
107
|
+
}
|
|
108
|
+
const buf = Buffer.allocUnsafe(8);
|
|
109
|
+
// size [2 type] [1 field] [2 start] [2 len]
|
|
110
|
+
buf.writeUint16LE(t.id, 0);
|
|
111
|
+
buf[2] = prop.prop;
|
|
112
|
+
buf.writeUint16LE(prop.start, 3);
|
|
113
|
+
buf.writeUint16LE(prop.len, 5);
|
|
114
|
+
buf[7] = prop.typeIndex;
|
|
115
|
+
sortIndex = native.createSortIndex(buf, this.dbCtxExternal);
|
|
116
|
+
fields[prop.start] = sortIndex;
|
|
117
|
+
return sortIndex;
|
|
118
|
+
}
|
|
119
|
+
destroySortIndex(type, field) {
|
|
120
|
+
const t = this.schemaTypesParsed[type];
|
|
121
|
+
const prop = t.props[field];
|
|
122
|
+
let types = this.sortIndexes[t.id];
|
|
123
|
+
if (!type) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
let fields = types[prop.prop];
|
|
127
|
+
if (!fields) {
|
|
128
|
+
fields = types[prop.prop] = {};
|
|
129
|
+
}
|
|
130
|
+
let sortIndex = fields[prop.start];
|
|
131
|
+
if (sortIndex) {
|
|
132
|
+
const buf = Buffer.allocUnsafe(5);
|
|
133
|
+
buf.writeUint16LE(t.id, 0);
|
|
134
|
+
buf[2] = prop.prop;
|
|
135
|
+
buf.writeUint16LE(prop.start, 3);
|
|
136
|
+
native.destroySortIndex(buf, this.dbCtxExternal);
|
|
137
|
+
delete fields[prop.start];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
hasSortIndex(typeId, field, start) {
|
|
141
|
+
let types = this.sortIndexes[typeId];
|
|
142
|
+
if (!types) {
|
|
143
|
+
types = this.sortIndexes[typeId] = {};
|
|
144
|
+
}
|
|
145
|
+
let fields = types[field];
|
|
146
|
+
if (!fields) {
|
|
147
|
+
fields = types[field] = {};
|
|
148
|
+
}
|
|
149
|
+
let sortIndex = fields[start];
|
|
150
|
+
if (sortIndex) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
migrateSchema(schema, transform) {
|
|
156
|
+
return migrate(this, schema, transform);
|
|
157
|
+
}
|
|
158
|
+
createSortIndexBuffer(typeId, field, start) {
|
|
159
|
+
const buf = Buffer.allocUnsafe(8);
|
|
160
|
+
buf.writeUint16LE(typeId, 0);
|
|
161
|
+
buf[2] = field;
|
|
162
|
+
buf.writeUint16LE(start, 3);
|
|
163
|
+
let typeDef;
|
|
164
|
+
let prop;
|
|
165
|
+
for (const t in this.schemaTypesParsed) {
|
|
166
|
+
typeDef = this.schemaTypesParsed[t];
|
|
167
|
+
if (typeDef.id == typeId) {
|
|
168
|
+
for (const p in typeDef.props) {
|
|
169
|
+
const propDef = typeDef.props[p];
|
|
170
|
+
if (propDef.prop == field && propDef.start == start) {
|
|
171
|
+
prop = propDef;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!typeDef) {
|
|
179
|
+
throw new Error(`Cannot find type id on db from query for sort ${typeId}`);
|
|
180
|
+
}
|
|
181
|
+
if (!prop) {
|
|
182
|
+
throw new Error(`Cannot find prop on db from query for sort ${field}`);
|
|
183
|
+
}
|
|
184
|
+
buf.writeUint16LE(prop.len, 5);
|
|
185
|
+
buf[7] = prop.typeIndex;
|
|
186
|
+
// put in modify stuff
|
|
187
|
+
const sortIndex = native.createSortIndex(buf, this.dbCtxExternal);
|
|
188
|
+
const types = this.sortIndexes[typeId];
|
|
189
|
+
const fields = types[field];
|
|
190
|
+
fields[start] = sortIndex;
|
|
191
|
+
return sortIndex;
|
|
192
|
+
}
|
|
193
|
+
updateMerkleTree() {
|
|
194
|
+
foreachDirtyBlock(this, (mtKey, typeId, start, end) => {
|
|
195
|
+
const oldLeaf = this.merkleTree.search(mtKey);
|
|
196
|
+
const hash = Buffer.allocUnsafe(16);
|
|
197
|
+
native.getNodeRangeHash(typeId, start, end, hash, this.dbCtxExternal);
|
|
198
|
+
if (oldLeaf) {
|
|
199
|
+
if (oldLeaf.hash.equals(hash)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
this.merkleTree.delete(mtKey);
|
|
204
|
+
}
|
|
205
|
+
catch (err) { }
|
|
206
|
+
}
|
|
207
|
+
const data = {
|
|
208
|
+
file: '', // not saved yet
|
|
209
|
+
typeId,
|
|
210
|
+
start,
|
|
211
|
+
end,
|
|
212
|
+
};
|
|
213
|
+
this.merkleTree.insert(mtKey, hash, data);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
putSchema(strictSchema, fromStart = false, transformFns) {
|
|
217
|
+
if (!fromStart && Object.keys(this.schema.types).length > 0) {
|
|
218
|
+
return this.migrateSchema(strictSchema, transformFns);
|
|
219
|
+
}
|
|
220
|
+
const { lastId } = this.schema;
|
|
221
|
+
this.schema = {
|
|
222
|
+
lastId,
|
|
223
|
+
...strictSchema,
|
|
224
|
+
};
|
|
225
|
+
if (strictSchema.props) {
|
|
226
|
+
this.schema.types ??= {};
|
|
227
|
+
const props = { ...strictSchema.props };
|
|
228
|
+
for (const key in props) {
|
|
229
|
+
const prop = props[key];
|
|
230
|
+
const propType = getPropType(prop);
|
|
231
|
+
let refProp;
|
|
232
|
+
if (propType === 'reference') {
|
|
233
|
+
refProp = prop;
|
|
234
|
+
}
|
|
235
|
+
else if (propType === 'references') {
|
|
236
|
+
refProp = prop.items;
|
|
237
|
+
}
|
|
238
|
+
if (refProp) {
|
|
239
|
+
const type = this.schema.types[refProp.ref];
|
|
240
|
+
const inverseKey = '_' + key;
|
|
241
|
+
this.schema.types[refProp.ref] = {
|
|
242
|
+
...type,
|
|
243
|
+
props: {
|
|
244
|
+
...type.props,
|
|
245
|
+
[inverseKey]: {
|
|
246
|
+
items: {
|
|
247
|
+
ref: '_root',
|
|
248
|
+
prop: key,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
refProp.prop = inverseKey;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// @ts-ignore This creates an internal type to use for root props
|
|
257
|
+
this.schema.types._root = {
|
|
258
|
+
id: genRootId(),
|
|
259
|
+
props,
|
|
260
|
+
};
|
|
261
|
+
delete this.schema.props;
|
|
262
|
+
}
|
|
263
|
+
updateTypeDefs(this);
|
|
264
|
+
if (!fromStart) {
|
|
265
|
+
writeFile(join(this.fileSystemPath, SCHEMA_FILE), JSON.stringify(this.schema)).catch((err) => console.error(SCHEMA_FILE, err));
|
|
266
|
+
let types = Object.keys(this.schemaTypesParsed);
|
|
267
|
+
const s = schemaToSelvaBuffer(this.schemaTypesParsed);
|
|
268
|
+
for (let i = 0; i < s.length; i++) {
|
|
269
|
+
// TYPE SELVA user Uint8Array(6) [ 1, 17, 23, 0, 11, 0 ]
|
|
270
|
+
const type = this.schemaTypesParsed[types[i]];
|
|
271
|
+
// TODO should not crash!
|
|
272
|
+
try {
|
|
273
|
+
native.updateSchemaType(type.id, s[i], this.dbCtxExternal);
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
console.error('Cannot update schema on selva', type.type, err, s[i]);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (strictSchema.props) {
|
|
280
|
+
// insert a root node
|
|
281
|
+
const data = [2, 1, 0, 0, 0, 9, 1, 0, 0, 0, 7, 1, 0, 1];
|
|
282
|
+
const blockKey = makeCsmtKey(1, 0);
|
|
283
|
+
const buf = Buffer.alloc(data.length + 2 + 8 + 4);
|
|
284
|
+
// add content
|
|
285
|
+
buf.set(data);
|
|
286
|
+
// add typesLen
|
|
287
|
+
buf.writeDoubleLE(0, data.length);
|
|
288
|
+
// add dirty key
|
|
289
|
+
buf.writeDoubleLE(blockKey, data.length + 2);
|
|
290
|
+
// add dataLen
|
|
291
|
+
buf.writeUint32LE(data.length, buf.length - 4);
|
|
292
|
+
this.modify(buf);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
this.onSchemaChange?.(this.schema);
|
|
296
|
+
return this.schema;
|
|
297
|
+
}
|
|
298
|
+
modify(buf) {
|
|
299
|
+
const offsets = {};
|
|
300
|
+
const dataLen = buf.readUint32LE(buf.length - 4);
|
|
301
|
+
let typesSize = buf.readUint16LE(dataLen);
|
|
302
|
+
let i = dataLen + 2;
|
|
303
|
+
while (typesSize--) {
|
|
304
|
+
const typeId = buf.readUint16LE(i);
|
|
305
|
+
i += 2;
|
|
306
|
+
const startId = buf.readUint32LE(i);
|
|
307
|
+
const def = this.schemaTypesParsedById[typeId];
|
|
308
|
+
const offset = def.lastId - startId;
|
|
309
|
+
buf.writeUint32LE(offset, i);
|
|
310
|
+
i += 4;
|
|
311
|
+
const lastId = buf.readUint32LE(i);
|
|
312
|
+
i += 4;
|
|
313
|
+
def.lastId = lastId + offset;
|
|
314
|
+
offsets[typeId] = offset;
|
|
315
|
+
}
|
|
316
|
+
if (this.processingQueries) {
|
|
317
|
+
this.modifyQueue.push(Buffer.from(buf));
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
this.#modify(buf);
|
|
321
|
+
}
|
|
322
|
+
return offsets;
|
|
323
|
+
}
|
|
324
|
+
#modify(buf) {
|
|
325
|
+
const end = buf.length - 4;
|
|
326
|
+
const dataLen = buf.readUint32LE(end);
|
|
327
|
+
const typesSize = buf.readUint16LE(dataLen);
|
|
328
|
+
const typesLen = typesSize * 10;
|
|
329
|
+
const types = buf.subarray(dataLen + 2, dataLen + typesLen + 2);
|
|
330
|
+
const data = buf.subarray(0, dataLen);
|
|
331
|
+
let i = dataLen + 2 + typesLen;
|
|
332
|
+
while (i < end) {
|
|
333
|
+
const key = buf.readDoubleLE(i);
|
|
334
|
+
this.dirtyRanges.add(key);
|
|
335
|
+
i += 8;
|
|
336
|
+
}
|
|
337
|
+
native.modify(data, types, this.dbCtxExternal);
|
|
338
|
+
}
|
|
339
|
+
getQueryBuf(buf) {
|
|
340
|
+
if (this.modifyQueue.length) {
|
|
341
|
+
return new Promise((resolve) => {
|
|
342
|
+
this.queryQueue.set(resolve, buf);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
const queryType = buf[0];
|
|
347
|
+
if (queryType == 2) {
|
|
348
|
+
const s = 13 + buf.readUint16LE(11);
|
|
349
|
+
const sortLen = buf.readUint16LE(s);
|
|
350
|
+
if (sortLen) {
|
|
351
|
+
const typeId = buf.readUint16LE(1);
|
|
352
|
+
const sort = buf.slice(s + 2, s + 2 + sortLen);
|
|
353
|
+
const field = sort[1];
|
|
354
|
+
const start = sort.readUint16LE(2 + 1);
|
|
355
|
+
if (!this.hasSortIndex(typeId, field, start)) {
|
|
356
|
+
if (this.processingQueries) {
|
|
357
|
+
return new Promise((resolve) => {
|
|
358
|
+
this.queryQueue.set(resolve, buf);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
this.createSortIndexBuffer(typeId, field, start);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (queryType == 1) {
|
|
366
|
+
// This will be more advanced - sometimes has indexes / sometimes not
|
|
367
|
+
}
|
|
368
|
+
this.availableWorkerIndex =
|
|
369
|
+
(this.availableWorkerIndex + 1) % this.workers.length;
|
|
370
|
+
return this.workers[this.availableWorkerIndex].getQueryBuf(buf);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
onQueryEnd() {
|
|
374
|
+
this.processingQueries--;
|
|
375
|
+
if (this.processingQueries === 0) {
|
|
376
|
+
if (this.modifyQueue.length) {
|
|
377
|
+
for (const buf of this.modifyQueue) {
|
|
378
|
+
this.#modify(buf);
|
|
379
|
+
}
|
|
380
|
+
this.modifyQueue = [];
|
|
381
|
+
}
|
|
382
|
+
if (this.queryQueue.size) {
|
|
383
|
+
for (const [resolve, buf] of this.queryQueue) {
|
|
384
|
+
resolve(this.getQueryBuf(buf));
|
|
385
|
+
}
|
|
386
|
+
this.queryQueue.clear();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
async stop(noSave) {
|
|
391
|
+
if (this.stopped) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (!noSave) {
|
|
395
|
+
await this.save();
|
|
396
|
+
}
|
|
397
|
+
await Promise.all(this.workers.map(({ worker }) => worker.terminate()));
|
|
398
|
+
this.workers = [];
|
|
399
|
+
native.stop(this.dbCtxExternal);
|
|
400
|
+
await setTimeout();
|
|
401
|
+
}
|
|
402
|
+
async destroy() {
|
|
403
|
+
await this.stop(true);
|
|
404
|
+
await rm(this.fileSystemPath, { recursive: true }).catch((err) => console.warn('Error removing dump folder', err.message));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { StrictSchema } from '@based/schema';
|
|
2
|
+
import './worker.js';
|
|
3
|
+
import { DbServer } from '../index.js';
|
|
4
|
+
type TransformFn = (node: Record<string, any>) => Record<string, any> | [string, Record<string, any>];
|
|
5
|
+
export type TransformFns = Record<string, TransformFn>;
|
|
6
|
+
export declare const migrate: (fromDbServer: DbServer, toSchema: StrictSchema, transform?: TransformFns) => Promise<DbServer["schema"]>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { BasedDb } from '../../index.js';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
import { Worker, MessageChannel } from 'node:worker_threads';
|
|
5
|
+
import native from '../../native.js';
|
|
6
|
+
import './worker.js';
|
|
7
|
+
import { foreachDirtyBlock } from '../tree.js';
|
|
8
|
+
let migrationCnt = 0;
|
|
9
|
+
const parseTransform = (transform) => {
|
|
10
|
+
const res = {};
|
|
11
|
+
if (typeof transform === 'object' && transform !== null) {
|
|
12
|
+
for (const type in transform) {
|
|
13
|
+
const fn = transform[type];
|
|
14
|
+
if (typeof fn === 'function') {
|
|
15
|
+
let src = fn.toString();
|
|
16
|
+
const trimmedForCheckOnly = src.replace(/\s+/g, '');
|
|
17
|
+
if (trimmedForCheckOnly.startsWith(type + '(')) {
|
|
18
|
+
src = 'function ' + src;
|
|
19
|
+
}
|
|
20
|
+
res[type] = src;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return res;
|
|
25
|
+
};
|
|
26
|
+
export const migrate = async (fromDbServer, toSchema, transform) => {
|
|
27
|
+
const migrationId = migrationCnt++;
|
|
28
|
+
fromDbServer.migrating = migrationId;
|
|
29
|
+
const abort = () => fromDbServer.migrating !== migrationId;
|
|
30
|
+
const toDb = new BasedDb({
|
|
31
|
+
path: join(tmpdir(), (~~Math.random()).toString(36)),
|
|
32
|
+
});
|
|
33
|
+
await toDb.start({ clean: true });
|
|
34
|
+
if (abort()) {
|
|
35
|
+
await toDb.destroy();
|
|
36
|
+
return fromDbServer.schema;
|
|
37
|
+
}
|
|
38
|
+
toSchema = await toDb.putSchema(toSchema);
|
|
39
|
+
const fromSchema = fromDbServer.schema;
|
|
40
|
+
const fromCtx = fromDbServer.dbCtxExternal;
|
|
41
|
+
const toCtx = toDb.server.dbCtxExternal;
|
|
42
|
+
const { port1, port2 } = new MessageChannel();
|
|
43
|
+
const atomics = new Int32Array(new SharedArrayBuffer(4));
|
|
44
|
+
const fromAddress = native.intFromExternal(fromCtx);
|
|
45
|
+
const toAddress = native.intFromExternal(toCtx);
|
|
46
|
+
const transformFns = parseTransform(transform);
|
|
47
|
+
atomics[0] = 1;
|
|
48
|
+
const worker = new Worker('./dist/src/server/migrate/worker.js', {
|
|
49
|
+
workerData: {
|
|
50
|
+
from: fromAddress,
|
|
51
|
+
to: toAddress,
|
|
52
|
+
fromSchema,
|
|
53
|
+
toSchema,
|
|
54
|
+
channel: port2,
|
|
55
|
+
atomics,
|
|
56
|
+
transformFns,
|
|
57
|
+
},
|
|
58
|
+
transferList: [port2],
|
|
59
|
+
});
|
|
60
|
+
worker.on('error', console.error);
|
|
61
|
+
let i = 0;
|
|
62
|
+
let ranges = [];
|
|
63
|
+
fromDbServer.updateMerkleTree();
|
|
64
|
+
fromDbServer.dirtyRanges.clear();
|
|
65
|
+
fromDbServer.merkleTree.visitLeafNodes((leaf) => {
|
|
66
|
+
ranges.push(leaf.data);
|
|
67
|
+
});
|
|
68
|
+
await Atomics.waitAsync(atomics, 0, 1).value;
|
|
69
|
+
while (i < ranges.length) {
|
|
70
|
+
// block modifies
|
|
71
|
+
fromDbServer.processingQueries++;
|
|
72
|
+
const leafData = ranges[i++];
|
|
73
|
+
port1.postMessage(leafData);
|
|
74
|
+
// wake up the worker
|
|
75
|
+
atomics[0] = 1;
|
|
76
|
+
Atomics.notify(atomics, 0);
|
|
77
|
+
// wait until it's done
|
|
78
|
+
await Atomics.waitAsync(atomics, 0, 1).value;
|
|
79
|
+
// exec queued modifies
|
|
80
|
+
fromDbServer.onQueryEnd();
|
|
81
|
+
if (abort()) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
if (i === ranges.length && fromDbServer.dirtyRanges.size) {
|
|
85
|
+
ranges = [];
|
|
86
|
+
i = 0;
|
|
87
|
+
foreachDirtyBlock(fromDbServer, (_mtKey, typeId, start, end) => {
|
|
88
|
+
ranges.push({
|
|
89
|
+
typeId,
|
|
90
|
+
start,
|
|
91
|
+
end,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
fromDbServer.dirtyRanges.clear();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!abort()) {
|
|
98
|
+
fromDbServer.putSchema(toSchema, true);
|
|
99
|
+
fromDbServer.dbCtxExternal = toCtx;
|
|
100
|
+
toDb.server.dbCtxExternal = fromCtx;
|
|
101
|
+
}
|
|
102
|
+
const promises = fromDbServer.workers.map((worker) => worker.updateCtx(toAddress));
|
|
103
|
+
promises.push(toDb.destroy(), worker.terminate());
|
|
104
|
+
await Promise.all(promises);
|
|
105
|
+
fromDbServer.onSchemaChange?.(fromDbServer.schema);
|
|
106
|
+
return fromDbServer.schema;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { isMainThread, receiveMessageOnPort, workerData, } from 'node:worker_threads';
|
|
2
|
+
import native from '../../native.js';
|
|
3
|
+
import { BasedDb } from '../../index.js';
|
|
4
|
+
import { REFERENCE, REFERENCES } from '../schema/types.js';
|
|
5
|
+
if (isMainThread) {
|
|
6
|
+
console.warn('running worker.ts in mainthread');
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
const { from, to, fromSchema, toSchema, channel, atomics, transformFns } = workerData;
|
|
10
|
+
const fromCtx = native.externalFromInt(from);
|
|
11
|
+
const toCtx = native.externalFromInt(to);
|
|
12
|
+
const path = null;
|
|
13
|
+
const fromDb = new BasedDb({ path });
|
|
14
|
+
const toDb = new BasedDb({ path });
|
|
15
|
+
fromDb.server.dbCtxExternal = fromCtx;
|
|
16
|
+
toDb.server.dbCtxExternal = toCtx;
|
|
17
|
+
await fromDb.putSchema(fromSchema, true);
|
|
18
|
+
await toDb.putSchema(toSchema, true);
|
|
19
|
+
const map = {};
|
|
20
|
+
for (const type in fromDb.client.schemaTypesParsed) {
|
|
21
|
+
const { id, props } = fromDb.client.schemaTypesParsed[type];
|
|
22
|
+
const include = Object.keys(props);
|
|
23
|
+
let i = include.length;
|
|
24
|
+
while (i--) {
|
|
25
|
+
const path = include[i];
|
|
26
|
+
if (props[path].typeIndex === REFERENCE ||
|
|
27
|
+
props[path].typeIndex === REFERENCES) {
|
|
28
|
+
include[i] = `${path}.id`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
map[id] = { type, include };
|
|
32
|
+
}
|
|
33
|
+
for (const type in transformFns) {
|
|
34
|
+
const fnOrNull = transformFns[type];
|
|
35
|
+
transformFns[type] = eval(`(${fnOrNull})`);
|
|
36
|
+
}
|
|
37
|
+
while (true) {
|
|
38
|
+
let msg;
|
|
39
|
+
while ((msg = receiveMessageOnPort(channel))) {
|
|
40
|
+
const leafData = msg.message;
|
|
41
|
+
const { type, include } = map[leafData.typeId];
|
|
42
|
+
const typeTransformFn = transformFns[type];
|
|
43
|
+
if (typeTransformFn) {
|
|
44
|
+
const nodes = fromDb
|
|
45
|
+
.query(type)
|
|
46
|
+
.include(include)
|
|
47
|
+
.range(leafData.start - 1, leafData.end - leafData.start + 1)
|
|
48
|
+
._getSync(fromCtx);
|
|
49
|
+
for (const node of nodes) {
|
|
50
|
+
const res = typeTransformFn(node);
|
|
51
|
+
if (res === null) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(res)) {
|
|
55
|
+
toDb.create(res[0], res[1] || node, true);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
toDb.create(type, res || node, true);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else if (type in toDb.client.schemaTypesParsed) {
|
|
63
|
+
const nodes = fromDb
|
|
64
|
+
.query(type)
|
|
65
|
+
.include(include)
|
|
66
|
+
.range(leafData.start - 1, leafData.end - leafData.start + 1)
|
|
67
|
+
._getSync(fromCtx);
|
|
68
|
+
for (const node of nodes) {
|
|
69
|
+
toDb.create(type, node, true);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
await toDb.drain();
|
|
74
|
+
// await setTimeout()
|
|
75
|
+
// put it to sleep
|
|
76
|
+
atomics[0] = 0;
|
|
77
|
+
Atomics.notify(atomics, 0);
|
|
78
|
+
Atomics.wait(atomics, 0, 0);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import native from '../native.js';
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { destructureCsmtKey, foreachDirtyBlock } from './tree.js';
|
|
5
|
+
const WRITELOG_FILE = 'writelog.json';
|
|
6
|
+
const COMMON_SDB_FILE = 'common.sdb';
|
|
7
|
+
const block_sdb_file = (typeId, start, end) => `${typeId}_${start}_${end}.sdb`;
|
|
8
|
+
export async function save(db) {
|
|
9
|
+
let err;
|
|
10
|
+
const ts = Date.now();
|
|
11
|
+
err = native.saveCommon(join(db.fileSystemPath, COMMON_SDB_FILE), db.dbCtxExternal);
|
|
12
|
+
if (err) {
|
|
13
|
+
console.error(`Save common failed: ${err}`);
|
|
14
|
+
}
|
|
15
|
+
foreachDirtyBlock(db, (mtKey, typeId, start, end) => {
|
|
16
|
+
const file = block_sdb_file(typeId, start, end);
|
|
17
|
+
const path = join(db.fileSystemPath, file);
|
|
18
|
+
const hash = Buffer.allocUnsafe(16);
|
|
19
|
+
err = native.saveRange(path, typeId, start, end, db.dbCtxExternal, hash);
|
|
20
|
+
if (err) {
|
|
21
|
+
console.error(`Save ${typeId}:${start}-${end} failed: ${err}`);
|
|
22
|
+
return; // TODO What to do with the merkle tree in db situation?
|
|
23
|
+
}
|
|
24
|
+
const data = {
|
|
25
|
+
file,
|
|
26
|
+
typeId,
|
|
27
|
+
start,
|
|
28
|
+
end,
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
db.merkleTree.delete(mtKey);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
// console.error({ err })
|
|
35
|
+
}
|
|
36
|
+
db.merkleTree.insert(mtKey, hash, data);
|
|
37
|
+
});
|
|
38
|
+
db.dirtyRanges.clear();
|
|
39
|
+
const types = {};
|
|
40
|
+
for (const key in db.schemaTypesParsed) {
|
|
41
|
+
const def = db.schemaTypesParsed[key];
|
|
42
|
+
types[def.id] = { lastId: def.lastId, blockCapacity: def.blockCapacity };
|
|
43
|
+
}
|
|
44
|
+
const dumps = {};
|
|
45
|
+
for (const key in db.schemaTypesParsed) {
|
|
46
|
+
const def = db.schemaTypesParsed[key];
|
|
47
|
+
dumps[def.id] = [];
|
|
48
|
+
}
|
|
49
|
+
db.merkleTree.visitLeafNodes((leaf) => {
|
|
50
|
+
const [typeId] = destructureCsmtKey(leaf.key);
|
|
51
|
+
const data = leaf.data;
|
|
52
|
+
dumps[typeId].push({ ...data, hash: leaf.hash.toString('hex') });
|
|
53
|
+
});
|
|
54
|
+
const data = {
|
|
55
|
+
ts,
|
|
56
|
+
types,
|
|
57
|
+
commonDump: COMMON_SDB_FILE,
|
|
58
|
+
rangeDumps: dumps,
|
|
59
|
+
};
|
|
60
|
+
const mtRoot = db.merkleTree.getRoot();
|
|
61
|
+
if (mtRoot) {
|
|
62
|
+
data.hash = mtRoot.hash.toString('hex');
|
|
63
|
+
}
|
|
64
|
+
await writeFile(join(db.fileSystemPath, WRITELOG_FILE), JSON.stringify(data));
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=save.js.map
|