@based/db 0.0.30 → 0.0.32
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 +565 -3
- package/dist/lib/darwin_aarch64/include/selva/db.h +3 -2
- package/dist/lib/darwin_aarch64/include/selva/fields.h +10 -7
- package/dist/lib/darwin_aarch64/include/selva/types.h +3 -1
- 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.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/src/client/flushModify.d.ts +1 -1
- package/dist/src/client/flushModify.js +5 -4
- package/dist/src/client/index.d.ts +3 -2
- package/dist/src/client/modify/binary.js +1 -1
- package/dist/src/client/modify/cardinality.js +1 -1
- package/dist/src/client/modify/references/appendEdgeRefs.js +3 -0
- package/dist/src/client/modify/references/edge.js +6 -0
- package/dist/src/client/modify/references/getEdgeSize.js +1 -1
- package/dist/src/client/modify/string.js +10 -4
- package/dist/src/client/modify/text.js +1 -9
- package/dist/src/client/modify/types.d.ts +1 -0
- package/dist/src/client/modify/types.js +1 -0
- package/dist/src/client/modify/upsert.js +33 -21
- package/dist/src/client/query/BasedDbQuery.js +1 -1
- package/dist/src/client/query/BasedIterable.d.ts +2 -2
- package/dist/src/client/query/BasedIterable.js +7 -1
- package/dist/src/client/query/aggregates/aggregation.d.ts +4 -0
- package/dist/src/client/query/aggregates/aggregation.js +12 -0
- package/dist/src/client/query/aggregation.d.ts +1 -1
- package/dist/src/client/query/debug.js +3 -2
- package/dist/src/client/query/display.js +1 -1
- package/dist/src/client/query/filter/createFixedFilterBuffer.js +1 -1
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +1 -1
- package/dist/src/client/query/filter/parseFilterValue.js +1 -2
- package/dist/src/client/query/queryDef.js +2 -2
- package/dist/src/client/query/read/read.js +4 -14
- package/dist/src/client/query/registerQuery.js +1 -1
- package/dist/src/client/query/search/index.d.ts +1 -1
- package/dist/src/client/query/search/index.js +1 -1
- package/dist/src/client/query/sort.d.ts +1 -1
- package/dist/src/client/query/toBuffer.js +11 -15
- package/dist/src/client/query/types.d.ts +7 -0
- package/dist/src/client/query/types.js +8 -0
- package/dist/src/client/query/validation.d.ts +1 -1
- package/dist/src/client/query/validation.js +4 -5
- package/dist/src/client/string.js +1 -3
- package/dist/src/client/xxHash64.d.ts +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +31 -3
- package/dist/src/native.d.ts +1 -2
- package/dist/src/native.js +2 -5
- package/dist/src/server/csmt/draw-dot.d.ts +3 -1
- package/dist/src/server/csmt/draw-dot.js +7 -2
- package/dist/src/server/csmt/match.d.ts +1 -1
- package/dist/src/server/csmt/memebership-proof.d.ts +1 -1
- package/dist/src/server/csmt/tree-utils.d.ts +4 -4
- package/dist/src/server/csmt/tree.d.ts +1 -1
- package/dist/src/server/csmt/tree.js +1 -1
- package/dist/src/server/csmt/types.d.ts +10 -10
- package/dist/src/server/dbHash.d.ts +1 -1
- package/dist/src/server/dbHash.js +1 -1
- package/dist/src/server/index.d.ts +8 -4
- package/dist/src/server/index.js +28 -13
- package/dist/src/server/migrate/worker.js +11 -0
- package/dist/src/server/save.js +4 -6
- package/dist/src/server/start.js +17 -11
- package/dist/src/server/tree.d.ts +1 -1
- package/dist/src/server/tree.js +2 -2
- package/dist/src/utils.d.ts +0 -10
- package/dist/src/utils.js +0 -152
- package/package.json +3 -3
- package/dist/lib/darwin_aarch64/include/selva/xxhash64.h +0 -23
- package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
- package/dist/lib/linux_aarch64/include/cdefs.h +0 -317
- package/dist/lib/linux_aarch64/include/jemalloc.h +0 -468
- package/dist/lib/linux_aarch64/include/libdeflate.h +0 -322
- package/dist/lib/linux_aarch64/include/libdeflate_strings.h +0 -35
- package/dist/lib/linux_aarch64/include/linker_set.h +0 -109
- package/dist/lib/linux_aarch64/include/queue.h +0 -627
- package/dist/lib/linux_aarch64/include/selva/_export.h +0 -7
- package/dist/lib/linux_aarch64/include/selva/align.h +0 -9
- package/dist/lib/linux_aarch64/include/selva/backoff_timeout.h +0 -29
- package/dist/lib/linux_aarch64/include/selva/bitmap.h +0 -95
- package/dist/lib/linux_aarch64/include/selva/crc32c.h +0 -17
- package/dist/lib/linux_aarch64/include/selva/ctime.h +0 -135
- package/dist/lib/linux_aarch64/include/selva/db.h +0 -417
- package/dist/lib/linux_aarch64/include/selva/endian.h +0 -301
- package/dist/lib/linux_aarch64/include/selva/fast_linear_search.h +0 -23
- package/dist/lib/linux_aarch64/include/selva/fast_memcmp.h +0 -18
- package/dist/lib/linux_aarch64/include/selva/fast_memmem.h +0 -11
- package/dist/lib/linux_aarch64/include/selva/fast_parsei.h +0 -36
- package/dist/lib/linux_aarch64/include/selva/fields.h +0 -378
- package/dist/lib/linux_aarch64/include/selva/find.h +0 -47
- package/dist/lib/linux_aarch64/include/selva/history.h +0 -64
- package/dist/lib/linux_aarch64/include/selva/hll.h +0 -81
- package/dist/lib/linux_aarch64/include/selva/lpf.h +0 -28
- package/dist/lib/linux_aarch64/include/selva/node_id_set.h +0 -43
- package/dist/lib/linux_aarch64/include/selva/poptop.h +0 -114
- package/dist/lib/linux_aarch64/include/selva/queue_r.h +0 -190
- package/dist/lib/linux_aarch64/include/selva/selva_hash128.h +0 -49
- package/dist/lib/linux_aarch64/include/selva/selva_lang.h +0 -105
- package/dist/lib/linux_aarch64/include/selva/selva_math.h +0 -37
- package/dist/lib/linux_aarch64/include/selva/selva_string.h +0 -674
- package/dist/lib/linux_aarch64/include/selva/sort.h +0 -140
- package/dist/lib/linux_aarch64/include/selva/strsearch.h +0 -43
- package/dist/lib/linux_aarch64/include/selva/timestamp.h +0 -25
- package/dist/lib/linux_aarch64/include/selva/traverse.h +0 -65
- package/dist/lib/linux_aarch64/include/selva/types.h +0 -104
- package/dist/lib/linux_aarch64/include/selva/vector.h +0 -35
- package/dist/lib/linux_aarch64/include/selva/worker_ctx.h +0 -13
- package/dist/lib/linux_aarch64/include/selva/xxhash64.h +0 -23
- package/dist/lib/linux_aarch64/include/selva_error.h +0 -137
- package/dist/lib/linux_aarch64/include/selva_lang_code.h +0 -157
- package/dist/lib/linux_aarch64/include/tree.h +0 -852
- 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.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so.0 +0 -0
- package/dist/lib/linux_x86_64/include/cdefs.h +0 -317
- package/dist/lib/linux_x86_64/include/jemalloc.h +0 -468
- package/dist/lib/linux_x86_64/include/libdeflate.h +0 -322
- package/dist/lib/linux_x86_64/include/libdeflate_strings.h +0 -35
- package/dist/lib/linux_x86_64/include/linker_set.h +0 -109
- package/dist/lib/linux_x86_64/include/queue.h +0 -627
- package/dist/lib/linux_x86_64/include/selva/_export.h +0 -7
- package/dist/lib/linux_x86_64/include/selva/align.h +0 -9
- package/dist/lib/linux_x86_64/include/selva/backoff_timeout.h +0 -29
- package/dist/lib/linux_x86_64/include/selva/bitmap.h +0 -95
- package/dist/lib/linux_x86_64/include/selva/crc32c.h +0 -17
- package/dist/lib/linux_x86_64/include/selva/ctime.h +0 -135
- package/dist/lib/linux_x86_64/include/selva/db.h +0 -417
- package/dist/lib/linux_x86_64/include/selva/endian.h +0 -301
- package/dist/lib/linux_x86_64/include/selva/fast_linear_search.h +0 -23
- package/dist/lib/linux_x86_64/include/selva/fast_memcmp.h +0 -18
- package/dist/lib/linux_x86_64/include/selva/fast_memmem.h +0 -11
- package/dist/lib/linux_x86_64/include/selva/fast_parsei.h +0 -36
- package/dist/lib/linux_x86_64/include/selva/fields.h +0 -378
- package/dist/lib/linux_x86_64/include/selva/find.h +0 -47
- package/dist/lib/linux_x86_64/include/selva/history.h +0 -64
- package/dist/lib/linux_x86_64/include/selva/hll.h +0 -81
- package/dist/lib/linux_x86_64/include/selva/lpf.h +0 -28
- package/dist/lib/linux_x86_64/include/selva/node_id_set.h +0 -43
- package/dist/lib/linux_x86_64/include/selva/poptop.h +0 -114
- package/dist/lib/linux_x86_64/include/selva/queue_r.h +0 -190
- package/dist/lib/linux_x86_64/include/selva/selva_hash128.h +0 -49
- package/dist/lib/linux_x86_64/include/selva/selva_lang.h +0 -105
- package/dist/lib/linux_x86_64/include/selva/selva_math.h +0 -37
- package/dist/lib/linux_x86_64/include/selva/selva_string.h +0 -674
- package/dist/lib/linux_x86_64/include/selva/sort.h +0 -140
- package/dist/lib/linux_x86_64/include/selva/strsearch.h +0 -43
- package/dist/lib/linux_x86_64/include/selva/timestamp.h +0 -25
- package/dist/lib/linux_x86_64/include/selva/traverse.h +0 -65
- package/dist/lib/linux_x86_64/include/selva/types.h +0 -104
- package/dist/lib/linux_x86_64/include/selva/vector.h +0 -35
- package/dist/lib/linux_x86_64/include/selva/worker_ctx.h +0 -13
- package/dist/lib/linux_x86_64/include/selva/xxhash64.h +0 -23
- package/dist/lib/linux_x86_64/include/selva_error.h +0 -137
- package/dist/lib/linux_x86_64/include/selva_lang_code.h +0 -157
- package/dist/lib/linux_x86_64/include/tree.h +0 -852
- 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.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so.0 +0 -0
- package/dist/src/client/query/subscription/markers.d.ts +0 -10
- package/dist/src/client/query/subscription/markers.js +0 -213
- package/dist/src/client/query/subscription/run.d.ts +0 -5
- package/dist/src/client/query/subscription/run.js +0 -76
|
@@ -31,7 +31,7 @@ export const ERR_SORT_LANG = 24;
|
|
|
31
31
|
const messages = {
|
|
32
32
|
[ERR_TARGET_INVAL_TYPE]: (p) => `Type "${p}" does not exist`,
|
|
33
33
|
[ERR_TARGET_INVAL_ALIAS]: (p) => {
|
|
34
|
-
return `Invalid alias
|
|
34
|
+
return `Invalid alias provided to query\n ${picocolors.italic(safeStringify(p, 100))}`;
|
|
35
35
|
},
|
|
36
36
|
[ERR_TARGET_EXCEED_MAX_IDS]: (p) => `Exceeds max ids ${~~(p.length / 1e3)}k (max ${MAX_IDS_PER_QUERY / 1e3}k)`,
|
|
37
37
|
[ERR_TARGET_INVAL_IDS]: (p) => `Ids should be of type array or Uint32Array with valid ids \n ${picocolors.italic(safeStringify(p, 100))}`,
|
|
@@ -305,18 +305,18 @@ export const validateSort = (def, field, orderInput) => {
|
|
|
305
305
|
lang,
|
|
306
306
|
};
|
|
307
307
|
};
|
|
308
|
-
export const validateAlias = (alias, path
|
|
308
|
+
export const validateAlias = (def, alias, path) => {
|
|
309
309
|
const schema = def.schema;
|
|
310
310
|
for (const k in alias) {
|
|
311
311
|
if (typeof alias[k] === 'string') {
|
|
312
|
-
const p = path
|
|
312
|
+
const p = path ? `${path}.${k}` : k;
|
|
313
313
|
const prop = schema.props[p];
|
|
314
314
|
if (prop.typeIndex === ALIAS) {
|
|
315
315
|
return { def: prop, value: alias[k] };
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
else if (typeof alias[k] === 'object') {
|
|
319
|
-
const propDef = validateAlias(alias[k],
|
|
319
|
+
const propDef = validateAlias(def, alias[k], path ? `${path}.${k}` : k);
|
|
320
320
|
if (propDef) {
|
|
321
321
|
return propDef;
|
|
322
322
|
}
|
|
@@ -438,7 +438,6 @@ export const EMPTY_SCHEMA_DEF = {
|
|
|
438
438
|
...createEmptyDef('_error', { props: {} }, {}),
|
|
439
439
|
buf: new Uint8Array([]),
|
|
440
440
|
propNames: new Uint8Array([]),
|
|
441
|
-
packed: new Uint8Array([]),
|
|
442
441
|
idUint8: new Uint8Array([0, 0]),
|
|
443
442
|
mainEmptyAllZeroes: true,
|
|
444
443
|
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import native from '../native.js';
|
|
2
|
-
import { readUint32 } from '
|
|
3
|
-
import makeTmpBuffer from './tmpBuffer.js';
|
|
4
|
-
import { DECODER, ENCODER } from '../utils.js';
|
|
2
|
+
import { readUint32, makeTmpBuffer, DECODER, ENCODER } from '@saulx/utils';
|
|
5
3
|
const { getUint8Array: getTmpBuffer } = makeTmpBuffer(4096); // the usual page size?
|
|
6
4
|
export const COMPRESSED = 1;
|
|
7
5
|
export const NOT_COMPRESSED = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const xxHash64: (buf: Uint8Array, target?: Uint8Array, index?: number) => Uint8Array
|
|
1
|
+
export declare const xxHash64: (buf: Uint8Array, target?: Uint8Array, index?: number) => Uint8Array<ArrayBufferLike>;
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { DbServer } from './server/index.js';
|
|
|
4
4
|
import { DbClient } from './client/index.js';
|
|
5
5
|
import { wait } from '@saulx/utils';
|
|
6
6
|
import { debugMode, debugServer } from './utils.js';
|
|
7
|
+
import { BasedQueryResponse } from './client/query/BasedIterable.js';
|
|
7
8
|
export * from './client/modify/modify.js';
|
|
8
9
|
export { compress, decompress };
|
|
9
10
|
export { ModifyCtx }; // TODO move this somewhere
|
|
@@ -31,12 +32,13 @@ export class BasedDb {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
|
-
#init({ path, maxModifySize }) {
|
|
35
|
+
#init({ path, maxModifySize, saveIntervalInSeconds, }) {
|
|
35
36
|
this.fileSystemPath = path;
|
|
36
37
|
this.maxModifySize = maxModifySize;
|
|
37
38
|
const server = new DbServer({
|
|
38
39
|
path,
|
|
39
40
|
maxModifySize,
|
|
41
|
+
saveIntervalInSeconds,
|
|
40
42
|
onSchemaChange(schema) {
|
|
41
43
|
client.putLocalSchema(schema);
|
|
42
44
|
},
|
|
@@ -45,16 +47,42 @@ export class BasedDb {
|
|
|
45
47
|
maxModifySize,
|
|
46
48
|
hooks: {
|
|
47
49
|
subscribe(q, onData, onError) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
let timer;
|
|
51
|
+
let prevChecksum;
|
|
52
|
+
let lastLen = 0;
|
|
53
|
+
let response;
|
|
54
|
+
const get = async () => {
|
|
55
|
+
const res = await server.getQueryBuf(q.buffer);
|
|
56
|
+
if (!response) {
|
|
57
|
+
response = new BasedQueryResponse(q.id, q.def, res, 0);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
response.result = res;
|
|
61
|
+
response.end = res.byteLength;
|
|
62
|
+
}
|
|
63
|
+
const checksum = response.checksum;
|
|
64
|
+
if (lastLen != res.byteLength || checksum != prevChecksum) {
|
|
65
|
+
onData(response);
|
|
66
|
+
lastLen = res.byteLength;
|
|
67
|
+
prevChecksum = checksum;
|
|
68
|
+
}
|
|
69
|
+
setTimeout(get, 200);
|
|
70
|
+
};
|
|
71
|
+
get();
|
|
72
|
+
return () => {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
};
|
|
50
75
|
},
|
|
51
76
|
setSchema(schema, fromStart) {
|
|
52
77
|
return Promise.resolve(server.setSchema(schema, fromStart));
|
|
53
78
|
},
|
|
54
79
|
flushModify(buf) {
|
|
80
|
+
const d = performance.now();
|
|
55
81
|
const offsets = server.modify(buf);
|
|
82
|
+
const dbWriteTime = performance.now() - d;
|
|
56
83
|
return Promise.resolve({
|
|
57
84
|
offsets,
|
|
85
|
+
dbWriteTime,
|
|
58
86
|
});
|
|
59
87
|
},
|
|
60
88
|
getQueryBuf(buf) {
|
package/dist/src/native.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare const native: {
|
|
|
6
6
|
intFromExternal(external: any): BigInt;
|
|
7
7
|
modify: (data: Uint8Array, types: Uint8Array, dbCtx: any, dirtyBlocksOut: Float64Array) => any;
|
|
8
8
|
getQueryBuf: (q: Uint8Array, dbCtx: any) => ArrayBuffer | null;
|
|
9
|
-
start: (
|
|
9
|
+
start: () => any;
|
|
10
10
|
stop: (dbCtx: any) => any;
|
|
11
11
|
saveCommon: (path: string, dbCtx: any) => number;
|
|
12
12
|
saveRange: (path: string, typeCode: number, start: number, end: number, dbCtx: any, hashOut: Uint8Array) => number;
|
|
@@ -22,6 +22,5 @@ declare const native: {
|
|
|
22
22
|
destroySortIndex: (buf: Uint8Array, dbCtx: any) => any;
|
|
23
23
|
xxHash64: (buf: Uint8Array, target: Uint8Array, index: number) => any;
|
|
24
24
|
equals: (a: Uint8Array, b: Uint8Array) => boolean;
|
|
25
|
-
expire: (dbCtx: any) => void;
|
|
26
25
|
};
|
|
27
26
|
export default native;
|
package/dist/src/native.js
CHANGED
|
@@ -35,8 +35,8 @@ const native = {
|
|
|
35
35
|
const x = db.getQueryBuf(dbCtx, q);
|
|
36
36
|
return x;
|
|
37
37
|
},
|
|
38
|
-
start: (
|
|
39
|
-
return db.start(
|
|
38
|
+
start: () => {
|
|
39
|
+
return db.start();
|
|
40
40
|
},
|
|
41
41
|
stop: (dbCtx) => {
|
|
42
42
|
return db.stop(dbCtx);
|
|
@@ -93,9 +93,6 @@ const native = {
|
|
|
93
93
|
equals: (a, b) => {
|
|
94
94
|
return !!db.equals(a, b);
|
|
95
95
|
},
|
|
96
|
-
expire: (dbCtx) => {
|
|
97
|
-
db.expire(dbCtx);
|
|
98
|
-
},
|
|
99
96
|
};
|
|
100
97
|
global.__basedDb__native__ = native;
|
|
101
98
|
export default native;
|
|
@@ -2,7 +2,12 @@ import { encodeBase64 } from '@saulx/utils';
|
|
|
2
2
|
function makeLabel(node) {
|
|
3
3
|
return `${node.key}\n${encodeBase64(node.hash).substring(0, 5)}`;
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
function wrapFormatter(dataFormatter, node) {
|
|
6
|
+
return `\n${dataFormatter(node.data).replace('"', '\\"')}`;
|
|
7
|
+
}
|
|
8
|
+
// This can be visualized with Graphviz dot.
|
|
9
|
+
// Online: https://dreampuf.github.io/GraphvizOnline/?engine=dot
|
|
10
|
+
export default function draw(csmt, dataFormatter) {
|
|
6
11
|
const root = csmt.getRoot();
|
|
7
12
|
const lines = [];
|
|
8
13
|
const nodes = [];
|
|
@@ -12,7 +17,7 @@ export default function draw(csmt) {
|
|
|
12
17
|
const left = node.left;
|
|
13
18
|
const right = node.right;
|
|
14
19
|
const isLeaf = !left && !right;
|
|
15
|
-
nodes.push(`n${cur} [label="${makeLabel(node)}"${isLeaf ? ' shape=box' : ''}];`);
|
|
20
|
+
nodes.push(`n${cur} [label="${makeLabel(node) + ((dataFormatter && node.data) ? wrapFormatter(dataFormatter, node) : '')}"${isLeaf ? ' shape=box' : ''}];`);
|
|
16
21
|
if (cur > 0) {
|
|
17
22
|
lines.push(`n${prev} -- n${cur}`);
|
|
18
23
|
}
|
|
@@ -4,4 +4,4 @@ export declare enum Direction {
|
|
|
4
4
|
Right = "R"
|
|
5
5
|
}
|
|
6
6
|
export type Proof = [TreeKey | null, TreeKey | null] | [TreeKey | Uint8Array, TreeKey | Direction][];
|
|
7
|
-
export default function membershipProof(root: TreeNode | null, k: TreeKey): Proof;
|
|
7
|
+
export default function membershipProof<T = any>(root: TreeNode<T> | null, k: TreeKey): Proof;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TreeKey, TreeNode } from './types.js';
|
|
2
2
|
export declare function distance(x: TreeKey, y: TreeKey): TreeKey;
|
|
3
|
-
export declare function min(x: TreeNode | null, y: TreeNode | null):
|
|
4
|
-
export declare function max(x: TreeNode | null, y: TreeNode | null):
|
|
5
|
-
export declare function minInSubtree(node: TreeNode): TreeKey;
|
|
6
|
-
export declare function maxInSubtree(node: TreeNode): TreeKey;
|
|
3
|
+
export declare function min(x: TreeNode<any> | null, y: TreeNode<any> | null): TreeKey;
|
|
4
|
+
export declare function max(x: TreeNode<any> | null, y: TreeNode<any> | null): TreeKey;
|
|
5
|
+
export declare function minInSubtree(node: TreeNode<any>): TreeKey;
|
|
6
|
+
export declare function maxInSubtree(node: TreeNode<any>): TreeKey;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TreeKeyNil } from './types.js';
|
|
2
2
|
import { distance, min, max } from './tree-utils.js';
|
|
3
3
|
import membershipProof from './memebership-proof.js';
|
|
4
|
-
import { equals } from '
|
|
4
|
+
import { equals } from '@saulx/utils';
|
|
5
5
|
export function hashEq(a, b) {
|
|
6
6
|
return equals(a, b);
|
|
7
7
|
}
|
|
@@ -2,24 +2,24 @@ import { Proof } from './memebership-proof.js';
|
|
|
2
2
|
export type TreeKey = number;
|
|
3
3
|
export declare const TreeKeyNil = 0;
|
|
4
4
|
export type Hash = Uint8Array;
|
|
5
|
-
export interface TreeNode {
|
|
5
|
+
export interface TreeNode<T> {
|
|
6
6
|
hash: Hash;
|
|
7
|
-
key: TreeKey;
|
|
8
|
-
data?:
|
|
9
|
-
left: TreeNode | null;
|
|
10
|
-
right: TreeNode | null;
|
|
7
|
+
key: TreeKey | null;
|
|
8
|
+
data?: T | null;
|
|
9
|
+
left: TreeNode<T> | null;
|
|
10
|
+
right: TreeNode<T> | null;
|
|
11
11
|
}
|
|
12
12
|
export type KeyHashPair = [TreeKey, Hash];
|
|
13
13
|
export interface TreeDiff {
|
|
14
14
|
left: KeyHashPair[];
|
|
15
15
|
right: KeyHashPair[];
|
|
16
16
|
}
|
|
17
|
-
export interface Csmt {
|
|
17
|
+
export interface Csmt<T> {
|
|
18
18
|
emptyHash: Uint8Array;
|
|
19
19
|
/**
|
|
20
20
|
* Get the root node.
|
|
21
21
|
*/
|
|
22
|
-
getRoot: () => TreeNode | null;
|
|
22
|
+
getRoot: () => TreeNode<T> | null;
|
|
23
23
|
/**
|
|
24
24
|
* Insert a new key-hash pair.
|
|
25
25
|
*/
|
|
@@ -35,12 +35,12 @@ export interface Csmt {
|
|
|
35
35
|
/**
|
|
36
36
|
* Compute the diff between this and a given tree.
|
|
37
37
|
*/
|
|
38
|
-
diff: (tree: Csmt) => TreeDiff;
|
|
38
|
+
diff: (tree: Csmt<T>) => TreeDiff;
|
|
39
39
|
/**
|
|
40
40
|
* Provide a proof of membership if a key exist in the three;
|
|
41
41
|
* Otherwise a proof of non-membership is returned.
|
|
42
42
|
*/
|
|
43
43
|
membershipProof: (k: TreeKey) => Proof;
|
|
44
|
-
visitLeafNodes: (cb: (leaf: TreeNode) => void) => void;
|
|
45
|
-
search: (k: TreeKey) => TreeNode
|
|
44
|
+
visitLeafNodes: (cb: (leaf: TreeNode<T>) => void) => void;
|
|
45
|
+
search: (k: TreeKey) => TreeNode<T>;
|
|
46
46
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LangName, StrictSchema } from '@based/schema';
|
|
2
2
|
import { SchemaTypesParsed, SchemaTypesParsedById } from '@based/schema/def';
|
|
3
3
|
import { createTree } from './csmt/index.js';
|
|
4
|
+
import { CsmtNodeRange } from './tree.js';
|
|
4
5
|
import { Worker, MessagePort } from 'node:worker_threads';
|
|
5
6
|
import { TransformFns } from './migrate/index.js';
|
|
6
7
|
import exitHook from 'exit-hook';
|
|
@@ -35,10 +36,10 @@ export declare class DbServer {
|
|
|
35
36
|
schemaTypesParsedById: SchemaTypesParsedById;
|
|
36
37
|
fileSystemPath: string;
|
|
37
38
|
maxModifySize: number;
|
|
38
|
-
merkleTree: ReturnType<typeof createTree
|
|
39
|
+
merkleTree: ReturnType<typeof createTree<CsmtNodeRange>>;
|
|
39
40
|
dirtyRanges: Set<number>;
|
|
40
41
|
csmtHashFun: {
|
|
41
|
-
update: (buf: Uint8Array) => any;
|
|
42
|
+
update: (buf: Uint8Array) => /*elided*/ any;
|
|
42
43
|
digest: (encoding?: "hex") => Uint8Array | string;
|
|
43
44
|
reset: () => void;
|
|
44
45
|
};
|
|
@@ -50,11 +51,14 @@ export declare class DbServer {
|
|
|
50
51
|
stopped: boolean;
|
|
51
52
|
onSchemaChange: OnSchemaChange;
|
|
52
53
|
unlistenExit: ReturnType<typeof exitHook>;
|
|
53
|
-
|
|
54
|
+
saveIntervalInSeconds?: number;
|
|
55
|
+
saveInterval?: NodeJS.Timeout;
|
|
56
|
+
constructor({ path, maxModifySize, onSchemaChange, debug, saveIntervalInSeconds, }: {
|
|
54
57
|
path: string;
|
|
55
58
|
maxModifySize?: number;
|
|
56
59
|
onSchemaChange?: OnSchemaChange;
|
|
57
60
|
debug?: boolean;
|
|
61
|
+
saveIntervalInSeconds?: number;
|
|
58
62
|
});
|
|
59
63
|
start(opts?: {
|
|
60
64
|
clean?: boolean;
|
|
@@ -64,7 +68,7 @@ export declare class DbServer {
|
|
|
64
68
|
forceFullDump?: boolean;
|
|
65
69
|
}): Promise<void>;
|
|
66
70
|
createCsmtHashFun: () => {
|
|
67
|
-
update: (buf: Uint8Array) => any;
|
|
71
|
+
update: (buf: Uint8Array) => /*elided*/ any;
|
|
68
72
|
digest: (encoding?: "hex") => Uint8Array | string;
|
|
69
73
|
reset: () => void;
|
|
70
74
|
};
|
package/dist/src/server/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname, join } from 'node:path';
|
|
|
5
5
|
import { getPropType, langCodesMap, } from '@based/schema';
|
|
6
6
|
import { updateTypeDefs, schemaToSelvaBuffer, } from '@based/schema/def';
|
|
7
7
|
import { start } from './start.js';
|
|
8
|
-
import { initCsmt, makeCsmtKey, makeCsmtKeyFromNodeId } from './tree.js';
|
|
8
|
+
import { initCsmt, makeCsmtKey, makeCsmtKeyFromNodeId, } from './tree.js';
|
|
9
9
|
import { save } from './save.js';
|
|
10
10
|
import { Worker, MessageChannel } from 'node:worker_threads';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
@@ -17,6 +17,7 @@ export const WRITELOG_FILE = 'writelog.json';
|
|
|
17
17
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
18
|
const __dirname = dirname(__filename);
|
|
19
19
|
const workerPath = join(__dirname, 'worker.js');
|
|
20
|
+
const emptyUint8Array = new Uint8Array(0);
|
|
20
21
|
class SortIndex {
|
|
21
22
|
constructor(buf, dbCtxExternal) {
|
|
22
23
|
this.buf = buf;
|
|
@@ -89,11 +90,14 @@ export class DbServer {
|
|
|
89
90
|
stopped;
|
|
90
91
|
onSchemaChange;
|
|
91
92
|
unlistenExit;
|
|
92
|
-
|
|
93
|
+
saveIntervalInSeconds;
|
|
94
|
+
saveInterval;
|
|
95
|
+
constructor({ path, maxModifySize = 100 * 1e3 * 1e3, onSchemaChange, debug, saveIntervalInSeconds, }) {
|
|
93
96
|
this.maxModifySize = maxModifySize;
|
|
94
97
|
this.fileSystemPath = path;
|
|
95
98
|
this.sortIndexes = {};
|
|
96
99
|
this.onSchemaChange = onSchemaChange;
|
|
100
|
+
this.saveIntervalInSeconds = saveIntervalInSeconds;
|
|
97
101
|
if (debug) {
|
|
98
102
|
debugServer(this);
|
|
99
103
|
}
|
|
@@ -380,12 +384,6 @@ export class DbServer {
|
|
|
380
384
|
const def = this.schemaTypesParsedById[typeId];
|
|
381
385
|
let offset = def.lastId - startId;
|
|
382
386
|
if (offset < 0) {
|
|
383
|
-
console.log('-----------------');
|
|
384
|
-
console.log(def.type, {
|
|
385
|
-
offset,
|
|
386
|
-
serverId: def.lastId,
|
|
387
|
-
clientId: startId,
|
|
388
|
-
});
|
|
389
387
|
offset = 0;
|
|
390
388
|
}
|
|
391
389
|
buf[i++] = offset;
|
|
@@ -397,7 +395,6 @@ export class DbServer {
|
|
|
397
395
|
def.lastId = lastId + offset;
|
|
398
396
|
offsets[typeId] = offset;
|
|
399
397
|
}
|
|
400
|
-
// console.log('modify', this.processingQueries)
|
|
401
398
|
if (this.processingQueries) {
|
|
402
399
|
this.modifyQueue.push(new Uint8Array(buf));
|
|
403
400
|
}
|
|
@@ -424,7 +421,8 @@ export class DbServer {
|
|
|
424
421
|
const view = new DataView(buf.buffer, buf.byteOffset);
|
|
425
422
|
while (i < end) {
|
|
426
423
|
const key = view.getFloat64(i, true);
|
|
427
|
-
|
|
424
|
+
// These node ranges may not actually exist
|
|
425
|
+
//this.dirtyRanges.add(key)
|
|
428
426
|
i += 8;
|
|
429
427
|
}
|
|
430
428
|
this.#resizeModifyDirtyRanges();
|
|
@@ -436,6 +434,16 @@ export class DbServer {
|
|
|
436
434
|
this.dirtyRanges.add(key);
|
|
437
435
|
}
|
|
438
436
|
}
|
|
437
|
+
#expire() {
|
|
438
|
+
this.#resizeModifyDirtyRanges();
|
|
439
|
+
native.modify(emptyUint8Array, emptyUint8Array, this.dbCtxExternal, this.modifyDirtyRanges);
|
|
440
|
+
for (let key of this.modifyDirtyRanges) {
|
|
441
|
+
if (key === 0) {
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
this.dirtyRanges.add(key);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
439
447
|
addToQueryQueue(resolve, buf) {
|
|
440
448
|
if (this.queryQueue.size === 16777216) {
|
|
441
449
|
resolve(new Error('Query queue exceeded'));
|
|
@@ -477,7 +485,7 @@ export class DbServer {
|
|
|
477
485
|
// This will be more advanced - sometimes has indexes / sometimes not
|
|
478
486
|
}
|
|
479
487
|
if (!fromQueue) {
|
|
480
|
-
|
|
488
|
+
this.#expire();
|
|
481
489
|
}
|
|
482
490
|
this.availableWorkerIndex =
|
|
483
491
|
(this.availableWorkerIndex + 1) % this.workers.length;
|
|
@@ -497,7 +505,7 @@ export class DbServer {
|
|
|
497
505
|
if (this.queryQueue.size) {
|
|
498
506
|
const queryQueue = this.queryQueue;
|
|
499
507
|
this.queryQueue = new Map();
|
|
500
|
-
|
|
508
|
+
this.#expire();
|
|
501
509
|
for (const [resolve, buf] of queryQueue) {
|
|
502
510
|
resolve(this.getQueryBuf(buf, true));
|
|
503
511
|
}
|
|
@@ -509,8 +517,15 @@ export class DbServer {
|
|
|
509
517
|
return;
|
|
510
518
|
}
|
|
511
519
|
this.stopped = true;
|
|
512
|
-
clearTimeout(this.cleanupTimer);
|
|
513
520
|
this.unlistenExit();
|
|
521
|
+
if (this.cleanupTimer) {
|
|
522
|
+
clearTimeout(this.cleanupTimer);
|
|
523
|
+
this.cleanupTimer = null;
|
|
524
|
+
}
|
|
525
|
+
if (this.saveInterval) {
|
|
526
|
+
clearInterval(this.saveInterval);
|
|
527
|
+
this.saveInterval = null;
|
|
528
|
+
}
|
|
514
529
|
try {
|
|
515
530
|
if (!noSave) {
|
|
516
531
|
await this.save();
|
|
@@ -48,6 +48,17 @@ else {
|
|
|
48
48
|
if (props[path].typeIndex === REFERENCE ||
|
|
49
49
|
props[path].typeIndex === REFERENCES) {
|
|
50
50
|
include[i] = `${path}.id`;
|
|
51
|
+
if (props[path].edges) {
|
|
52
|
+
for (const key in props[path].edges) {
|
|
53
|
+
const prop = props[path].edges[key];
|
|
54
|
+
if (prop.typeIndex === REFERENCE || prop.typeIndex === REFERENCES) {
|
|
55
|
+
include.push(`${path}.${key}.id`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
include.push(`${path}.${key}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
map[id] = { type, include };
|
package/dist/src/server/save.js
CHANGED
|
@@ -5,7 +5,7 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { destructureCsmtKey, foreachBlock, foreachDirtyBlock, initCsmt, makeCsmtKey, specialBlock, } from './tree.js';
|
|
6
6
|
import { WRITELOG_FILE } from './index.js';
|
|
7
7
|
import { writeFileSync } from 'node:fs';
|
|
8
|
-
import { bufToHex } from '
|
|
8
|
+
import { bufToHex } from '@saulx/utils';
|
|
9
9
|
const COMMON_SDB_FILE = 'common.sdb';
|
|
10
10
|
const block_sdb_file = (typeId, start, end) => `${typeId}_${start}_${end}.sdb`;
|
|
11
11
|
function saveRange(db, typeId, start, end, hashOut) {
|
|
@@ -14,7 +14,7 @@ function saveRange(db, typeId, start, end, hashOut) {
|
|
|
14
14
|
const err = native.saveRange(path, typeId, start, end, db.dbCtxExternal, hashOut);
|
|
15
15
|
if (err == -8) {
|
|
16
16
|
// TODO ENOENT
|
|
17
|
-
return '';
|
|
17
|
+
return ''; // empty range
|
|
18
18
|
}
|
|
19
19
|
else if (err) {
|
|
20
20
|
// TODO print the error string
|
|
@@ -61,18 +61,16 @@ export function save(db, sync = false, forceFullDump = false) {
|
|
|
61
61
|
else {
|
|
62
62
|
foreachDirtyBlock(db, (mtKey, typeId, start, end) => {
|
|
63
63
|
const hash = new Uint8Array(16);
|
|
64
|
-
// TODO Don't save if empty
|
|
65
64
|
const file = saveRange(db, typeId, start, end, hash);
|
|
66
65
|
if (file === null) {
|
|
67
66
|
// The previous state should remain in the merkle tree for
|
|
68
67
|
// load and sync purposes.
|
|
69
68
|
return;
|
|
70
69
|
}
|
|
71
|
-
else if (file.length === 0) {
|
|
72
|
-
// The range is empty
|
|
73
|
-
}
|
|
74
70
|
else {
|
|
75
71
|
const oldLeaf = db.merkleTree.search(mtKey);
|
|
72
|
+
// If (file.length === 0) then the range is empty but that's fine,
|
|
73
|
+
// we'll keep them around for now to maintain the order of the tree.
|
|
76
74
|
if (oldLeaf) {
|
|
77
75
|
oldLeaf.data.file = file;
|
|
78
76
|
db.merkleTree.update(mtKey, hash);
|
package/dist/src/server/start.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { stringHash } from '@saulx/hash';
|
|
2
1
|
import { DbWorker, SCHEMA_FILE, WRITELOG_FILE } from './index.js';
|
|
3
2
|
import native from '../native.js';
|
|
4
3
|
import { rm, mkdir, readFile } from 'node:fs/promises';
|
|
@@ -10,16 +9,15 @@ import exitHook from 'exit-hook';
|
|
|
10
9
|
import './worker.js';
|
|
11
10
|
import { save } from './save.js';
|
|
12
11
|
import { DEFAULT_BLOCK_CAPACITY } from '@based/schema/def';
|
|
13
|
-
import { bufToHex, hexToBuf } from '
|
|
12
|
+
import { bufToHex, hexToBuf } from '@saulx/utils';
|
|
14
13
|
export async function start(db, opts) {
|
|
15
14
|
const path = db.fileSystemPath;
|
|
16
|
-
const id = stringHash(path) >>> 0;
|
|
17
15
|
const noop = () => { };
|
|
18
16
|
if (opts?.clean) {
|
|
19
17
|
await rm(path, { recursive: true, force: true }).catch(noop);
|
|
20
18
|
}
|
|
21
19
|
await mkdir(path, { recursive: true }).catch(noop);
|
|
22
|
-
db.dbCtxExternal = native.start(
|
|
20
|
+
db.dbCtxExternal = native.start();
|
|
23
21
|
let writelog = null;
|
|
24
22
|
try {
|
|
25
23
|
writelog = JSON.parse((await readFile(join(path, WRITELOG_FILE))).toString());
|
|
@@ -36,11 +34,13 @@ export async function start(db, opts) {
|
|
|
36
34
|
const dumps = writelog.rangeDumps[typeId];
|
|
37
35
|
for (const dump of dumps) {
|
|
38
36
|
const fname = dump.file;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
if (fname?.length > 0) {
|
|
38
|
+
try {
|
|
39
|
+
native.loadRange(join(path, fname), db.dbCtxExternal);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
console.error(e.message);
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -63,7 +63,8 @@ export async function start(db, opts) {
|
|
|
63
63
|
writelog?.types[def.id]?.blockCapacity || DEFAULT_BLOCK_CAPACITY;
|
|
64
64
|
foreachBlock(db, def, (start, end, hash) => {
|
|
65
65
|
const mtKey = makeCsmtKey(def.id, start);
|
|
66
|
-
const file = writelog.rangeDumps[def.id]?.find((v) => v.start === start)?.file ||
|
|
66
|
+
const file = writelog.rangeDumps[def.id]?.find((v) => v.start === start)?.file ||
|
|
67
|
+
'';
|
|
67
68
|
const data = {
|
|
68
69
|
file,
|
|
69
70
|
typeId: def.id,
|
|
@@ -71,7 +72,7 @@ export async function start(db, opts) {
|
|
|
71
72
|
end,
|
|
72
73
|
};
|
|
73
74
|
db.merkleTree.insert(mtKey, hash, data);
|
|
74
|
-
});
|
|
75
|
+
}, true);
|
|
75
76
|
}
|
|
76
77
|
if (writelog?.hash) {
|
|
77
78
|
const oldHash = hexToBuf(writelog.hash);
|
|
@@ -101,5 +102,10 @@ export async function start(db, opts) {
|
|
|
101
102
|
signals.forEach((sig) => process.off(sig, blockSig));
|
|
102
103
|
});
|
|
103
104
|
}
|
|
105
|
+
if (db.saveIntervalInSeconds > 0) {
|
|
106
|
+
db.saveInterval ??= setInterval(() => {
|
|
107
|
+
save(db);
|
|
108
|
+
}, db.saveIntervalInSeconds * 1e3);
|
|
109
|
+
}
|
|
104
110
|
}
|
|
105
111
|
//# sourceMappingURL=start.js.map
|
|
@@ -11,5 +11,5 @@ export declare const destructureCsmtKey: (key: number) => number[];
|
|
|
11
11
|
export declare const makeCsmtKey: (typeId: number, start: number) => number;
|
|
12
12
|
export declare const makeCsmtKeyFromNodeId: (typeId: number, blockCapacity: number, nodeId: number) => number;
|
|
13
13
|
export declare function initCsmt(db: DbServer): {};
|
|
14
|
-
export declare function foreachBlock(db: DbServer, def: SchemaTypeDef, cb: (start: number, end: number, hash: Uint8Array) => void): void;
|
|
14
|
+
export declare function foreachBlock(db: DbServer, def: SchemaTypeDef, cb: (start: number, end: number, hash: Uint8Array) => void, includeEmptyBlocks?: boolean): void;
|
|
15
15
|
export declare function foreachDirtyBlock(db: DbServer, cb: (mtKey: number, typeId: number, start: number, end: number) => void): Promise<void>;
|
package/dist/src/server/tree.js
CHANGED
|
@@ -38,13 +38,13 @@ export function initCsmt(db) {
|
|
|
38
38
|
}
|
|
39
39
|
return types;
|
|
40
40
|
}
|
|
41
|
-
export function foreachBlock(db, def, cb) {
|
|
41
|
+
export function foreachBlock(db, def, cb, includeEmptyBlocks = false) {
|
|
42
42
|
const step = def.blockCapacity;
|
|
43
43
|
for (let start = 1; start <= def.lastId; start += step) {
|
|
44
44
|
const end = start + step - 1;
|
|
45
45
|
const hash = new Uint8Array(16);
|
|
46
46
|
const res = native.getNodeRangeHash(def.id, start, end, hash, db.dbCtxExternal);
|
|
47
|
-
if (res) {
|
|
47
|
+
if (res || includeEmptyBlocks) {
|
|
48
48
|
cb(start, end, hash);
|
|
49
49
|
}
|
|
50
50
|
}
|
package/dist/src/utils.d.ts
CHANGED
|
@@ -3,13 +3,3 @@ export declare const DECODER: TextDecoder;
|
|
|
3
3
|
export declare const ENCODER: TextEncoder;
|
|
4
4
|
export declare const debugMode: (target: any, getInfo?: any) => void;
|
|
5
5
|
export declare const debugServer: (server: DbServer) => void;
|
|
6
|
-
export declare const equals: (aB: Uint8Array, bB: Uint8Array) => boolean;
|
|
7
|
-
export declare function concatUint8Arr(bufs: Uint8Array[], totalByteLength?: number): Uint8Array;
|
|
8
|
-
export declare const bufToHex: (a: Uint8Array) => string;
|
|
9
|
-
export declare const hexToBuf: (s: string) => Uint8Array;
|
|
10
|
-
export declare const readDoubleLE: (val: Uint8Array, offset: number) => number;
|
|
11
|
-
export declare const readFloatLE: (val: Uint8Array, offset: number) => number;
|
|
12
|
-
export declare const readUint32: (val: Uint8Array, offset: number) => number;
|
|
13
|
-
export declare const readInt32: (val: Uint8Array, offset: number) => number;
|
|
14
|
-
export declare const readInt16: (val: Uint8Array, offset: number) => number;
|
|
15
|
-
export declare const readUint16: (val: Uint8Array, offset: number) => number;
|