@based/db 0.0.46 → 0.0.48
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/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
- 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/darwin_aarch64/libnode-v24.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +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/libnode-v24.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +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/libnode-v24.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/src/client/index.d.ts +3 -1
- package/dist/src/client/index.js +11 -1
- package/dist/src/client/query/BasedDbQuery.d.ts +2 -2
- package/dist/src/client/query/display.d.ts +1 -0
- package/dist/src/client/query/display.js +10 -4
- package/dist/src/client/query/filter/toBuffer.d.ts +1 -0
- package/dist/src/client/query/filter/toBuffer.js +11 -0
- package/dist/src/client/query/query.d.ts +1 -1
- package/dist/src/client/query/query.js +1 -1
- package/dist/src/client/query/registerQuery.js +1 -1
- package/dist/src/client/query/subscription/index.d.ts +10 -0
- package/dist/src/client/query/subscription/index.js +59 -4
- package/dist/src/client/query/toByteCode/default.d.ts +2 -0
- package/dist/src/client/query/toByteCode/default.js +40 -0
- package/dist/src/client/query/toByteCode/toBuffer.d.ts +3 -0
- package/dist/src/client/query/{toBuffer.js → toByteCode/toBuffer.js} +10 -34
- package/dist/src/hooks.d.ts +16 -0
- package/dist/src/hooks.js +47 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +3 -62
- package/dist/src/server/index.js +6 -2
- package/dist/src/server/migrate/index.d.ts +0 -1
- package/dist/src/server/migrate/index.js +1 -1
- package/dist/src/server/migrate/worker.js +4 -1
- package/dist/src/server/start.d.ts +0 -1
- package/dist/src/server/start.js +0 -1
- package/dist/src/server/worker.js +5 -2
- package/package.json +1 -1
- package/dist/src/client/query/toBuffer.d.ts +0 -3
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -8,6 +8,7 @@ import { DbServer } from '../server/index.js';
|
|
|
8
8
|
import { TransformFns } from '../server/migrate/index.js';
|
|
9
9
|
import { ModifyOpts } from './modify/types.js';
|
|
10
10
|
import { OnClose, OnData, OnError } from './query/subscription/types.js';
|
|
11
|
+
import { SubStore } from './query/subscription/index.js';
|
|
11
12
|
export type DbClientHooks = {
|
|
12
13
|
setSchema(schema: StrictSchema, fromStart?: boolean, transformFns?: TransformFns): Promise<DbServer['schema']>;
|
|
13
14
|
flushModify(buf: Uint8Array): Promise<{
|
|
@@ -15,7 +16,7 @@ export type DbClientHooks = {
|
|
|
15
16
|
dbWriteTime?: number;
|
|
16
17
|
}>;
|
|
17
18
|
getQueryBuf(buf: Uint8Array): Promise<Uint8Array>;
|
|
18
|
-
subscribe(q: BasedDbQuery, onData: OnData
|
|
19
|
+
subscribe(q: BasedDbQuery, onData: (buf: Uint8Array) => ReturnType<OnData>, onError?: OnError): OnClose;
|
|
19
20
|
};
|
|
20
21
|
type DbClientOpts = {
|
|
21
22
|
hooks: DbClientHooks;
|
|
@@ -26,6 +27,7 @@ type DbClientOpts = {
|
|
|
26
27
|
type DbClientSchema = DbServer['schema'];
|
|
27
28
|
export declare class DbClient {
|
|
28
29
|
constructor({ hooks, maxModifySize, flushTime, debug, }: DbClientOpts);
|
|
30
|
+
subs: Map<BasedDbQuery, SubStore>;
|
|
29
31
|
flushTime: number;
|
|
30
32
|
flushReady: () => void;
|
|
31
33
|
flushIsReady: Promise<void>;
|
package/dist/src/client/index.js
CHANGED
|
@@ -30,6 +30,7 @@ export class DbClient {
|
|
|
30
30
|
debugMode(this);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
subs = new Map();
|
|
33
34
|
flushTime;
|
|
34
35
|
flushReady;
|
|
35
36
|
flushIsReady;
|
|
@@ -75,9 +76,14 @@ export class DbClient {
|
|
|
75
76
|
if (this.modifyCtx.len > 8) {
|
|
76
77
|
console.info('Modify cancelled - schema updated');
|
|
77
78
|
}
|
|
79
|
+
// cancel modify queue
|
|
78
80
|
const resCtx = this.modifyCtx.ctx;
|
|
79
81
|
this.modifyCtx.reset();
|
|
80
82
|
execCtxQueue(resCtx, true);
|
|
83
|
+
// resubscribe
|
|
84
|
+
for (const [q, store] of this.subs) {
|
|
85
|
+
store.resubscribe(q);
|
|
86
|
+
}
|
|
81
87
|
if (this.listeners?.schema) {
|
|
82
88
|
for (const cb of this.listeners.schema) {
|
|
83
89
|
cb(this.schema);
|
|
@@ -180,10 +186,14 @@ export class DbClient {
|
|
|
180
186
|
return expire(this, type, typeof id === 'number' ? id : id.tmpId, seconds);
|
|
181
187
|
}
|
|
182
188
|
destroy() {
|
|
183
|
-
this.
|
|
189
|
+
this.stop();
|
|
184
190
|
this.modifyCtx.db = null; // Make sure we don't have a circular ref and leak mem
|
|
185
191
|
}
|
|
186
192
|
stop() {
|
|
193
|
+
for (const [, { onClose }] of this.subs) {
|
|
194
|
+
onClose();
|
|
195
|
+
}
|
|
196
|
+
this.subs.clear();
|
|
187
197
|
this.modifyCtx.len = 0;
|
|
188
198
|
}
|
|
189
199
|
// For more advanced / internal usage - use isModified instead for most cases
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { QueryDef, QueryTarget, Operator, QueryByAliasObj } from './query.js';
|
|
2
2
|
import { BasedQueryResponse } from './BasedIterable.js';
|
|
3
3
|
import { Search } from './search/index.js';
|
|
4
|
-
import { OnData, OnError } from './subscription/index.js';
|
|
4
|
+
import { OnData, OnError, OnClose } from './subscription/index.js';
|
|
5
5
|
import { DbClient } from '../index.js';
|
|
6
6
|
import { LangName } from '@based/schema';
|
|
7
7
|
import { FilterAst, FilterBranchFn, FilterOpts } from './filter/types.js';
|
|
@@ -48,7 +48,7 @@ export declare class BasedDbQuery extends QueryBranch<BasedDbQuery> {
|
|
|
48
48
|
buffer: Uint8Array;
|
|
49
49
|
register(): void;
|
|
50
50
|
locale(locale: LangName): this;
|
|
51
|
-
subscribe(onData: OnData, onError?: OnError):
|
|
51
|
+
subscribe(onData: OnData, onError?: OnError): OnClose;
|
|
52
52
|
_getSync(dbCtxExternal: any): BasedQueryResponse;
|
|
53
53
|
toBuffer(): Uint8Array;
|
|
54
54
|
}
|
|
@@ -3,6 +3,7 @@ import { TypeIndex } from '@based/schema/def';
|
|
|
3
3
|
import { BasedQueryResponse } from './BasedIterable.js';
|
|
4
4
|
export declare const size: (size: number) => string;
|
|
5
5
|
export declare const time: (time: number) => string;
|
|
6
|
+
export declare const printNumber: (nr: number) => string;
|
|
6
7
|
export declare const prettyPrintVal: (v: any, type: TypeIndex) => string;
|
|
7
8
|
export declare const parseUint8Array: (p: any) => any;
|
|
8
9
|
export declare const safeStringify: (p: any, nr?: number) => string;
|
|
@@ -35,6 +35,12 @@ export const time = (time) => {
|
|
|
35
35
|
return picocolors.green(str);
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
+
export const printNumber = (nr) => {
|
|
39
|
+
if (nr > 1000) {
|
|
40
|
+
return picocolors.blue(nr.toLocaleString());
|
|
41
|
+
}
|
|
42
|
+
return picocolors.blue(nr);
|
|
43
|
+
};
|
|
38
44
|
export const prettyPrintVal = (v, type) => {
|
|
39
45
|
if (type === BINARY) {
|
|
40
46
|
const nr = 12;
|
|
@@ -151,12 +157,12 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
|
|
|
151
157
|
else if (!def) {
|
|
152
158
|
if (typeof v === 'number') {
|
|
153
159
|
if (q.aggregate) {
|
|
154
|
-
str +=
|
|
160
|
+
str += printNumber(v);
|
|
155
161
|
str += picocolors.italic(picocolors.dim(` ${key.indexOf('count') >= 0 ? ' count' : ' sum'}`));
|
|
156
162
|
str += ',\n';
|
|
157
163
|
}
|
|
158
164
|
else {
|
|
159
|
-
str +=
|
|
165
|
+
str += printNumber(v) + '\n';
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
168
|
else {
|
|
@@ -212,11 +218,11 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
|
|
|
212
218
|
else {
|
|
213
219
|
if (typeof v === 'number') {
|
|
214
220
|
if (q.aggregate) {
|
|
215
|
-
str +=
|
|
221
|
+
str += printNumber(v);
|
|
216
222
|
str += picocolors.italic(picocolors.dim(` ${key.indexOf('count') >= 0 ? ' count' : ' sum'}`));
|
|
217
223
|
}
|
|
218
224
|
else {
|
|
219
|
-
str +=
|
|
225
|
+
str += printNumber(v);
|
|
220
226
|
}
|
|
221
227
|
}
|
|
222
228
|
else if (typeof v === 'object' && v) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { QueryDefFilter } from '../types.js';
|
|
2
2
|
export declare const fillConditionsBuffer: (result: Uint8Array, conditions: QueryDefFilter, offset: number) => number;
|
|
3
|
+
export declare const isSimpleMainFilter: (conditions: QueryDefFilter) => boolean;
|
|
3
4
|
export declare const filterToBuffer: (conditions: QueryDefFilter) => Uint8Array;
|
|
@@ -81,7 +81,18 @@ export const fillConditionsBuffer = (result, conditions, offset) => {
|
|
|
81
81
|
}
|
|
82
82
|
return lastWritten - offset;
|
|
83
83
|
};
|
|
84
|
+
export const isSimpleMainFilter = (conditions) => {
|
|
85
|
+
if (!conditions.references &&
|
|
86
|
+
!conditions.edges &&
|
|
87
|
+
conditions.conditions.size === 1 &&
|
|
88
|
+
conditions.conditions.has(0) &&
|
|
89
|
+
!conditions.or) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
};
|
|
84
94
|
export const filterToBuffer = (conditions) => {
|
|
95
|
+
// add extra byte IS SINGLE CONDITION
|
|
85
96
|
let result;
|
|
86
97
|
if (conditions.size > 0) {
|
|
87
98
|
result = new Uint8Array(conditions.size);
|
|
@@ -2,7 +2,7 @@ export * from './queryDef.js';
|
|
|
2
2
|
export * from './types.js';
|
|
3
3
|
export * from './include/props.js';
|
|
4
4
|
export * from './include/toBuffer.js';
|
|
5
|
-
export * from './toBuffer.js';
|
|
5
|
+
export * from './toByteCode/toBuffer.js';
|
|
6
6
|
export * from './filter/filter.js';
|
|
7
7
|
export * from './filter/toBuffer.js';
|
|
8
8
|
export * from './sort.js';
|
|
@@ -2,7 +2,7 @@ export * from './queryDef.js';
|
|
|
2
2
|
export * from './types.js';
|
|
3
3
|
export * from './include/props.js';
|
|
4
4
|
export * from './include/toBuffer.js';
|
|
5
|
-
export * from './toBuffer.js';
|
|
5
|
+
export * from './toByteCode/toBuffer.js';
|
|
6
6
|
export * from './filter/filter.js';
|
|
7
7
|
export * from './filter/toBuffer.js';
|
|
8
8
|
export * from './sort.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import native from '../../native.js';
|
|
2
2
|
import { concatUint8Arr } from '@saulx/utils';
|
|
3
|
-
import { defToBuffer } from './toBuffer.js';
|
|
3
|
+
import { defToBuffer } from './toByteCode/toBuffer.js';
|
|
4
4
|
import { handleErrors } from './validation.js';
|
|
5
5
|
export const registerQuery = (q) => {
|
|
6
6
|
if (!q.id) {
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { BasedDbQuery } from '../BasedDbQuery.js';
|
|
2
|
+
import { BasedQueryResponse } from '../BasedIterable.js';
|
|
2
3
|
import { OnData, OnError, OnClose } from './types.js';
|
|
4
|
+
export declare class SubStore {
|
|
5
|
+
listeners: Map<OnData, OnError>;
|
|
6
|
+
onClose: OnClose;
|
|
7
|
+
response?: BasedQueryResponse;
|
|
8
|
+
checksum?: number;
|
|
9
|
+
len?: number;
|
|
10
|
+
subscribe(q: BasedDbQuery): void;
|
|
11
|
+
resubscribe(q: BasedDbQuery): void;
|
|
12
|
+
}
|
|
3
13
|
export declare const subscribe: (q: BasedDbQuery, onData: OnData, onError?: OnError) => OnClose;
|
|
4
14
|
export * from './types.js';
|
|
@@ -1,11 +1,66 @@
|
|
|
1
|
+
import { BasedQueryResponse } from '../BasedIterable.js';
|
|
1
2
|
import { includeField } from '../query.js';
|
|
2
3
|
import { registerQuery } from '../registerQuery.js';
|
|
4
|
+
export class SubStore {
|
|
5
|
+
listeners;
|
|
6
|
+
onClose;
|
|
7
|
+
response;
|
|
8
|
+
checksum;
|
|
9
|
+
len;
|
|
10
|
+
subscribe(q) {
|
|
11
|
+
if (!q.def.include.stringFields.size && !q.def.references.size) {
|
|
12
|
+
includeField(q.def, '*');
|
|
13
|
+
}
|
|
14
|
+
registerQuery(q);
|
|
15
|
+
this.onClose = q.db.hooks.subscribe(q, (res) => {
|
|
16
|
+
if (!this.response) {
|
|
17
|
+
this.response = new BasedQueryResponse(q.id, q.def, res, 0);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.response.result = res;
|
|
21
|
+
this.response.end = res.byteLength;
|
|
22
|
+
}
|
|
23
|
+
const checksum = this.response.checksum;
|
|
24
|
+
const len = res.byteLength;
|
|
25
|
+
if (this.len !== len || this.checksum !== checksum) {
|
|
26
|
+
for (const [onData] of this.listeners) {
|
|
27
|
+
onData(this.response);
|
|
28
|
+
}
|
|
29
|
+
this.len = len;
|
|
30
|
+
this.checksum = checksum;
|
|
31
|
+
}
|
|
32
|
+
}, (err) => {
|
|
33
|
+
for (const [, onError] of this.listeners) {
|
|
34
|
+
onError(err);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
resubscribe(q) {
|
|
39
|
+
this.onClose();
|
|
40
|
+
q.reBuildQuery();
|
|
41
|
+
this.response = null;
|
|
42
|
+
this.subscribe(q);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
3
45
|
export const subscribe = (q, onData, onError) => {
|
|
4
|
-
if (!q.
|
|
5
|
-
|
|
46
|
+
if (!q.db.subs.has(q)) {
|
|
47
|
+
const store = new SubStore();
|
|
48
|
+
store.listeners = new Map([[onData, onError]]);
|
|
49
|
+
store.subscribe(q);
|
|
50
|
+
q.db.subs.set(q, store);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const store = q.db.subs.get(q);
|
|
54
|
+
store.listeners.set(onData, onError);
|
|
6
55
|
}
|
|
7
|
-
|
|
8
|
-
|
|
56
|
+
return () => {
|
|
57
|
+
const store = q.db.subs.get(q);
|
|
58
|
+
store.listeners.delete(onData);
|
|
59
|
+
if (!store.listeners.size) {
|
|
60
|
+
q.db.subs.delete(q);
|
|
61
|
+
store.onClose();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
9
64
|
};
|
|
10
65
|
export * from './types.js';
|
|
11
66
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { filterToBuffer, isSimpleMainFilter } from '../query.js';
|
|
2
|
+
import { QueryType } from '../types.js';
|
|
3
|
+
export const defaultQuery = (def, filterSize, sortSize, searchSize, sort, search) => {
|
|
4
|
+
const buf = new Uint8Array(18 + filterSize + sortSize + searchSize);
|
|
5
|
+
let index = 0;
|
|
6
|
+
buf[index++] = QueryType.default;
|
|
7
|
+
buf[index++] = def.schema.idUint8[0];
|
|
8
|
+
buf[index++] = def.schema.idUint8[1];
|
|
9
|
+
buf[index++] = def.range.offset;
|
|
10
|
+
buf[index++] = def.range.offset >>> 8;
|
|
11
|
+
buf[index++] = def.range.offset >>> 16;
|
|
12
|
+
buf[index++] = def.range.offset >>> 24;
|
|
13
|
+
buf[index++] = def.range.limit;
|
|
14
|
+
buf[index++] = def.range.limit >>> 8;
|
|
15
|
+
buf[index++] = def.range.limit >>> 16;
|
|
16
|
+
buf[index++] = def.range.limit >>> 24;
|
|
17
|
+
buf[index++] = filterSize;
|
|
18
|
+
buf[index++] = filterSize >>> 8;
|
|
19
|
+
buf[index++] = filterSize && isSimpleMainFilter(def.filter) ? 1 : 0;
|
|
20
|
+
// if (filterSize && isSimpleMainFilter(def.filter)) {
|
|
21
|
+
// console.log('SIMPLE FILTER!')
|
|
22
|
+
if (filterSize) {
|
|
23
|
+
buf.set(filterToBuffer(def.filter), index);
|
|
24
|
+
index += filterSize;
|
|
25
|
+
}
|
|
26
|
+
buf[index++] = sortSize;
|
|
27
|
+
buf[index++] = sortSize >>> 8;
|
|
28
|
+
if (sortSize) {
|
|
29
|
+
buf.set(sort, index);
|
|
30
|
+
index += sortSize;
|
|
31
|
+
}
|
|
32
|
+
buf[index++] = searchSize;
|
|
33
|
+
buf[index++] = searchSize >>> 8;
|
|
34
|
+
if (searchSize) {
|
|
35
|
+
buf.set(search, index);
|
|
36
|
+
index += searchSize;
|
|
37
|
+
}
|
|
38
|
+
return buf;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=default.js.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createSortBuffer } from '
|
|
2
|
-
import { QueryDefType, QueryType } from '
|
|
3
|
-
import { includeToBuffer } from '
|
|
4
|
-
import { filterToBuffer } from '
|
|
5
|
-
import { searchToBuffer } from '
|
|
1
|
+
import { createSortBuffer } from '../sort.js';
|
|
2
|
+
import { QueryDefType, QueryType } from '../types.js';
|
|
3
|
+
import { includeToBuffer } from '../include/toBuffer.js';
|
|
4
|
+
import { filterToBuffer } from '../query.js';
|
|
5
|
+
import { searchToBuffer } from '../search/index.js';
|
|
6
6
|
import { ENCODER, writeUint64 } from '@saulx/utils';
|
|
7
|
-
import { aggregateToBuffer, isRootCountOnly } from '
|
|
7
|
+
import { aggregateToBuffer, isRootCountOnly, } from '../aggregates/aggregation.js';
|
|
8
|
+
import { defaultQuery } from './default.js';
|
|
8
9
|
const byteSize = (arr) => {
|
|
9
10
|
return arr.reduce((a, b) => {
|
|
10
11
|
return a + b.byteLength;
|
|
@@ -173,6 +174,8 @@ export function defToBuffer(db, def) {
|
|
|
173
174
|
buf[idsSize + 12] = def.range.limit >>> 8;
|
|
174
175
|
buf[idsSize + 13] = def.range.limit >>> 16;
|
|
175
176
|
buf[idsSize + 14] = def.range.limit >>> 24;
|
|
177
|
+
// if (filterSize && isSimpleMainFilter(def.filter)) {
|
|
178
|
+
// console.log('SIMPLE FILTER!')
|
|
176
179
|
buf[idsSize + 15] = filterSize;
|
|
177
180
|
buf[idsSize + 16] = filterSize >>> 8;
|
|
178
181
|
if (filterSize) {
|
|
@@ -193,34 +196,7 @@ export function defToBuffer(db, def) {
|
|
|
193
196
|
result.push(buf);
|
|
194
197
|
}
|
|
195
198
|
else {
|
|
196
|
-
|
|
197
|
-
buf[0] = QueryType.default;
|
|
198
|
-
buf[1] = def.schema.idUint8[0];
|
|
199
|
-
buf[2] = def.schema.idUint8[1];
|
|
200
|
-
buf[3] = def.range.offset;
|
|
201
|
-
buf[4] = def.range.offset >>> 8;
|
|
202
|
-
buf[5] = def.range.offset >>> 16;
|
|
203
|
-
buf[6] = def.range.offset >>> 24;
|
|
204
|
-
buf[7] = def.range.limit;
|
|
205
|
-
buf[8] = def.range.limit >>> 8;
|
|
206
|
-
buf[9] = def.range.limit >>> 16;
|
|
207
|
-
buf[10] = def.range.limit >>> 24;
|
|
208
|
-
buf[11] = filterSize;
|
|
209
|
-
buf[12] = filterSize >>> 8;
|
|
210
|
-
if (filterSize) {
|
|
211
|
-
buf.set(filterToBuffer(def.filter), 13);
|
|
212
|
-
}
|
|
213
|
-
buf[13 + filterSize] = sortSize;
|
|
214
|
-
buf[14 + filterSize] = sortSize >>> 8;
|
|
215
|
-
if (sortSize) {
|
|
216
|
-
buf.set(sort, 15 + filterSize);
|
|
217
|
-
}
|
|
218
|
-
buf[15 + filterSize + sortSize] = searchSize;
|
|
219
|
-
buf[16 + filterSize + sortSize] = searchSize >>> 8;
|
|
220
|
-
if (searchSize) {
|
|
221
|
-
buf.set(search, 17 + filterSize + sortSize);
|
|
222
|
-
}
|
|
223
|
-
result.push(buf);
|
|
199
|
+
result.push(defaultQuery(def, filterSize, sortSize, searchSize, sort, search));
|
|
224
200
|
}
|
|
225
201
|
}
|
|
226
202
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { StrictSchema } from '@based/schema';
|
|
2
|
+
import { BasedDbQuery } from './client/query/BasedDbQuery.js';
|
|
3
|
+
import { OnError } from './client/query/subscription/types.js';
|
|
4
|
+
import { DbServer } from './server/index.js';
|
|
5
|
+
export declare const getDefaultHooks: (server: DbServer, subInterval?: number) => {
|
|
6
|
+
subscribe(q: BasedDbQuery, onData: (res: Uint8Array) => void, onError: OnError): () => void;
|
|
7
|
+
setSchema(schema: StrictSchema, fromStart: boolean): Promise<StrictSchema & {
|
|
8
|
+
lastId: number;
|
|
9
|
+
hash?: number;
|
|
10
|
+
}>;
|
|
11
|
+
flushModify(buf: Uint8Array): Promise<{
|
|
12
|
+
offsets: Record<number, number>;
|
|
13
|
+
dbWriteTime: number;
|
|
14
|
+
}>;
|
|
15
|
+
getQueryBuf(buf: Uint8Array): Promise<Uint8Array>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const getDefaultHooks = (server, subInterval = 200) => {
|
|
2
|
+
return {
|
|
3
|
+
subscribe(q, onData, onError) {
|
|
4
|
+
let timer;
|
|
5
|
+
let killed = false;
|
|
6
|
+
const poll = async () => {
|
|
7
|
+
const res = await server.getQueryBuf(q.buffer);
|
|
8
|
+
if (killed) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (res.byteLength >= 8) {
|
|
12
|
+
onData(res);
|
|
13
|
+
}
|
|
14
|
+
else if (res.byteLength === 1 && res[0] === 0) {
|
|
15
|
+
console.info('schema mismatch, should resolve after update');
|
|
16
|
+
// ignore update and stop polling
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
onError(new Error('unexpected error'));
|
|
21
|
+
}
|
|
22
|
+
timer = setTimeout(poll, subInterval);
|
|
23
|
+
};
|
|
24
|
+
poll();
|
|
25
|
+
return () => {
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
killed = true;
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
setSchema(schema, fromStart) {
|
|
31
|
+
return Promise.resolve(server.setSchema(schema, fromStart));
|
|
32
|
+
},
|
|
33
|
+
flushModify(buf) {
|
|
34
|
+
const d = performance.now();
|
|
35
|
+
const offsets = server.modify(buf);
|
|
36
|
+
const dbWriteTime = performance.now() - d;
|
|
37
|
+
return Promise.resolve({
|
|
38
|
+
offsets,
|
|
39
|
+
dbWriteTime,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
getQueryBuf(buf) {
|
|
43
|
+
return Promise.resolve(server.getQueryBuf(buf));
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=hooks.js.map
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { compress, decompress } from './client/string.js';
|
|
|
2
2
|
import { ModifyCtx } from './client/flushModify.js';
|
|
3
3
|
import { DbServer } from './server/index.js';
|
|
4
4
|
import { DbClient } from './client/index.js';
|
|
5
|
+
import { getDefaultHooks } from './hooks.js';
|
|
5
6
|
export * from './client/modify/modify.js';
|
|
6
7
|
export { compress, decompress };
|
|
7
8
|
export { ModifyCtx };
|
|
@@ -15,6 +16,7 @@ export * from './client/query/query.js';
|
|
|
15
16
|
export * from './client/query/BasedDbQuery.js';
|
|
16
17
|
export * from './client/query/BasedIterable.js';
|
|
17
18
|
export * from './server/save.js';
|
|
19
|
+
export { getDefaultHooks };
|
|
18
20
|
export declare class BasedDb {
|
|
19
21
|
#private;
|
|
20
22
|
client: DbClient;
|
package/dist/src/index.js
CHANGED
|
@@ -4,8 +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 {
|
|
8
|
-
import { registerQuery } from './client/query/registerQuery.js';
|
|
7
|
+
import { getDefaultHooks } from './hooks.js';
|
|
9
8
|
export * from './client/modify/modify.js';
|
|
10
9
|
export { compress, decompress };
|
|
11
10
|
export { ModifyCtx }; // TODO move this somewhere
|
|
@@ -19,6 +18,7 @@ export * from './client/query/query.js';
|
|
|
19
18
|
export * from './client/query/BasedDbQuery.js';
|
|
20
19
|
export * from './client/query/BasedIterable.js';
|
|
21
20
|
export * from './server/save.js';
|
|
21
|
+
export { getDefaultHooks };
|
|
22
22
|
export class BasedDb {
|
|
23
23
|
client;
|
|
24
24
|
server;
|
|
@@ -51,66 +51,7 @@ export class BasedDb {
|
|
|
51
51
|
});
|
|
52
52
|
const client = new DbClient({
|
|
53
53
|
maxModifySize,
|
|
54
|
-
hooks:
|
|
55
|
-
subscribe(q, onData, onError) {
|
|
56
|
-
let killed = false;
|
|
57
|
-
let timer;
|
|
58
|
-
let prevChecksum;
|
|
59
|
-
let lastLen = 0;
|
|
60
|
-
let response;
|
|
61
|
-
const get = async () => {
|
|
62
|
-
const schemaVersion = q.def.schemaChecksum;
|
|
63
|
-
if (schemaVersion && schemaVersion !== server.schema.hash) {
|
|
64
|
-
q.reBuildQuery();
|
|
65
|
-
registerQuery(q);
|
|
66
|
-
response = undefined;
|
|
67
|
-
timer = setTimeout(get, 0);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (killed) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const res = await server.getQueryBuf(q.buffer);
|
|
74
|
-
if (killed) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (!response) {
|
|
78
|
-
response = new BasedQueryResponse(q.id, q.def, res, 0);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
response.result = res;
|
|
82
|
-
response.end = res.byteLength;
|
|
83
|
-
}
|
|
84
|
-
const checksum = response.checksum;
|
|
85
|
-
if (lastLen != res.byteLength || checksum != prevChecksum) {
|
|
86
|
-
onData(response);
|
|
87
|
-
lastLen = res.byteLength;
|
|
88
|
-
prevChecksum = checksum;
|
|
89
|
-
}
|
|
90
|
-
timer = setTimeout(get, 200);
|
|
91
|
-
};
|
|
92
|
-
get();
|
|
93
|
-
return () => {
|
|
94
|
-
killed = true;
|
|
95
|
-
clearTimeout(timer);
|
|
96
|
-
};
|
|
97
|
-
},
|
|
98
|
-
setSchema(schema, fromStart) {
|
|
99
|
-
return Promise.resolve(server.setSchema(schema, fromStart));
|
|
100
|
-
},
|
|
101
|
-
flushModify(buf) {
|
|
102
|
-
const d = performance.now();
|
|
103
|
-
const offsets = server.modify(buf);
|
|
104
|
-
const dbWriteTime = performance.now() - d;
|
|
105
|
-
return Promise.resolve({
|
|
106
|
-
offsets,
|
|
107
|
-
dbWriteTime,
|
|
108
|
-
});
|
|
109
|
-
},
|
|
110
|
-
getQueryBuf(buf) {
|
|
111
|
-
return Promise.resolve(server.getQueryBuf(buf));
|
|
112
|
-
},
|
|
113
|
-
},
|
|
54
|
+
hooks: getDefaultHooks(server),
|
|
114
55
|
});
|
|
115
56
|
this.server = server;
|
|
116
57
|
this.client = client;
|
package/dist/src/server/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { migrate } from './migrate/index.js';
|
|
|
14
14
|
import { debugServer, schemaLooseEqual } from '../utils.js';
|
|
15
15
|
import { readUint16, readUint32, readUint64, writeUint64 } from '@saulx/utils';
|
|
16
16
|
import { hash } from '@saulx/hash';
|
|
17
|
+
import { QueryType } from '../client/query/types.js';
|
|
17
18
|
export const SCHEMA_FILE = 'schema.json';
|
|
18
19
|
export const WRITELOG_FILE = 'writelog.json';
|
|
19
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -36,6 +37,7 @@ export class DbWorker {
|
|
|
36
37
|
this.channel = port1;
|
|
37
38
|
this.worker = new Worker(workerPath, {
|
|
38
39
|
workerData: {
|
|
40
|
+
isDbWorker: true,
|
|
39
41
|
channel: port2,
|
|
40
42
|
address,
|
|
41
43
|
},
|
|
@@ -480,10 +482,12 @@ export class DbServer {
|
|
|
480
482
|
}
|
|
481
483
|
else {
|
|
482
484
|
const queryType = buf[0];
|
|
483
|
-
if (queryType ==
|
|
484
|
-
|
|
485
|
+
if (queryType == QueryType.default) {
|
|
486
|
+
// TODO: make a function for this!
|
|
487
|
+
const s = 14 + readUint16(buf, 11);
|
|
485
488
|
const sortLen = readUint16(buf, s);
|
|
486
489
|
if (sortLen) {
|
|
490
|
+
// make function for this
|
|
487
491
|
const typeId = readUint16(buf, 1);
|
|
488
492
|
const sort = buf.slice(s + 2, s + 2 + sortLen);
|
|
489
493
|
const field = sort[1];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { StrictSchema } from '@based/schema';
|
|
2
|
-
import './worker.js';
|
|
3
2
|
import { DbServer } from '../index.js';
|
|
4
3
|
type TransformFn = (node: Record<string, any>) => Record<string, any> | [string, Record<string, any>];
|
|
5
4
|
export type TransformFns = Record<string, TransformFn>;
|
|
@@ -3,7 +3,6 @@ import { dirname, join } from 'path';
|
|
|
3
3
|
import { tmpdir } from 'os';
|
|
4
4
|
import { Worker, MessageChannel, receiveMessageOnPort, } from 'node:worker_threads';
|
|
5
5
|
import native from '../../native.js';
|
|
6
|
-
import './worker.js';
|
|
7
6
|
import { destructureCsmtKey, foreachDirtyBlock, specialBlock } from '../tree.js';
|
|
8
7
|
import { SCHEMA_FILE } from '../index.js';
|
|
9
8
|
import { fileURLToPath } from 'url';
|
|
@@ -58,6 +57,7 @@ export const migrate = async (fromDbServer, toSchema, transform) => {
|
|
|
58
57
|
atomics[0] = 1;
|
|
59
58
|
const worker = new Worker(workerPath, {
|
|
60
59
|
workerData: {
|
|
60
|
+
isDbMigrateWorker: true,
|
|
61
61
|
from: fromAddress,
|
|
62
62
|
to: toAddress,
|
|
63
63
|
fromSchema,
|
|
@@ -6,7 +6,7 @@ import { isTypedArray } from 'node:util/types';
|
|
|
6
6
|
if (isMainThread) {
|
|
7
7
|
console.warn('running worker.ts in mainthread');
|
|
8
8
|
}
|
|
9
|
-
else {
|
|
9
|
+
else if (workerData?.isDbMigrateWorker) {
|
|
10
10
|
const { from, to, fromSchema, toSchema, channel, atomics, transformFns } = workerData;
|
|
11
11
|
const fromCtx = native.externalFromInt(from);
|
|
12
12
|
const toCtx = native.externalFromInt(to);
|
|
@@ -114,4 +114,7 @@ else {
|
|
|
114
114
|
Atomics.wait(atomics, 0, 0);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
else {
|
|
118
|
+
console.info('incorrect worker db migrate');
|
|
119
|
+
}
|
|
117
120
|
//# sourceMappingURL=worker.js.map
|
package/dist/src/server/start.js
CHANGED
|
@@ -6,7 +6,6 @@ import { hashEq } from './csmt/index.js';
|
|
|
6
6
|
import { foreachBlock, initCsmt, makeCsmtKey } from './tree.js';
|
|
7
7
|
import { availableParallelism } from 'node:os';
|
|
8
8
|
import exitHook from 'exit-hook';
|
|
9
|
-
import './worker.js';
|
|
10
9
|
import { save } from './save.js';
|
|
11
10
|
import { DEFAULT_BLOCK_CAPACITY } from '@based/schema/def';
|
|
12
11
|
import { bufToHex, hexToBuf } from '@saulx/utils';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isMainThread, receiveMessageOnPort, workerData, } from 'node:worker_threads';
|
|
2
2
|
import native from '../native.js';
|
|
3
3
|
if (isMainThread) {
|
|
4
|
-
console.warn('running query worker.ts in mainthread');
|
|
4
|
+
console.warn('running query worker.ts in mainthread - incorrect');
|
|
5
5
|
}
|
|
6
|
-
else {
|
|
6
|
+
else if (workerData?.isDbWorker) {
|
|
7
7
|
let { address, channel } = workerData;
|
|
8
8
|
let dbCtx = native.externalFromInt(address);
|
|
9
9
|
native.workerCtxInit();
|
|
@@ -32,4 +32,7 @@ else {
|
|
|
32
32
|
handleMsg(msg.message);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
else {
|
|
36
|
+
console.info('incorrect worker db query');
|
|
37
|
+
}
|
|
35
38
|
//# sourceMappingURL=worker.js.map
|
package/package.json
CHANGED