@based/db 0.0.30 → 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.
Files changed (30) hide show
  1. package/dist/lib/darwin_aarch64/include/selva/db.h +2 -1
  2. package/dist/lib/darwin_aarch64/include/selva/fields.h +10 -5
  3. package/dist/lib/darwin_aarch64/include/selva/types.h +3 -1
  4. package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
  5. package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
  6. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  7. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  8. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  9. package/dist/lib/linux_aarch64/include/selva/db.h +2 -1
  10. package/dist/lib/linux_aarch64/include/selva/fields.h +10 -5
  11. package/dist/lib/linux_aarch64/include/selva/types.h +3 -1
  12. package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
  13. package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
  14. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  15. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  16. package/dist/lib/linux_aarch64/libselva.so +0 -0
  17. package/dist/lib/linux_x86_64/include/selva/db.h +2 -1
  18. package/dist/lib/linux_x86_64/include/selva/fields.h +10 -5
  19. package/dist/lib/linux_x86_64/include/selva/types.h +3 -1
  20. package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
  21. package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
  22. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  23. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  24. package/dist/lib/linux_x86_64/libselva.so +0 -0
  25. package/dist/src/index.js +26 -2
  26. package/dist/src/server/save.js +4 -7
  27. package/dist/src/server/start.js +8 -6
  28. package/dist/src/server/tree.d.ts +1 -1
  29. package/dist/src/server/tree.js +2 -2
  30. 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.
@@ -341,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
341
341
 
342
342
  /**
343
343
  * Delete field.
344
+ * @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
344
345
  */
345
346
  SELVA_EXPORT
346
- int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
347
- __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)));
348
349
 
349
350
  /**
350
351
  * Delete an edge from a references field.
@@ -352,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
352
353
  SELVA_EXPORT
353
354
  int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
354
355
 
356
+ /**
357
+ * Clear a references field but don't free it.
358
+ */
355
359
  SELVA_EXPORT
356
- void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
357
- __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)));
358
362
 
359
363
  /**
360
364
  * Init the fields struct of a node or edge.
@@ -369,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
369
373
  * regardless wether the schema defines fields for this node.
370
374
  */
371
375
  SELVA_EXPORT
372
- 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)));
373
378
 
374
379
  SELVA_EXPORT
375
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 SELVA_FIELD_TYPE_WEAK_REFERENCES it's saved
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
 
@@ -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.
@@ -341,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
341
341
 
342
342
  /**
343
343
  * Delete field.
344
+ * @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
344
345
  */
345
346
  SELVA_EXPORT
346
- int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
347
- __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)));
348
349
 
349
350
  /**
350
351
  * Delete an edge from a references field.
@@ -352,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
352
353
  SELVA_EXPORT
353
354
  int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
354
355
 
356
+ /**
357
+ * Clear a references field but don't free it.
358
+ */
355
359
  SELVA_EXPORT
356
- void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
357
- __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)));
358
362
 
359
363
  /**
360
364
  * Init the fields struct of a node or edge.
@@ -369,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
369
373
  * regardless wether the schema defines fields for this node.
370
374
  */
371
375
  SELVA_EXPORT
372
- 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)));
373
378
 
374
379
  SELVA_EXPORT
375
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 SELVA_FIELD_TYPE_WEAK_REFERENCES it's saved
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
@@ -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.
@@ -341,10 +341,11 @@ struct SelvaFieldsPointer selva_fields_get_raw(struct SelvaNode *node, const str
341
341
 
342
342
  /**
343
343
  * Delete field.
344
+ * @param dirty_cb will be called with the deleted node_id in case of a reference(s) field.
344
345
  */
345
346
  SELVA_EXPORT
346
- int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
347
- __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)));
348
349
 
349
350
  /**
350
351
  * Delete an edge from a references field.
@@ -352,9 +353,12 @@ int selva_fields_del(struct SelvaDb *db, struct SelvaNode *node, const struct Se
352
353
  SELVA_EXPORT
353
354
  int selva_fields_del_ref(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs, node_id_t dst_node_id);
354
355
 
356
+ /**
357
+ * Clear a references field but don't free it.
358
+ */
355
359
  SELVA_EXPORT
356
- void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs)
357
- __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)));
358
362
 
359
363
  /**
360
364
  * Init the fields struct of a node or edge.
@@ -369,7 +373,8 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
369
373
  * regardless wether the schema defines fields for this node.
370
374
  */
371
375
  SELVA_EXPORT
372
- 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)));
373
378
 
374
379
  SELVA_EXPORT
375
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 SELVA_FIELD_TYPE_WEAK_REFERENCES it's saved
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
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
@@ -45,8 +46,31 @@ export class BasedDb {
45
46
  maxModifySize,
46
47
  hooks: {
47
48
  subscribe(q, onData, onError) {
48
- console.warn('Subscription not supported without based-server!');
49
- return () => { };
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
+ };
50
74
  },
51
75
  setSchema(schema, fromStart) {
52
76
  return Promise.resolve(server.setSchema(schema, fromStart));
@@ -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
- // TODO ENOENT
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);
@@ -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
- try {
40
- native.loadRange(join(path, fname), db.dbCtxExternal);
41
- }
42
- catch (e) {
43
- console.error(e.message);
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>;
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@based/db",
3
- "version": "0.0.30",
3
+ "version": "0.0.31",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",