@dxos/echo-pipeline 0.1.36 → 0.1.37-next.8c6108a

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.
@@ -1,10 +1,8 @@
1
1
  import "@dxos/node-std/globals"
2
2
 
3
3
  // packages/core/echo/echo-pipeline/src/metadata/metadata-store.ts
4
- import CRC32 from "crc-32";
5
4
  import assert from "@dxos/node-std/assert";
6
5
  import { synchronized } from "@dxos/async";
7
- import { DataCorruptionError } from "@dxos/errors";
8
6
  import { log } from "@dxos/log";
9
7
  import { schema } from "@dxos/protocols";
10
8
  var __decorate = function(decorators, target, key, desc) {
@@ -49,35 +47,31 @@ var MetadataStore = class {
49
47
  const file = this._directory.getOrCreateFile("EchoMetadata");
50
48
  try {
51
49
  const { size: fileLength } = await file.stat();
52
- if (fileLength < 8) {
50
+ if (fileLength < 4) {
53
51
  return;
54
52
  }
55
53
  const dataSize = fromBytesInt32(await file.read(0, 4));
56
- const checksum = fromBytesInt32(await file.read(4, 4));
57
54
  log("loaded", {
58
- size: dataSize,
59
- checksum
55
+ size: dataSize
60
56
  }, {
61
57
  file: "metadata-store.ts",
62
- line: 70,
58
+ line: 67,
63
59
  scope: this,
64
60
  callSite: (f, a) => f(...a)
65
61
  });
66
- if (fileLength < dataSize + 8) {
67
- throw new DataCorruptionError("Metadata size is smaller than expected.");
68
- }
69
- const data = await file.read(8, dataSize);
70
- const calculatedChecksum = CRC32.buf(data);
71
- if (calculatedChecksum !== checksum) {
72
- throw new DataCorruptionError("Metadata checksum is invalid.");
62
+ {
63
+ if (fileLength < dataSize + 4) {
64
+ throw new Error("Metadata storage is corrupted");
65
+ }
73
66
  }
67
+ const data = await file.read(4, dataSize);
74
68
  this._metadata = schema.getCodecForType("dxos.echo.metadata.EchoMetadata").decode(data);
75
69
  } catch (err) {
76
70
  log.error("failed to load metadata", {
77
71
  err
78
72
  }, {
79
73
  file: "metadata-store.ts",
80
- line: 85,
74
+ line: 79,
81
75
  scope: this,
82
76
  callSite: (f, a) => f(...a)
83
77
  });
@@ -97,21 +91,16 @@ var MetadataStore = class {
97
91
  const file = this._directory.getOrCreateFile("EchoMetadata");
98
92
  try {
99
93
  const encoded = Buffer.from(schema.getCodecForType("dxos.echo.metadata.EchoMetadata").encode(data));
100
- const checksum = CRC32.buf(encoded);
101
- const result = Buffer.alloc(8 + encoded.length);
102
- result.writeInt32LE(encoded.length, 0);
103
- result.writeInt32LE(checksum, 4);
104
- encoded.copy(result, 8);
105
- await file.write(0, result);
94
+ await file.write(0, toBytesInt32(encoded.length));
106
95
  log("saved", {
107
- size: encoded.length,
108
- checksum
96
+ size: encoded.length
109
97
  }, {
110
98
  file: "metadata-store.ts",
111
- line: 116,
99
+ line: 102,
112
100
  scope: this,
113
101
  callSite: (f, a) => f(...a)
114
102
  });
103
+ await file.write(4, encoded);
115
104
  } finally {
116
105
  await file.close();
117
106
  }
@@ -122,7 +111,7 @@ var MetadataStore = class {
122
111
  async clear() {
123
112
  log("clearing all metadata", {}, {
124
113
  file: "metadata-store.ts",
125
- line: 126,
114
+ line: 115,
126
115
  scope: this,
127
116
  callSite: (f, a) => f(...a)
128
117
  });
@@ -168,6 +157,11 @@ __decorate([
168
157
  __decorate([
169
158
  synchronized
170
159
  ], MetadataStore.prototype, "_save", null);
160
+ var toBytesInt32 = (num) => {
161
+ const buf = Buffer.alloc(4);
162
+ buf.writeInt32LE(num, 0);
163
+ return buf;
164
+ };
171
165
  var fromBytesInt32 = (buf) => buf.readInt32LE(0);
172
166
 
173
167
  // packages/core/echo/echo-pipeline/src/common/codec.ts
@@ -218,31 +212,17 @@ var TimeframeClock = class {
218
212
  constructor(_timeframe = new Timeframe()) {
219
213
  this._timeframe = _timeframe;
220
214
  this.update = new Event();
221
- this._pendingTimeframe = _timeframe;
222
215
  }
223
- /**
224
- * Timeframe that was processed by ECHO.
225
- */
226
216
  get timeframe() {
227
217
  return this._timeframe;
228
218
  }
229
- /**
230
- * Timeframe that is currently being processed by ECHO.
231
- * Will be equal to `timeframe` after the processing is complete.
232
- */
233
- get pendingTimeframe() {
234
- return this._pendingTimeframe;
235
- }
236
- updatePendingTimeframe(key, seq) {
237
- this._pendingTimeframe = Timeframe.merge(this._pendingTimeframe, new Timeframe([
219
+ updateTimeframe(key, seq) {
220
+ this._timeframe = Timeframe.merge(this._timeframe, new Timeframe([
238
221
  [
239
222
  key,
240
223
  seq
241
224
  ]
242
225
  ]));
243
- }
244
- updateTimeframe() {
245
- this._timeframe = this._pendingTimeframe;
246
226
  this.update.emit(this._timeframe);
247
227
  }
248
228
  hasGaps(timeframe) {
@@ -255,7 +235,7 @@ var TimeframeClock = class {
255
235
  current: this._timeframe
256
236
  }, {
257
237
  file: "timeframe-clock.ts",
258
- line: 67,
238
+ line: 48,
259
239
  scope: this,
260
240
  callSite: (f, a) => f(...a)
261
241
  });
@@ -266,7 +246,7 @@ var TimeframeClock = class {
266
246
  deps: Timeframe.dependencies(target, this._timeframe)
267
247
  }, {
268
248
  file: "timeframe-clock.ts",
269
- line: 69,
249
+ line: 50,
270
250
  scope: this,
271
251
  callSite: (f, a) => f(...a)
272
252
  });
@@ -336,9 +316,6 @@ var PipelineState = class {
336
316
  get timeframe() {
337
317
  return this._timeframeClock.timeframe;
338
318
  }
339
- get pendingTimeframe() {
340
- return this._timeframeClock.pendingTimeframe;
341
- }
342
319
  get targetTimeframe() {
343
320
  return this._targetTimeframe ? this._targetTimeframe : new Timeframe2();
344
321
  }
@@ -366,7 +343,7 @@ var PipelineState = class {
366
343
  target: this.targetTimeframe
367
344
  }, {
368
345
  file: "pipeline.ts",
369
- line: 105,
346
+ line: 101,
370
347
  scope: this,
371
348
  callSite: (f, a) => f(...a)
372
349
  });
@@ -396,7 +373,7 @@ var PipelineState = class {
396
373
  dependencies: Timeframe2.dependencies(this.targetTimeframe, this.timeframe)
397
374
  }, {
398
375
  file: "pipeline.ts",
399
- line: 131,
376
+ line: 127,
400
377
  scope: this,
401
378
  callSite: (f, a) => f(...a)
402
379
  });
@@ -422,7 +399,7 @@ var Pipeline = class {
422
399
  this._feedSetIterator.stalled.on((iterator) => {
423
400
  log4.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, {}, {
424
401
  file: "pipeline.ts",
425
- line: 207,
402
+ line: 203,
426
403
  scope: this,
427
404
  callSite: (f, a) => f(...a)
428
405
  });
@@ -457,14 +434,14 @@ var Pipeline = class {
457
434
  async start() {
458
435
  log4("starting...", {}, {
459
436
  file: "pipeline.ts",
460
- line: 249,
437
+ line: 245,
461
438
  scope: this,
462
439
  callSite: (f, a) => f(...a)
463
440
  });
464
441
  await this._feedSetIterator.open();
465
442
  log4("started", {}, {
466
443
  file: "pipeline.ts",
467
- line: 251,
444
+ line: 247,
468
445
  scope: this,
469
446
  callSite: (f, a) => f(...a)
470
447
  });
@@ -472,7 +449,7 @@ var Pipeline = class {
472
449
  async stop() {
473
450
  log4("stopping...", {}, {
474
451
  file: "pipeline.ts",
475
- line: 256,
452
+ line: 252,
476
453
  scope: this,
477
454
  callSite: (f, a) => f(...a)
478
455
  });
@@ -480,7 +457,7 @@ var Pipeline = class {
480
457
  await this._processingTrigger.wait();
481
458
  log4("stopped", {}, {
482
459
  file: "pipeline.ts",
483
- line: 259,
460
+ line: 255,
484
461
  scope: this,
485
462
  callSite: (f, a) => f(...a)
486
463
  });
@@ -494,10 +471,9 @@ var Pipeline = class {
494
471
  this._isOpen = true;
495
472
  for await (const block of this._feedSetIterator) {
496
473
  this._processingTrigger.reset();
497
- this._timeframeClock.updatePendingTimeframe(PublicKey.from(block.feedKey), block.seq);
498
474
  yield block;
499
475
  this._processingTrigger.wake();
500
- this._timeframeClock.updateTimeframe();
476
+ this._timeframeClock.updateTimeframe(PublicKey.from(block.feedKey), block.seq);
501
477
  }
502
478
  this._isOpen = false;
503
479
  }
@@ -1530,7 +1506,7 @@ var DataServiceImpl = class {
1530
1506
 
1531
1507
  // packages/core/echo/echo-pipeline/src/space/data-pipeline.ts
1532
1508
  import assert9 from "@dxos/node-std/assert";
1533
- import { scheduleTask as scheduleTask2, synchronized as synchronized5, trackLeaks as trackLeaks4 } from "@dxos/async";
1509
+ import { Event as Event3, scheduleTask as scheduleTask2, synchronized as synchronized5, trackLeaks as trackLeaks4 } from "@dxos/async";
1534
1510
  import { Context as Context3 } from "@dxos/context";
1535
1511
  import { failUndefined as failUndefined3 } from "@dxos/debug";
1536
1512
  import { ItemManager } from "@dxos/echo-db";
@@ -1556,8 +1532,7 @@ var DataPipeline = class DataPipeline2 {
1556
1532
  this._ctx = new Context3();
1557
1533
  this._lastAutomaticSnapshotTimeframe = new Timeframe3();
1558
1534
  this._isOpen = false;
1559
- this._lastTimeframeSaveTime = 0;
1560
- this._lastSnapshotSaveTime = 0;
1535
+ this.onTimeframeReached = new Event3();
1561
1536
  }
1562
1537
  get isOpen() {
1563
1538
  return this._isOpen;
@@ -1602,8 +1577,58 @@ var DataPipeline = class DataPipeline2 {
1602
1577
  scheduleTask2(this._ctx, async () => {
1603
1578
  await this._consumePipeline();
1604
1579
  });
1580
+ this._createPeriodicSnapshots();
1605
1581
  this._isOpen = true;
1606
1582
  }
1583
+ _createPeriodicSnapshots() {
1584
+ this.onTimeframeReached.debounce(TIMEFRAME_SAVE_DEBOUNCE_INTERVAL).on(this._ctx, async () => {
1585
+ await this._saveLatestTimeframe();
1586
+ });
1587
+ if (!DISABLE_SNAPSHOT_CACHE) {
1588
+ this.onTimeframeReached.debounce(AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL).on(this._ctx, async () => {
1589
+ var _a, _b;
1590
+ const latestTimeframe = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe;
1591
+ if (!latestTimeframe) {
1592
+ return;
1593
+ }
1594
+ if (latestTimeframe.totalMessages() - this._lastAutomaticSnapshotTimeframe.totalMessages() > MESSAGES_PER_SNAPSHOT) {
1595
+ const snapshot = await this._saveSnapshot();
1596
+ this._lastAutomaticSnapshotTimeframe = (_b = snapshot.timeframe) != null ? _b : failUndefined3();
1597
+ log12("save", {
1598
+ snapshot
1599
+ }, {
1600
+ file: "data-pipeline.ts",
1601
+ line: 161,
1602
+ scope: this,
1603
+ callSite: (f, a) => f(...a)
1604
+ });
1605
+ }
1606
+ });
1607
+ }
1608
+ }
1609
+ async _saveSnapshot() {
1610
+ const snapshot = await this.createSnapshot();
1611
+ const snapshotKey = await this._params.snapshotManager.store(snapshot);
1612
+ await this._params.metadataStore.setSpaceSnapshot(this._params.spaceKey, snapshotKey);
1613
+ return snapshot;
1614
+ }
1615
+ async _saveLatestTimeframe() {
1616
+ var _a, _b;
1617
+ const latestTimeframe = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe;
1618
+ log12("save latest timeframe", {
1619
+ latestTimeframe,
1620
+ spaceKey: this._params.spaceKey
1621
+ }, {
1622
+ file: "data-pipeline.ts",
1623
+ line: 176,
1624
+ scope: this,
1625
+ callSite: (f, a) => f(...a)
1626
+ });
1627
+ if (latestTimeframe) {
1628
+ const newTimeframe = Timeframe3.merge((_b = this._targetTimeframe) != null ? _b : new Timeframe3(), latestTimeframe);
1629
+ await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, newTimeframe);
1630
+ }
1631
+ }
1607
1632
  async close() {
1608
1633
  var _a, _b, _c;
1609
1634
  if (!this._isOpen) {
@@ -1611,32 +1636,37 @@ var DataPipeline = class DataPipeline2 {
1611
1636
  }
1612
1637
  log12("close", {}, {
1613
1638
  file: "data-pipeline.ts",
1614
- line: 145,
1639
+ line: 188,
1615
1640
  scope: this,
1616
1641
  callSite: (f, a) => f(...a)
1617
1642
  });
1618
1643
  this._isOpen = false;
1619
- await this._ctx.dispose();
1620
- await ((_a = this._pipeline) == null ? void 0 : _a.stop());
1621
1644
  try {
1622
- if (this._pipeline) {
1623
- await this._saveTargetTimeframe(this._pipeline.state.timeframe);
1624
- if (!DISABLE_SNAPSHOT_CACHE) {
1625
- await this._saveSnapshot(this._pipeline.state.timeframe);
1626
- }
1627
- }
1645
+ await this._saveLatestTimeframe();
1646
+ await this._saveSnapshot();
1628
1647
  } catch (err) {
1629
1648
  log12.catch(err, {}, {
1630
1649
  file: "data-pipeline.ts",
1631
- line: 160,
1650
+ line: 195,
1632
1651
  scope: this,
1633
1652
  callSite: (f, a) => f(...a)
1634
1653
  });
1635
1654
  }
1655
+ await this._ctx.dispose();
1656
+ await ((_a = this._pipeline) == null ? void 0 : _a.stop());
1636
1657
  await ((_b = this.databaseBackend) == null ? void 0 : _b.close());
1637
1658
  await ((_c = this._itemManager) == null ? void 0 : _c.destroy());
1638
1659
  await this._params.snapshotManager.close();
1639
1660
  }
1661
+ createSnapshot() {
1662
+ var _a, _b;
1663
+ assert9(this.databaseBackend, "Database backend is not initialized.");
1664
+ return {
1665
+ spaceKey: this._params.spaceKey.asUint8Array(),
1666
+ timeframe: (_b = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe) != null ? _b : new Timeframe3(),
1667
+ database: this.databaseBackend.createSnapshot()
1668
+ };
1669
+ }
1640
1670
  async _consumePipeline() {
1641
1671
  assert9(this._pipeline, "Pipeline is not initialized.");
1642
1672
  for await (const msg of this._pipeline.consume()) {
@@ -1645,7 +1675,7 @@ var DataPipeline = class DataPipeline2 {
1645
1675
  msg
1646
1676
  }, {
1647
1677
  file: "data-pipeline.ts",
1648
- line: 172,
1678
+ line: 217,
1649
1679
  scope: this,
1650
1680
  callSite: (f, a) => f(...a)
1651
1681
  });
@@ -1657,7 +1687,7 @@ var DataPipeline = class DataPipeline2 {
1657
1687
  feedKey
1658
1688
  }, {
1659
1689
  file: "data-pipeline.ts",
1660
- line: 178,
1690
+ line: 223,
1661
1691
  scope: this,
1662
1692
  callSite: (f, a) => f(...a)
1663
1693
  });
@@ -1672,58 +1702,18 @@ var DataPipeline = class DataPipeline2 {
1672
1702
  memberKey: feedInfo.assertion.identityKey
1673
1703
  }
1674
1704
  });
1675
- await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
1705
+ this.onTimeframeReached.emit(data.timeframe);
1676
1706
  }
1677
1707
  } catch (err) {
1678
1708
  log12.catch(err, {}, {
1679
1709
  file: "data-pipeline.ts",
1680
- line: 196,
1710
+ line: 239,
1681
1711
  scope: this,
1682
1712
  callSite: (f, a) => f(...a)
1683
1713
  });
1684
1714
  }
1685
1715
  }
1686
1716
  }
1687
- _createSnapshot(timeframe) {
1688
- assert9(this.databaseBackend, "Database backend is not initialized.");
1689
- return {
1690
- spaceKey: this._params.spaceKey.asUint8Array(),
1691
- timeframe,
1692
- database: this.databaseBackend.createSnapshot()
1693
- };
1694
- }
1695
- async _saveSnapshot(timeframe) {
1696
- const snapshot = await this._createSnapshot(timeframe);
1697
- const snapshotKey = await this._params.snapshotManager.store(snapshot);
1698
- await this._params.metadataStore.setSpaceSnapshot(this._params.spaceKey, snapshotKey);
1699
- return snapshot;
1700
- }
1701
- async _saveTargetTimeframe(timeframe) {
1702
- var _a;
1703
- const newTimeframe = Timeframe3.merge((_a = this._targetTimeframe) != null ? _a : new Timeframe3(), timeframe);
1704
- await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, newTimeframe);
1705
- this._targetTimeframe = newTimeframe;
1706
- }
1707
- async _noteTargetStateIfNeeded(timeframe) {
1708
- var _a;
1709
- if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL) {
1710
- this._lastTimeframeSaveTime = Date.now();
1711
- await this._saveTargetTimeframe(timeframe);
1712
- }
1713
- if (!DISABLE_SNAPSHOT_CACHE && Date.now() - this._lastSnapshotSaveTime > AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL && timeframe.totalMessages() - this._lastAutomaticSnapshotTimeframe.totalMessages() > MESSAGES_PER_SNAPSHOT) {
1714
- this._lastSnapshotSaveTime = Date.now();
1715
- const snapshot = await this._saveSnapshot(timeframe);
1716
- this._lastAutomaticSnapshotTimeframe = (_a = snapshot.timeframe) != null ? _a : failUndefined3();
1717
- log12("save", {
1718
- snapshot
1719
- }, {
1720
- file: "data-pipeline.ts",
1721
- line: 239,
1722
- scope: this,
1723
- callSite: (f, a) => f(...a)
1724
- });
1725
- }
1726
- }
1727
1717
  async waitUntilTimeframe(timeframe) {
1728
1718
  assert9(this._pipeline, "Pipeline is not initialized.");
1729
1719
  await this._pipeline.state.waitUntilTimeframe(timeframe);
@@ -1773,4 +1763,4 @@ export {
1773
1763
  DataServiceImpl,
1774
1764
  DataPipeline
1775
1765
  };
1776
- //# sourceMappingURL=chunk-4YAT2XJW.mjs.map
1766
+ //# sourceMappingURL=chunk-4TOOIHMA.mjs.map