@based/db 0.0.29 → 0.0.31
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/include/selva/db.h +2 -1
- package/dist/lib/darwin_aarch64/include/selva/fields.h +20 -7
- package/dist/lib/darwin_aarch64/include/selva/types.h +3 -1
- 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/libselva.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +2 -1
- package/dist/lib/linux_aarch64/include/selva/fields.h +20 -7
- package/dist/lib/linux_aarch64/include/selva/types.h +3 -1
- 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_x86_64/include/selva/db.h +2 -1
- package/dist/lib/linux_x86_64/include/selva/fields.h +20 -7
- package/dist/lib/linux_x86_64/include/selva/types.h +3 -1
- 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/src/client/flushModify.js +4 -3
- package/dist/src/client/index.d.ts +2 -6
- package/dist/src/client/index.js +0 -6
- package/dist/src/client/modify/ModifyRes.d.ts +1 -3
- package/dist/src/client/modify/ModifyRes.js +1 -3
- package/dist/src/client/modify/create.js +1 -2
- package/dist/src/client/modify/delete.js +1 -2
- package/dist/src/client/modify/modify.js +0 -4
- package/dist/src/client/modify/setCursor.js +1 -1
- package/dist/src/client/modify/update.js +1 -2
- package/dist/src/client/query/read/read.js +13 -4
- package/dist/src/client/query/subscription/index.d.ts +1 -2
- package/dist/src/client/query/subscription/index.js +3 -50
- package/dist/src/client/query/subscription/types.d.ts +1 -29
- package/dist/src/client/query/subscription/types.js +8 -1
- package/dist/src/client/string.js +1 -1
- package/dist/src/index.js +28 -0
- package/dist/src/native.d.ts +2 -2
- package/dist/src/native.js +3 -1
- package/dist/src/server/save.js +4 -7
- package/dist/src/server/start.js +8 -6
- package/dist/src/server/tree.d.ts +1 -1
- package/dist/src/server/tree.js +2 -2
- package/package.json +1 -1
|
@@ -209,9 +209,10 @@ void selva_db_expire_tick(struct SelvaDb *db, int64_t now);
|
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* Delete a node.
|
|
212
|
+
* @param dirty_cb is called for any newly dirty nodes in addition to the node being deleted.
|
|
212
213
|
*/
|
|
213
214
|
SELVA_EXPORT
|
|
214
|
-
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node) __attribute__((nonnull));
|
|
215
|
+
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx) __attribute__((nonnull(1, 2, 3)));
|
|
215
216
|
|
|
216
217
|
/**
|
|
217
218
|
* Get a node by id.
|
|
@@ -152,14 +152,22 @@ struct selva_string *selva_fields_ensure_string2(
|
|
|
152
152
|
const struct SelvaFieldSchema *fs,
|
|
153
153
|
size_t initial_len);
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Set reference to fields.
|
|
157
|
+
* @param dirty_nodes returns the nodes that were changed, apart from src and dst.
|
|
158
|
+
* [n].id = 0 = nil;
|
|
159
|
+
* [0] = the node src was pointing to previously (same type as dst);
|
|
160
|
+
* [1] = the node dst was pointing to previously (same type as src).
|
|
161
|
+
*/
|
|
155
162
|
SELVA_EXPORT
|
|
156
163
|
int selva_fields_reference_set(
|
|
157
164
|
struct SelvaDb *db,
|
|
158
165
|
struct SelvaNode * restrict src,
|
|
159
166
|
const struct SelvaFieldSchema *fs_src,
|
|
160
167
|
struct SelvaNode * restrict dst,
|
|
161
|
-
struct SelvaNodeReference **ref_out
|
|
162
|
-
|
|
168
|
+
struct SelvaNodeReference **ref_out,
|
|
169
|
+
node_id_t dirty_nodes[static 2])
|
|
170
|
+
__attribute__((access(write_only, 5), access(write_only, 6)));
|
|
163
171
|
|
|
164
172
|
/**
|
|
165
173
|
* @param index 0 = first; -1 = last.
|
|
@@ -333,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
|
|
|
333
341
|
|
|
334
342
|
/**
|
|
335
343
|
* Delete field.
|
|
344
|
+
* @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
|
|
336
345
|
*/
|
|
337
346
|
SELVA_EXPORT
|
|
338
|
-
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
339
|
-
__attribute__((nonnull));
|
|
347
|
+
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
348
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
340
349
|
|
|
341
350
|
/**
|
|
342
351
|
* Delete an edge from a references field.
|
|
@@ -344,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
|
|
|
344
353
|
SELVA_EXPORT
|
|
345
354
|
int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
|
|
346
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Clear a references field but don't free it.
|
|
358
|
+
*/
|
|
347
359
|
SELVA_EXPORT
|
|
348
|
-
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
349
|
-
__attribute__((nonnull));
|
|
360
|
+
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
361
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
350
362
|
|
|
351
363
|
/**
|
|
352
364
|
* Init the fields struct of a node or edge.
|
|
@@ -361,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
|
|
|
361
373
|
* regardless wether the schema defines fields for this node.
|
|
362
374
|
*/
|
|
363
375
|
SELVA_EXPORT
|
|
364
|
-
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node)
|
|
376
|
+
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
377
|
+
__attribute__((nonnull(1, 2)));
|
|
365
378
|
|
|
366
379
|
SELVA_EXPORT
|
|
367
380
|
void selva_fields_hash_update(struct XXH3_state_s *hash_state, struct SelvaDb *db, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
|
|
@@ -43,7 +43,7 @@ struct EdgeFieldConstraint {
|
|
|
43
43
|
EDGE_FIELD_CONSTRAINT_FLAG_SCHEMA_REF_CACHED = 0x40,
|
|
44
44
|
/**
|
|
45
45
|
* Skip saving this field while dumping.
|
|
46
|
-
* If the field is of type
|
|
46
|
+
* If the field is of type SELVA_FIELD_TYPE_REFERENCES it's saved
|
|
47
47
|
* regardless of this flag to preserve the original order of references.
|
|
48
48
|
*/
|
|
49
49
|
EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80,
|
|
@@ -97,6 +97,8 @@ struct SelvaFields;
|
|
|
97
97
|
struct SelvaNode;
|
|
98
98
|
struct SelvaTypeEntry;
|
|
99
99
|
|
|
100
|
+
typedef void (*selva_dirty_node_cb_t)(void *ctx, node_type_t type, node_id_t node_id);
|
|
101
|
+
|
|
100
102
|
SELVA_EXPORT
|
|
101
103
|
bool selva_is_valid_field_type(enum SelvaFieldType ftype);
|
|
102
104
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -209,9 +209,10 @@ void selva_db_expire_tick(struct SelvaDb *db, int64_t now);
|
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* Delete a node.
|
|
212
|
+
* @param dirty_cb is called for any newly dirty nodes in addition to the node being deleted.
|
|
212
213
|
*/
|
|
213
214
|
SELVA_EXPORT
|
|
214
|
-
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node) __attribute__((nonnull));
|
|
215
|
+
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx) __attribute__((nonnull(1, 2, 3)));
|
|
215
216
|
|
|
216
217
|
/**
|
|
217
218
|
* Get a node by id.
|
|
@@ -152,14 +152,22 @@ struct selva_string *selva_fields_ensure_string2(
|
|
|
152
152
|
const struct SelvaFieldSchema *fs,
|
|
153
153
|
size_t initial_len);
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Set reference to fields.
|
|
157
|
+
* @param dirty_nodes returns the nodes that were changed, apart from src and dst.
|
|
158
|
+
* [n].id = 0 = nil;
|
|
159
|
+
* [0] = the node src was pointing to previously (same type as dst);
|
|
160
|
+
* [1] = the node dst was pointing to previously (same type as src).
|
|
161
|
+
*/
|
|
155
162
|
SELVA_EXPORT
|
|
156
163
|
int selva_fields_reference_set(
|
|
157
164
|
struct SelvaDb *db,
|
|
158
165
|
struct SelvaNode * restrict src,
|
|
159
166
|
const struct SelvaFieldSchema *fs_src,
|
|
160
167
|
struct SelvaNode * restrict dst,
|
|
161
|
-
struct SelvaNodeReference **ref_out
|
|
162
|
-
|
|
168
|
+
struct SelvaNodeReference **ref_out,
|
|
169
|
+
node_id_t dirty_nodes[static 2])
|
|
170
|
+
__attribute__((access(write_only, 5), access(write_only, 6)));
|
|
163
171
|
|
|
164
172
|
/**
|
|
165
173
|
* @param index 0 = first; -1 = last.
|
|
@@ -333,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
|
|
|
333
341
|
|
|
334
342
|
/**
|
|
335
343
|
* Delete field.
|
|
344
|
+
* @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
|
|
336
345
|
*/
|
|
337
346
|
SELVA_EXPORT
|
|
338
|
-
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
339
|
-
__attribute__((nonnull));
|
|
347
|
+
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
348
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
340
349
|
|
|
341
350
|
/**
|
|
342
351
|
* Delete an edge from a references field.
|
|
@@ -344,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
|
|
|
344
353
|
SELVA_EXPORT
|
|
345
354
|
int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
|
|
346
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Clear a references field but don't free it.
|
|
358
|
+
*/
|
|
347
359
|
SELVA_EXPORT
|
|
348
|
-
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
349
|
-
__attribute__((nonnull));
|
|
360
|
+
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
361
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
350
362
|
|
|
351
363
|
/**
|
|
352
364
|
* Init the fields struct of a node or edge.
|
|
@@ -361,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
|
|
|
361
373
|
* regardless wether the schema defines fields for this node.
|
|
362
374
|
*/
|
|
363
375
|
SELVA_EXPORT
|
|
364
|
-
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node)
|
|
376
|
+
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
377
|
+
__attribute__((nonnull(1, 2)));
|
|
365
378
|
|
|
366
379
|
SELVA_EXPORT
|
|
367
380
|
void selva_fields_hash_update(struct XXH3_state_s *hash_state, struct SelvaDb *db, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
|
|
@@ -43,7 +43,7 @@ struct EdgeFieldConstraint {
|
|
|
43
43
|
EDGE_FIELD_CONSTRAINT_FLAG_SCHEMA_REF_CACHED = 0x40,
|
|
44
44
|
/**
|
|
45
45
|
* Skip saving this field while dumping.
|
|
46
|
-
* If the field is of type
|
|
46
|
+
* If the field is of type SELVA_FIELD_TYPE_REFERENCES it's saved
|
|
47
47
|
* regardless of this flag to preserve the original order of references.
|
|
48
48
|
*/
|
|
49
49
|
EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80,
|
|
@@ -97,6 +97,8 @@ struct SelvaFields;
|
|
|
97
97
|
struct SelvaNode;
|
|
98
98
|
struct SelvaTypeEntry;
|
|
99
99
|
|
|
100
|
+
typedef void (*selva_dirty_node_cb_t)(void *ctx, node_type_t type, node_id_t node_id);
|
|
101
|
+
|
|
100
102
|
SELVA_EXPORT
|
|
101
103
|
bool selva_is_valid_field_type(enum SelvaFieldType ftype);
|
|
102
104
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -209,9 +209,10 @@ void selva_db_expire_tick(struct SelvaDb *db, int64_t now);
|
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* Delete a node.
|
|
212
|
+
* @param dirty_cb is called for any newly dirty nodes in addition to the node being deleted.
|
|
212
213
|
*/
|
|
213
214
|
SELVA_EXPORT
|
|
214
|
-
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node) __attribute__((nonnull));
|
|
215
|
+
void selva_del_node(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx) __attribute__((nonnull(1, 2, 3)));
|
|
215
216
|
|
|
216
217
|
/**
|
|
217
218
|
* Get a node by id.
|
|
@@ -152,14 +152,22 @@ struct selva_string *selva_fields_ensure_string2(
|
|
|
152
152
|
const struct SelvaFieldSchema *fs,
|
|
153
153
|
size_t initial_len);
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Set reference to fields.
|
|
157
|
+
* @param dirty_nodes returns the nodes that were changed, apart from src and dst.
|
|
158
|
+
* [n].id = 0 = nil;
|
|
159
|
+
* [0] = the node src was pointing to previously (same type as dst);
|
|
160
|
+
* [1] = the node dst was pointing to previously (same type as src).
|
|
161
|
+
*/
|
|
155
162
|
SELVA_EXPORT
|
|
156
163
|
int selva_fields_reference_set(
|
|
157
164
|
struct SelvaDb *db,
|
|
158
165
|
struct SelvaNode * restrict src,
|
|
159
166
|
const struct SelvaFieldSchema *fs_src,
|
|
160
167
|
struct SelvaNode * restrict dst,
|
|
161
|
-
struct SelvaNodeReference **ref_out
|
|
162
|
-
|
|
168
|
+
struct SelvaNodeReference **ref_out,
|
|
169
|
+
node_id_t dirty_nodes[static 2])
|
|
170
|
+
__attribute__((access(write_only, 5), access(write_only, 6)));
|
|
163
171
|
|
|
164
172
|
/**
|
|
165
173
|
* @param index 0 = first; -1 = last.
|
|
@@ -333,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
|
|
|
333
341
|
|
|
334
342
|
/**
|
|
335
343
|
* Delete field.
|
|
344
|
+
* @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
|
|
336
345
|
*/
|
|
337
346
|
SELVA_EXPORT
|
|
338
|
-
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
339
|
-
__attribute__((nonnull));
|
|
347
|
+
int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
348
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
340
349
|
|
|
341
350
|
/**
|
|
342
351
|
* Delete an edge from a references field.
|
|
@@ -344,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
|
|
|
344
353
|
SELVA_EXPORT
|
|
345
354
|
int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
|
|
346
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Clear a references field but don't free it.
|
|
358
|
+
*/
|
|
347
359
|
SELVA_EXPORT
|
|
348
|
-
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
|
|
349
|
-
__attribute__((nonnull));
|
|
360
|
+
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
361
|
+
__attribute__((nonnull(1, 2, 3)));
|
|
350
362
|
|
|
351
363
|
/**
|
|
352
364
|
* Init the fields struct of a node or edge.
|
|
@@ -361,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
|
|
|
361
373
|
* regardless wether the schema defines fields for this node.
|
|
362
374
|
*/
|
|
363
375
|
SELVA_EXPORT
|
|
364
|
-
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node)
|
|
376
|
+
void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node, selva_dirty_node_cb_t dirty_cb, void *dirty_ctx)
|
|
377
|
+
__attribute__((nonnull(1, 2)));
|
|
365
378
|
|
|
366
379
|
SELVA_EXPORT
|
|
367
380
|
void selva_fields_hash_update(struct XXH3_state_s *hash_state, struct SelvaDb *db, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
|
|
@@ -43,7 +43,7 @@ struct EdgeFieldConstraint {
|
|
|
43
43
|
EDGE_FIELD_CONSTRAINT_FLAG_SCHEMA_REF_CACHED = 0x40,
|
|
44
44
|
/**
|
|
45
45
|
* Skip saving this field while dumping.
|
|
46
|
-
* If the field is of type
|
|
46
|
+
* If the field is of type SELVA_FIELD_TYPE_REFERENCES it's saved
|
|
47
47
|
* regardless of this flag to preserve the original order of references.
|
|
48
48
|
*/
|
|
49
49
|
EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80,
|
|
@@ -97,6 +97,8 @@ struct SelvaFields;
|
|
|
97
97
|
struct SelvaNode;
|
|
98
98
|
struct SelvaTypeEntry;
|
|
99
99
|
|
|
100
|
+
typedef void (*selva_dirty_node_cb_t)(void *ctx, node_type_t type, node_id_t node_id);
|
|
101
|
+
|
|
100
102
|
SELVA_EXPORT
|
|
101
103
|
bool selva_is_valid_field_type(enum SelvaFieldType ftype);
|
|
102
104
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -90,11 +90,13 @@ export const flushBuffer = (db) => {
|
|
|
90
90
|
const ctx = db.modifyCtx;
|
|
91
91
|
let flushPromise;
|
|
92
92
|
if (ctx.len) {
|
|
93
|
-
const d = Date.now();
|
|
94
93
|
const lastIds = {};
|
|
95
94
|
const data = ctx.getData(lastIds);
|
|
96
95
|
const resCtx = ctx.ctx;
|
|
96
|
+
const d = performance.now();
|
|
97
97
|
flushPromise = db.hooks.flushModify(data).then(({ offsets }) => {
|
|
98
|
+
// return time there
|
|
99
|
+
db.writeTime += performance.now() - d;
|
|
98
100
|
resCtx.offsets = offsets;
|
|
99
101
|
for (const typeId in lastIds) {
|
|
100
102
|
if (typeId in offsets) {
|
|
@@ -107,7 +109,7 @@ export const flushBuffer = (db) => {
|
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
else {
|
|
110
|
-
console.
|
|
112
|
+
console.error('Panic: No offset returned in flushModify');
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
if (resCtx.queue?.size) {
|
|
@@ -117,7 +119,6 @@ export const flushBuffer = (db) => {
|
|
|
117
119
|
resolve(res.getId());
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
|
-
db.writeTime += Date.now() - d;
|
|
121
122
|
db.flushReady();
|
|
122
123
|
});
|
|
123
124
|
ctx.dirtyTypes.clear();
|
|
@@ -2,18 +2,19 @@ import { Schema, StrictSchema } from '@based/schema';
|
|
|
2
2
|
import { CreateObj } from './modify/create.js';
|
|
3
3
|
import { SchemaTypeDef } from '@based/schema/def';
|
|
4
4
|
import { ModifyCtx } from './flushModify.js';
|
|
5
|
-
import { SubscriptionMarkerMap, SubscriptionsMap, SubscriptionsToRun } from './query/subscription/index.js';
|
|
6
5
|
import { BasedDbQuery, QueryByAliasObj } from './query/BasedDbQuery.js';
|
|
7
6
|
import { ModifyRes } from './modify/ModifyRes.js';
|
|
8
7
|
import { DbServer } from '../server/index.js';
|
|
9
8
|
import { TransformFns } from '../server/migrate/index.js';
|
|
10
9
|
import { ModifyOpts } from './modify/types.js';
|
|
10
|
+
import { OnClose, OnData, OnError } from './query/subscription/types.js';
|
|
11
11
|
export type DbClientHooks = {
|
|
12
12
|
setSchema(schema: StrictSchema, fromStart?: boolean, transformFns?: TransformFns): Promise<DbServer['schema']>;
|
|
13
13
|
flushModify(buf: Uint8Array): Promise<{
|
|
14
14
|
offsets: Record<number, number>;
|
|
15
15
|
}>;
|
|
16
16
|
getQueryBuf(buf: Uint8Array): Promise<Uint8Array>;
|
|
17
|
+
subscribe(q: BasedDbQuery, onData: OnData, onError?: OnError): OnClose;
|
|
17
18
|
};
|
|
18
19
|
type DbClientOpts = {
|
|
19
20
|
hooks: DbClientHooks;
|
|
@@ -42,11 +43,6 @@ export declare class DbClient {
|
|
|
42
43
|
o: Record<string, any>;
|
|
43
44
|
p: Promise<number | ModifyRes>;
|
|
44
45
|
}>;
|
|
45
|
-
subscriptionsInProgress: boolean;
|
|
46
|
-
subscriptonThrottleMs: number;
|
|
47
|
-
subscriptions: SubscriptionsMap;
|
|
48
|
-
subscriptionMarkers: SubscriptionMarkerMap;
|
|
49
|
-
subscriptionsToRun: SubscriptionsToRun;
|
|
50
46
|
schemaChecksum: number;
|
|
51
47
|
setSchema(schema: Schema, fromStart?: boolean, transformFns?: TransformFns): Promise<StrictSchema>;
|
|
52
48
|
putLocalSchema(schema: any): DbClientSchema;
|
package/dist/src/client/index.js
CHANGED
|
@@ -47,12 +47,6 @@ export class DbClient {
|
|
|
47
47
|
modifyCtx;
|
|
48
48
|
maxModifySize;
|
|
49
49
|
upserting = new Map();
|
|
50
|
-
// subscriptions
|
|
51
|
-
subscriptionsInProgress = false;
|
|
52
|
-
subscriptonThrottleMs = 20;
|
|
53
|
-
subscriptions = new Map();
|
|
54
|
-
subscriptionMarkers = {};
|
|
55
|
-
subscriptionsToRun = [];
|
|
56
50
|
schemaChecksum;
|
|
57
51
|
async setSchema(schema, fromStart, transformFns) {
|
|
58
52
|
this.schemaIsSetValue = true;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PropDef, PropDefEdge, SchemaPropTree } from '@based/schema/def';
|
|
2
|
-
import { SubscriptionMarkersCheck } from '../query/subscription/index.js';
|
|
3
2
|
import { DbClient } from '../index.js';
|
|
4
3
|
import { ModifyOpts } from './types.js';
|
|
5
4
|
import { LangCode } from '@based/schema';
|
|
@@ -12,8 +11,7 @@ export declare class ModifyError extends Error {
|
|
|
12
11
|
}
|
|
13
12
|
export declare class ModifyState {
|
|
14
13
|
#private;
|
|
15
|
-
constructor(typeId: number, tmpId: number, db: DbClient,
|
|
16
|
-
subMarkers: SubscriptionMarkersCheck | false;
|
|
14
|
+
constructor(typeId: number, tmpId: number, db: DbClient, opts: ModifyOpts, update?: boolean);
|
|
17
15
|
update: boolean;
|
|
18
16
|
locale: LangCode;
|
|
19
17
|
tmpId: number;
|
|
@@ -42,17 +42,15 @@ export class ModifyError extends Error {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
export class ModifyState {
|
|
45
|
-
constructor(typeId, tmpId, db,
|
|
45
|
+
constructor(typeId, tmpId, db, opts, update = false) {
|
|
46
46
|
this.tmpId = tmpId;
|
|
47
47
|
this.#typeId = typeId;
|
|
48
48
|
this.#ctx = db.modifyCtx.ctx;
|
|
49
|
-
this.subMarkers = subMarkers;
|
|
50
49
|
this.update = update;
|
|
51
50
|
if (opts?.locale) {
|
|
52
51
|
this.locale = langCodesMap.get(opts.locale);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
|
-
subMarkers;
|
|
56
54
|
update;
|
|
57
55
|
locale;
|
|
58
56
|
#ctx;
|
|
@@ -5,7 +5,6 @@ import { modify } from './modify.js';
|
|
|
5
5
|
import { ModifyState } from './ModifyRes.js';
|
|
6
6
|
import { CREATE, RANGE_ERR, ADD_EMPTY_SORT, ADD_EMPTY_SORT_TEXT, } from './types.js';
|
|
7
7
|
import { writeFixedValue } from './fixed.js';
|
|
8
|
-
import { getSubscriptionMarkers } from '../query/subscription/index.js';
|
|
9
8
|
const appendCreate = (ctx, def, obj, res, unsafe) => {
|
|
10
9
|
const len = ctx.len;
|
|
11
10
|
let err = modify(ctx, res, obj, def, CREATE, def.tree, true, unsafe);
|
|
@@ -136,7 +135,7 @@ export function create(db, type, obj, opts) {
|
|
|
136
135
|
id = def.lastId + 1;
|
|
137
136
|
}
|
|
138
137
|
const ctx = db.modifyCtx;
|
|
139
|
-
const res = new ModifyState(def.id, id, db,
|
|
138
|
+
const res = new ModifyState(def.id, id, db, opts);
|
|
140
139
|
const pos = ctx.len;
|
|
141
140
|
const err = appendCreate(ctx, def, obj, res, opts?.unsafe);
|
|
142
141
|
if (err) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { flushBuffer, startDrain } from '../flushModify.js';
|
|
2
|
-
import { getSubscriptionMarkers } from '../query/subscription/markers.js';
|
|
3
2
|
import { ModifyState } from './ModifyRes.js';
|
|
4
3
|
import { setCursor } from './setCursor.js';
|
|
5
4
|
import { UPDATE, DELETE_SORT_INDEX, DELETE_NODE, } from './types.js';
|
|
@@ -10,7 +9,7 @@ export const deleteFn = (db, type, id, opts) => {
|
|
|
10
9
|
throw new Error(`Unknown type: ${type}. Did you mean on of: ${Object.keys(db.schemaTypesParsed).join(', ')}`);
|
|
11
10
|
}
|
|
12
11
|
const ctx = db.modifyCtx;
|
|
13
|
-
const res = new ModifyState(def.id, id, db,
|
|
12
|
+
const res = new ModifyState(def.id, id, db, opts);
|
|
14
13
|
const schema = db.schemaTypesParsed[type];
|
|
15
14
|
const separate = schema.separate;
|
|
16
15
|
if (separate) {
|
|
@@ -11,7 +11,6 @@ import { appendFixedValue, writeFixedValue } from './fixed.js';
|
|
|
11
11
|
import { writeAlias } from './alias.js';
|
|
12
12
|
import { writeHll } from './cardinality.js';
|
|
13
13
|
import { writeVector } from './vector.js';
|
|
14
|
-
import { checkSubscriptionMarkers } from '../query/subscription/index.js';
|
|
15
14
|
import { writeJson } from './json.js';
|
|
16
15
|
function _modify(ctx, res, obj, schema, mod, tree, overwrite, unsafe) {
|
|
17
16
|
for (const key in obj) {
|
|
@@ -28,9 +27,6 @@ function _modify(ctx, res, obj, schema, mod, tree, overwrite, unsafe) {
|
|
|
28
27
|
if (val === undefined) {
|
|
29
28
|
continue;
|
|
30
29
|
}
|
|
31
|
-
if (res.subMarkers) {
|
|
32
|
-
checkSubscriptionMarkers(ctx.db, res.subMarkers, def);
|
|
33
|
-
}
|
|
34
30
|
const type = def.typeIndex;
|
|
35
31
|
if (def.separate) {
|
|
36
32
|
if (type === STRING) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CREATE, SWITCH_FIELD, SWITCH_ID_CREATE, SWITCH_ID_UPDATE, SWITCH_TYPE, } from './types.js';
|
|
2
|
-
export const setCursor = (ctx, schema, field, //
|
|
2
|
+
export const setCursor = (ctx, schema, field, // TODO pass propdef better
|
|
3
3
|
typeIndex, id, modifyOp, ignoreField) => {
|
|
4
4
|
const prefix0 = schema.idUint8[0];
|
|
5
5
|
const prefix1 = schema.idUint8[1];
|
|
@@ -5,7 +5,6 @@ import { modify } from './modify.js';
|
|
|
5
5
|
import { ModifyState } from './ModifyRes.js';
|
|
6
6
|
import { RANGE_ERR, UPDATE } from './types.js';
|
|
7
7
|
import { appendFixedValue } from './fixed.js';
|
|
8
|
-
import { getSubscriptionMarkers } from '../query/subscription/index.js';
|
|
9
8
|
const appendUpdate = (ctx, def, obj, res, overwrite) => {
|
|
10
9
|
const err = modify(ctx, res, obj, def, UPDATE, def.tree, overwrite);
|
|
11
10
|
if (err) {
|
|
@@ -62,7 +61,7 @@ export const update = (db, type, id, obj, opts) => {
|
|
|
62
61
|
}
|
|
63
62
|
const ctx = db.modifyCtx;
|
|
64
63
|
const pos = ctx.len;
|
|
65
|
-
const res = new ModifyState(def.id, id, db,
|
|
64
|
+
const res = new ModifyState(def.id, id, db, opts, true);
|
|
66
65
|
const err = appendUpdate(ctx, def, obj, res, opts?.overwrite);
|
|
67
66
|
if (err) {
|
|
68
67
|
ctx.prefix0 = -1; // force a new cursor
|
|
@@ -146,7 +146,8 @@ const handleUndefinedProps = (id, q, item) => {
|
|
|
146
146
|
if (lang.has(0)) {
|
|
147
147
|
for (const locale in q.schema.locales) {
|
|
148
148
|
if (!lan[locale]) {
|
|
149
|
-
|
|
149
|
+
// console.log('???', locale, prop.default)
|
|
150
|
+
lan[locale] = prop.default[locale] || '';
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
}
|
|
@@ -154,16 +155,24 @@ const handleUndefinedProps = (id, q, item) => {
|
|
|
154
155
|
for (const code of lang) {
|
|
155
156
|
const locale = inverseLangMap.get(code);
|
|
156
157
|
if (!lan[locale]) {
|
|
157
|
-
lan[locale] = '';
|
|
158
|
+
lan[locale] = prop.default[locale] || '';
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
else if (prop.typeIndex === BINARY) {
|
|
163
|
-
addField(prop,
|
|
164
|
+
addField(prop, prop.default, item);
|
|
165
|
+
}
|
|
166
|
+
else if (prop.typeIndex === TEXT) {
|
|
167
|
+
// q.lang
|
|
168
|
+
// console.log('???')
|
|
169
|
+
addField(prop, '', item);
|
|
164
170
|
}
|
|
165
171
|
else {
|
|
166
|
-
|
|
172
|
+
1;
|
|
173
|
+
if (prop.default !== undefined) {
|
|
174
|
+
addField(prop, prop.default, item);
|
|
175
|
+
}
|
|
167
176
|
}
|
|
168
177
|
}
|
|
169
178
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BasedDbQuery } from '../BasedDbQuery.js';
|
|
2
2
|
import { OnData, OnError, OnClose } from './types.js';
|
|
3
|
+
export declare const subscribe: (q: BasedDbQuery, onData: OnData, onError?: OnError) => OnClose;
|
|
3
4
|
export * from './types.js';
|
|
4
|
-
export * from './markers.js';
|
|
5
|
-
export declare const subscribe: (q: BasedDbQuery, onData: OnData, onError: OnError) => OnClose;
|
|
@@ -1,58 +1,11 @@
|
|
|
1
1
|
import { includeField } from '../query.js';
|
|
2
2
|
import { registerQuery } from '../registerQuery.js';
|
|
3
|
-
import { runSubscription } from './run.js';
|
|
4
|
-
import { addSubscriptionMarkers, deleteSubscriptionMarkers } from './markers.js';
|
|
5
|
-
export * from './types.js';
|
|
6
|
-
export * from './markers.js';
|
|
7
3
|
export const subscribe = (q, onData, onError) => {
|
|
8
|
-
let closed = false;
|
|
9
4
|
if (!q.def.include.stringFields.size && !q.def.references.size) {
|
|
10
5
|
includeField(q.def, '*');
|
|
11
6
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
catch (err) {
|
|
16
|
-
onError(err);
|
|
17
|
-
return () => q;
|
|
18
|
-
}
|
|
19
|
-
if (!q.db.subscriptions.has(q.id)) {
|
|
20
|
-
const subscription = {
|
|
21
|
-
query: q,
|
|
22
|
-
subs: new Set(),
|
|
23
|
-
inProgress: false,
|
|
24
|
-
closed: false,
|
|
25
|
-
};
|
|
26
|
-
q.db.subscriptions.set(q.id, subscription);
|
|
27
|
-
addSubscriptionMarkers(q, subscription);
|
|
28
|
-
}
|
|
29
|
-
const fn = (res, err) => {
|
|
30
|
-
if (!closed) {
|
|
31
|
-
if (err) {
|
|
32
|
-
onError(err);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
onData(res);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
const sub = q.db.subscriptions.get(q.id);
|
|
40
|
-
const close = () => {
|
|
41
|
-
sub.subs.delete(fn);
|
|
42
|
-
if (sub.subs.size === 0) {
|
|
43
|
-
q.db.subscriptions.delete(q.id);
|
|
44
|
-
deleteSubscriptionMarkers(q);
|
|
45
|
-
}
|
|
46
|
-
closed = true;
|
|
47
|
-
return q;
|
|
48
|
-
};
|
|
49
|
-
sub.subs.add(fn);
|
|
50
|
-
if (sub.res) {
|
|
51
|
-
onData(sub.res);
|
|
52
|
-
}
|
|
53
|
-
if (!sub.inProgress) {
|
|
54
|
-
runSubscription(sub);
|
|
55
|
-
}
|
|
56
|
-
return close;
|
|
7
|
+
registerQuery(q);
|
|
8
|
+
return q.db.hooks.subscribe(q, onData, onError);
|
|
57
9
|
};
|
|
10
|
+
export * from './types.js';
|
|
58
11
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,33 +1,5 @@
|
|
|
1
1
|
import { BasedQueryResponse } from '../BasedIterable.js';
|
|
2
|
-
import { BasedDbQuery } from '../BasedDbQuery.js';
|
|
3
2
|
export type OnData = (res: BasedQueryResponse) => any;
|
|
4
3
|
export type OnError = (err: Error) => any;
|
|
5
|
-
export type OnClose = () =>
|
|
4
|
+
export type OnClose = () => any;
|
|
6
5
|
export type OnSubscription = (res: any, err?: Error) => void;
|
|
7
|
-
export type Subscription = {
|
|
8
|
-
query: BasedDbQuery;
|
|
9
|
-
subs: Set<OnSubscription>;
|
|
10
|
-
res?: BasedQueryResponse;
|
|
11
|
-
closed: boolean;
|
|
12
|
-
inProgress: boolean;
|
|
13
|
-
};
|
|
14
|
-
export type SubscriptionsMap = Map<number, Subscription>;
|
|
15
|
-
export type SubscriptionsToRun = Subscription[];
|
|
16
|
-
export type SubscriptionMarkers = {
|
|
17
|
-
main: {
|
|
18
|
-
[start: string]: Subscription[];
|
|
19
|
-
};
|
|
20
|
-
props: {
|
|
21
|
-
[prop: string]: Subscription[];
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
export type SubscriptionMarkerMap = {
|
|
25
|
-
[typeID: string]: {
|
|
26
|
-
ids: Map<number, SubscriptionMarkers>;
|
|
27
|
-
collection: SubscriptionMarkers;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
export type SubscriptionMarkersCheck = {
|
|
31
|
-
collection: SubscriptionMarkers | false;
|
|
32
|
-
ids: SubscriptionMarkers | false;
|
|
33
|
-
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//
|
|
2
|
+
// export type Subscription = {
|
|
3
|
+
// query: BasedDbQuery
|
|
4
|
+
// subs: Set<OnSubscription>
|
|
5
|
+
// res?: BasedQueryResponse
|
|
6
|
+
// closed: boolean
|
|
7
|
+
// inProgress: boolean // dont need to check
|
|
8
|
+
// // filter - realy nice to add
|
|
9
|
+
// }
|
|
3
10
|
//# sourceMappingURL=types.js.map
|
|
@@ -10,7 +10,7 @@ export const write = (buf, value, offset, noCompression, lang) => {
|
|
|
10
10
|
buf[offset] = lang || 0;
|
|
11
11
|
const { written: l } = ENCODER.encodeInto(value, buf.subarray(offset + 2));
|
|
12
12
|
let crc = native.crc32(buf.subarray(offset + 2, offset + 2 + l));
|
|
13
|
-
// 50 maybe if lvl 1
|
|
13
|
+
// 50 len maybe if lvl 1
|
|
14
14
|
if (value.length > 200 && !noCompression) {
|
|
15
15
|
buf.copyWithin(offset + 6 + l, offset + 2, offset + 2 + l);
|
|
16
16
|
const size = native.compress(buf, offset + 6, l);
|
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
|
|
@@ -44,6 +45,33 @@ export class BasedDb {
|
|
|
44
45
|
const client = new DbClient({
|
|
45
46
|
maxModifySize,
|
|
46
47
|
hooks: {
|
|
48
|
+
subscribe(q, onData, onError) {
|
|
49
|
+
let timer;
|
|
50
|
+
let prevChecksum;
|
|
51
|
+
let lastLen = 0;
|
|
52
|
+
let response;
|
|
53
|
+
const get = async () => {
|
|
54
|
+
const res = await server.getQueryBuf(q.buffer);
|
|
55
|
+
if (!response) {
|
|
56
|
+
response = new BasedQueryResponse(q.id, q.def, res, 0);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
response.result = res;
|
|
60
|
+
response.end = res.byteLength;
|
|
61
|
+
}
|
|
62
|
+
const checksum = response.checksum;
|
|
63
|
+
if (lastLen != res.byteLength || checksum != prevChecksum) {
|
|
64
|
+
onData(response);
|
|
65
|
+
lastLen = res.byteLength;
|
|
66
|
+
prevChecksum = checksum;
|
|
67
|
+
}
|
|
68
|
+
setTimeout(get, 200);
|
|
69
|
+
};
|
|
70
|
+
get();
|
|
71
|
+
return () => {
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
};
|
|
74
|
+
},
|
|
47
75
|
setSchema(schema, fromStart) {
|
|
48
76
|
return Promise.resolve(server.setSchema(schema, fromStart));
|
|
49
77
|
},
|
package/dist/src/native.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
declare const native: {
|
|
2
2
|
historyAppend(history: any, typeId: number, nodeId: number, dbCtx: any): any;
|
|
3
3
|
historyCreate(pathname: string, mainLen: number): any;
|
|
4
4
|
workerCtxInit: () => void;
|
|
@@ -24,4 +24,4 @@ declare const _default: {
|
|
|
24
24
|
equals: (a: Uint8Array, b: Uint8Array) => boolean;
|
|
25
25
|
expire: (dbCtx: any) => void;
|
|
26
26
|
};
|
|
27
|
-
export default
|
|
27
|
+
export default native;
|
package/dist/src/native.js
CHANGED
|
@@ -11,7 +11,7 @@ function SelvaIoErrlogToString(buf) {
|
|
|
11
11
|
let len = (i = buf.indexOf(0)) >= 0 ? i : buf.byteLength;
|
|
12
12
|
return DECODER.decode(selvaIoErrlog.slice(0, len));
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
const native = {
|
|
15
15
|
historyAppend(history, typeId, nodeId, dbCtx) {
|
|
16
16
|
return db.historyAppend(history, typeId, nodeId, dbCtx);
|
|
17
17
|
},
|
|
@@ -97,4 +97,6 @@ export default {
|
|
|
97
97
|
db.expire(dbCtx);
|
|
98
98
|
},
|
|
99
99
|
};
|
|
100
|
+
global.__basedDb__native__ = native;
|
|
101
|
+
export default native;
|
|
100
102
|
//# sourceMappingURL=native.js.map
|
package/dist/src/server/save.js
CHANGED
|
@@ -12,9 +12,8 @@ function saveRange(db, typeId, start, end, hashOut) {
|
|
|
12
12
|
const file = block_sdb_file(typeId, start, end);
|
|
13
13
|
const path = join(db.fileSystemPath, file);
|
|
14
14
|
const err = native.saveRange(path, typeId, start, end, db.dbCtxExternal, hashOut);
|
|
15
|
-
if (err == -8) {
|
|
16
|
-
//
|
|
17
|
-
return '';
|
|
15
|
+
if (err == -8) { // TODO ENOENT
|
|
16
|
+
return ''; // empty range
|
|
18
17
|
}
|
|
19
18
|
else if (err) {
|
|
20
19
|
// TODO print the error string
|
|
@@ -61,18 +60,16 @@ export function save(db, sync = false, forceFullDump = false) {
|
|
|
61
60
|
else {
|
|
62
61
|
foreachDirtyBlock(db, (mtKey, typeId, start, end) => {
|
|
63
62
|
const hash = new Uint8Array(16);
|
|
64
|
-
// TODO Don't save if empty
|
|
65
63
|
const file = saveRange(db, typeId, start, end, hash);
|
|
66
64
|
if (file === null) {
|
|
67
65
|
// The previous state should remain in the merkle tree for
|
|
68
66
|
// load and sync purposes.
|
|
69
67
|
return;
|
|
70
68
|
}
|
|
71
|
-
else if (file.length === 0) {
|
|
72
|
-
// The range is empty
|
|
73
|
-
}
|
|
74
69
|
else {
|
|
75
70
|
const oldLeaf = db.merkleTree.search(mtKey);
|
|
71
|
+
// If (file.length === 0) then the range is empty but that's fine,
|
|
72
|
+
// we'll keep them around for now to maintain the order of the tree.
|
|
76
73
|
if (oldLeaf) {
|
|
77
74
|
oldLeaf.data.file = file;
|
|
78
75
|
db.merkleTree.update(mtKey, hash);
|
package/dist/src/server/start.js
CHANGED
|
@@ -36,11 +36,13 @@ export async function start(db, opts) {
|
|
|
36
36
|
const dumps = writelog.rangeDumps[typeId];
|
|
37
37
|
for (const dump of dumps) {
|
|
38
38
|
const fname = dump.file;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
if (fname?.length > 0) {
|
|
40
|
+
try {
|
|
41
|
+
native.loadRange(join(path, fname), db.dbCtxExternal);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
console.error(e.message);
|
|
45
|
+
}
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
}
|
|
@@ -71,7 +73,7 @@ export async function start(db, opts) {
|
|
|
71
73
|
end,
|
|
72
74
|
};
|
|
73
75
|
db.merkleTree.insert(mtKey, hash, data);
|
|
74
|
-
});
|
|
76
|
+
}, true);
|
|
75
77
|
}
|
|
76
78
|
if (writelog?.hash) {
|
|
77
79
|
const oldHash = hexToBuf(writelog.hash);
|
|
@@ -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
|
}
|