@dxos/echo-pipeline 0.1.50 → 0.1.51-main.04d9478

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/browser/{chunk-CSFWTLPD.mjs → chunk-Q7JKCZLC.mjs} +140 -49
  2. package/dist/lib/browser/chunk-Q7JKCZLC.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/testing/index.mjs +2 -2
  6. package/dist/lib/browser/testing/index.mjs.map +1 -1
  7. package/dist/lib/node/index.cjs +146 -55
  8. package/dist/lib/node/index.cjs.map +3 -3
  9. package/dist/lib/node/meta.json +1 -1
  10. package/dist/lib/node/testing/index.cjs +154 -63
  11. package/dist/lib/node/testing/index.cjs.map +3 -3
  12. package/dist/types/src/dbhost/snapshot-manager.d.ts +2 -1
  13. package/dist/types/src/dbhost/snapshot-manager.d.ts.map +1 -1
  14. package/dist/types/src/metadata/metadata-store.d.ts +2 -1
  15. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
  16. package/dist/types/src/space/control-pipeline.d.ts +9 -1
  17. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  18. package/dist/types/src/space/data-pipeline.d.ts +3 -0
  19. package/dist/types/src/space/data-pipeline.d.ts.map +1 -1
  20. package/dist/types/src/space/space.d.ts.map +1 -1
  21. package/package.json +30 -30
  22. package/src/dbhost/snapshot-manager.ts +4 -3
  23. package/src/metadata/metadata-store.ts +12 -1
  24. package/src/space/control-pipeline.test.ts +4 -0
  25. package/src/space/control-pipeline.ts +36 -1
  26. package/src/space/data-pipeline.ts +51 -8
  27. package/src/space/space.test.ts +1 -4
  28. package/src/space/space.ts +3 -2
  29. package/src/testing/util.ts +1 -1
  30. package/dist/lib/browser/chunk-CSFWTLPD.mjs.map +0 -7
@@ -121,6 +121,10 @@ var MetadataStore = class {
121
121
  }
122
122
  }
123
123
  _getSpace(spaceKey) {
124
+ var _a;
125
+ if ((_a = this._metadata.identity) == null ? void 0 : _a.haloSpace.key.equals(spaceKey)) {
126
+ return this._metadata.identity.haloSpace;
127
+ }
124
128
  const space = this.spaces.find((space2) => space2.key === spaceKey);
125
129
  assert(space, "Space not found");
126
130
  return space;
@@ -131,7 +135,7 @@ var MetadataStore = class {
131
135
  async clear() {
132
136
  log("clearing all metadata", {}, {
133
137
  file: "metadata-store.ts",
134
- line: 131,
138
+ line: 136,
135
139
  scope: this,
136
140
  callSite: (f, a) => f(...a)
137
141
  });
@@ -152,10 +156,14 @@ var MetadataStore = class {
152
156
  ((_c = (_b = this._metadata).spaces) != null ? _c : _b.spaces = []).push(record);
153
157
  await this._save();
154
158
  }
155
- async setSpaceLatestTimeframe(spaceKey, timeframe) {
159
+ async setSpaceDataLatestTimeframe(spaceKey, timeframe) {
156
160
  this._getSpace(spaceKey).dataTimeframe = timeframe;
157
161
  await this._save();
158
162
  }
163
+ async setSpaceControlLatestTimeframe(spaceKey, timeframe) {
164
+ this._getSpace(spaceKey).controlTimeframe = timeframe;
165
+ await this._save();
166
+ }
159
167
  async setCache(spaceKey, cache) {
160
168
  this._getSpace(spaceKey).cache = cache;
161
169
  await this._save();
@@ -827,6 +835,7 @@ var DatabaseHost = class {
827
835
 
828
836
  // packages/core/echo/echo-pipeline/src/dbhost/snapshot-manager.ts
829
837
  import { trackLeaks } from "@dxos/async";
838
+ import { cancelWithContext } from "@dxos/context";
830
839
  import { timed as timed2 } from "@dxos/debug";
831
840
  import { log as log7 } from "@dxos/log";
832
841
  import { schema as schema4 } from "@dxos/protocols";
@@ -853,7 +862,7 @@ var SnapshotManager = class SnapshotManager2 {
853
862
  snapshot
854
863
  }, {
855
864
  file: "snapshot-manager.ts",
856
- line: 30,
865
+ line: 31,
857
866
  scope: this,
858
867
  callSite: (f, a) => f(...a)
859
868
  });
@@ -870,7 +879,7 @@ var SnapshotManager = class SnapshotManager2 {
870
879
  data
871
880
  }, {
872
881
  file: "snapshot-manager.ts",
873
- line: 40,
882
+ line: 41,
874
883
  scope: this,
875
884
  callSite: (f, a) => f(...a)
876
885
  });
@@ -888,12 +897,12 @@ var SnapshotManager = class SnapshotManager2 {
888
897
  async close() {
889
898
  await this._objectSync.close();
890
899
  }
891
- async load(id) {
892
- const local = await this._snapshotStore.loadSnapshot(id);
900
+ async load(ctx, id) {
901
+ const local = await cancelWithContext(ctx, this._snapshotStore.loadSnapshot(id));
893
902
  if (local) {
894
903
  return local;
895
904
  }
896
- const remote = await this._objectSync.download(id);
905
+ const remote = await cancelWithContext(ctx, this._objectSync.download(ctx, id));
897
906
  return schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(remote.payload.value);
898
907
  }
899
908
  async store(snapshot) {
@@ -1017,6 +1026,7 @@ import { Event as Event4, scheduleTask as scheduleTask2, synchronized as synchro
1017
1026
  import { Context as Context3 } from "@dxos/context";
1018
1027
  import { checkCredentialType } from "@dxos/credentials";
1019
1028
  import { getStateMachineFromItem, ItemManager } from "@dxos/echo-db";
1029
+ import { CancelledError } from "@dxos/errors";
1020
1030
  import { log as log9 } from "@dxos/log";
1021
1031
  import { Timeframe as Timeframe3 } from "@dxos/timeframe";
1022
1032
  var __decorate5 = function(decorators, target, key, desc) {
@@ -1040,6 +1050,7 @@ var DataPipeline = class DataPipeline2 {
1040
1050
  this._isOpen = false;
1041
1051
  this._lastTimeframeSaveTime = 0;
1042
1052
  this._lastSnapshotSaveTime = 0;
1053
+ this._lastProcessedEpoch = -1;
1043
1054
  this.onNewEpoch = new Event4();
1044
1055
  }
1045
1056
  get isOpen() {
@@ -1063,17 +1074,10 @@ var DataPipeline = class DataPipeline2 {
1063
1074
  if (!checkCredentialType(credential, "dxos.halo.credentials.Epoch")) {
1064
1075
  return;
1065
1076
  }
1066
- log9("new epoch", {
1067
- credential
1068
- }, {
1069
- file: "data-pipeline.ts",
1070
- line: 109,
1071
- scope: this,
1072
- callSite: (f, a) => f(...a)
1073
- });
1074
- await this._processEpoch(credential.subject.assertion);
1075
1077
  this.currentEpoch = credential;
1076
- this.onNewEpoch.emit(credential);
1078
+ if (this._isOpen) {
1079
+ await this._processEpochInSeparateTask(credential);
1080
+ }
1077
1081
  }
1078
1082
  };
1079
1083
  }
@@ -1112,7 +1116,7 @@ var DataPipeline = class DataPipeline2 {
1112
1116
  }
1113
1117
  log9("close", {}, {
1114
1118
  file: "data-pipeline.ts",
1115
- line: 161,
1119
+ line: 165,
1116
1120
  scope: this,
1117
1121
  callSite: (f, a) => f(...a)
1118
1122
  });
@@ -1127,7 +1131,7 @@ var DataPipeline = class DataPipeline2 {
1127
1131
  } catch (err) {
1128
1132
  log9.catch(err, {}, {
1129
1133
  file: "data-pipeline.ts",
1130
- line: 174,
1134
+ line: 178,
1131
1135
  scope: this,
1132
1136
  callSite: (f, a) => f(...a)
1133
1137
  });
@@ -1137,6 +1141,11 @@ var DataPipeline = class DataPipeline2 {
1137
1141
  await this._params.snapshotManager.close();
1138
1142
  }
1139
1143
  async _consumePipeline() {
1144
+ if (this.currentEpoch) {
1145
+ const waitForOneEpoch = this.onNewEpoch.waitFor(() => true);
1146
+ await this._processEpochInSeparateTask(this.currentEpoch);
1147
+ await waitForOneEpoch;
1148
+ }
1140
1149
  assert8(this._pipeline, "Pipeline is not initialized.");
1141
1150
  for await (const msg of this._pipeline.consume()) {
1142
1151
  const { feedKey, seq, data } = msg;
@@ -1145,7 +1154,7 @@ var DataPipeline = class DataPipeline2 {
1145
1154
  seq
1146
1155
  }, {
1147
1156
  file: "data-pipeline.ts",
1148
- line: 186,
1157
+ line: 196,
1149
1158
  scope: this,
1150
1159
  callSite: (f, a) => f(...a)
1151
1160
  });
@@ -1157,7 +1166,7 @@ var DataPipeline = class DataPipeline2 {
1157
1166
  feedKey
1158
1167
  }, {
1159
1168
  file: "data-pipeline.ts",
1160
- line: 192,
1169
+ line: 202,
1161
1170
  scope: this,
1162
1171
  callSite: (f, a) => f(...a)
1163
1172
  });
@@ -1172,12 +1181,22 @@ var DataPipeline = class DataPipeline2 {
1172
1181
  memberKey: feedInfo.assertion.identityKey
1173
1182
  }
1174
1183
  });
1184
+ log9.trace("dxos.echo.data-pipeline.processed", {
1185
+ feedKey: feedKey.toHex(),
1186
+ seq,
1187
+ spaceKey: this._params.spaceKey.toHex()
1188
+ }, {
1189
+ file: "data-pipeline.ts",
1190
+ line: 216,
1191
+ scope: this,
1192
+ callSite: (f, a) => f(...a)
1193
+ });
1175
1194
  await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
1176
1195
  }
1177
1196
  } catch (err) {
1178
1197
  log9.catch(err, {}, {
1179
1198
  file: "data-pipeline.ts",
1180
- line: 210,
1199
+ line: 226,
1181
1200
  scope: this,
1182
1201
  callSite: (f, a) => f(...a)
1183
1202
  });
@@ -1195,7 +1214,7 @@ var DataPipeline = class DataPipeline2 {
1195
1214
  async _saveTargetTimeframe(timeframe) {
1196
1215
  var _a;
1197
1216
  const newTimeframe = Timeframe3.merge((_a = this._targetTimeframe) != null ? _a : new Timeframe3(), timeframe);
1198
- await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, newTimeframe);
1217
+ await this._params.metadataStore.setSpaceDataLatestTimeframe(this._params.spaceKey, newTimeframe);
1199
1218
  this._targetTimeframe = newTimeframe;
1200
1219
  }
1201
1220
  async _saveCache() {
@@ -1212,7 +1231,7 @@ var DataPipeline = class DataPipeline2 {
1212
1231
  } catch (err) {
1213
1232
  log9.warn("Failed to cache properties", err, {
1214
1233
  file: "data-pipeline.ts",
1215
- line: 244,
1234
+ line: 260,
1216
1235
  scope: this,
1217
1236
  callSite: (f, a) => f(...a)
1218
1237
  });
@@ -1228,24 +1247,67 @@ var DataPipeline = class DataPipeline2 {
1228
1247
  await this._saveCache();
1229
1248
  }
1230
1249
  }
1231
- async _processEpoch(epoch) {
1232
- assert8(this._isOpen);
1250
+ async _processEpochInSeparateTask(epoch) {
1251
+ var _a;
1252
+ if (epoch.subject.assertion.number <= this._lastProcessedEpoch) {
1253
+ return;
1254
+ }
1255
+ await ((_a = this._epochCtx) == null ? void 0 : _a.dispose());
1256
+ const ctx = new Context3({
1257
+ onError: (err) => {
1258
+ if (err instanceof CancelledError) {
1259
+ log9("Epoch processing cancelled.", {}, {
1260
+ file: "data-pipeline.ts",
1261
+ line: 292,
1262
+ scope: this,
1263
+ callSite: (f, a) => f(...a)
1264
+ });
1265
+ } else {
1266
+ log9.catch(err, {}, {
1267
+ file: "data-pipeline.ts",
1268
+ line: 294,
1269
+ scope: this,
1270
+ callSite: (f, a) => f(...a)
1271
+ });
1272
+ }
1273
+ }
1274
+ });
1275
+ this._epochCtx = ctx;
1276
+ scheduleTask2(ctx, async () => {
1277
+ if (!this._isOpen) {
1278
+ return;
1279
+ }
1280
+ log9("process epoch", {
1281
+ epoch
1282
+ }, {
1283
+ file: "data-pipeline.ts",
1284
+ line: 304,
1285
+ scope: this,
1286
+ callSite: (f, a) => f(...a)
1287
+ });
1288
+ await this._processEpoch(ctx, epoch.subject.assertion);
1289
+ this.onNewEpoch.emit(epoch);
1290
+ });
1291
+ }
1292
+ async _processEpoch(ctx, epoch) {
1293
+ assert8(this._isOpen, "Space is closed.");
1233
1294
  assert8(this._pipeline);
1295
+ this._lastProcessedEpoch = epoch.number;
1234
1296
  log9("Processing epoch", {
1235
1297
  epoch
1236
1298
  }, {
1237
1299
  file: "data-pipeline.ts",
1238
- line: 273,
1300
+ line: 316,
1239
1301
  scope: this,
1240
1302
  callSite: (f, a) => f(...a)
1241
1303
  });
1242
1304
  if (epoch.snapshotCid) {
1243
- const snapshot = await this._params.snapshotManager.load(epoch.snapshotCid);
1305
+ const snapshot = await this._params.snapshotManager.load(ctx, epoch.snapshotCid);
1244
1306
  this.databaseHost._itemDemuxer.restoreFromSnapshot(snapshot.database);
1245
1307
  }
1246
1308
  log9("restarting pipeline for epoch", {}, {
1247
1309
  file: "data-pipeline.ts",
1248
- line: 281,
1310
+ line: 324,
1249
1311
  scope: this,
1250
1312
  callSite: (f, a) => f(...a)
1251
1313
  });
@@ -1304,10 +1366,15 @@ import { SpaceStateMachine } from "@dxos/credentials";
1304
1366
  import { PublicKey as PublicKey3 } from "@dxos/keys";
1305
1367
  import { log as log10 } from "@dxos/log";
1306
1368
  import { AdmittedFeed } from "@dxos/protocols/proto/dxos/halo/credentials";
1369
+ import { Timeframe as Timeframe4 } from "@dxos/timeframe";
1307
1370
  import { Callback } from "@dxos/util";
1371
+ var TIMEFRAME_SAVE_DEBOUNCE_INTERVAL2 = 500;
1308
1372
  var ControlPipeline = class {
1309
- constructor({ spaceKey, genesisFeed, feedProvider }) {
1373
+ constructor({ spaceKey, genesisFeed, feedProvider, metadataStore }) {
1374
+ this._lastTimeframeSaveTime = Date.now();
1310
1375
  this.onFeedAdmitted = new Callback();
1376
+ this._spaceKey = spaceKey;
1377
+ this._metadata = metadataStore;
1311
1378
  this._pipeline = new Pipeline();
1312
1379
  void this._pipeline.addFeed(genesisFeed);
1313
1380
  this._spaceStateMachine = new SpaceStateMachine(spaceKey);
@@ -1316,7 +1383,7 @@ var ControlPipeline = class {
1316
1383
  key: info.key
1317
1384
  }, {
1318
1385
  file: "control-pipeline.ts",
1319
- line: 39,
1386
+ line: 51,
1320
1387
  scope: this,
1321
1388
  callSite: (f, a) => f(...a)
1322
1389
  });
@@ -1327,7 +1394,7 @@ var ControlPipeline = class {
1327
1394
  } catch (err) {
1328
1395
  log10.catch(err, {}, {
1329
1396
  file: "control-pipeline.ts",
1330
- line: 47,
1397
+ line: 59,
1331
1398
  scope: this,
1332
1399
  callSite: (f, a) => f(...a)
1333
1400
  });
@@ -1350,7 +1417,7 @@ var ControlPipeline = class {
1350
1417
  async start() {
1351
1418
  log10("starting...", {}, {
1352
1419
  file: "control-pipeline.ts",
1353
- line: 71,
1420
+ line: 83,
1354
1421
  scope: this,
1355
1422
  callSite: (f, a) => f(...a)
1356
1423
  });
@@ -1362,7 +1429,7 @@ var ControlPipeline = class {
1362
1429
  seq: msg.seq
1363
1430
  }, {
1364
1431
  file: "control-pipeline.ts",
1365
- line: 76,
1432
+ line: 88,
1366
1433
  scope: this,
1367
1434
  callSite: (f, a) => f(...a)
1368
1435
  });
@@ -1373,16 +1440,18 @@ var ControlPipeline = class {
1373
1440
  msg
1374
1441
  }, {
1375
1442
  file: "control-pipeline.ts",
1376
- line: 83,
1443
+ line: 95,
1377
1444
  scope: this,
1378
1445
  callSite: (f, a) => f(...a)
1379
1446
  });
1447
+ } else {
1448
+ await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
1380
1449
  }
1381
1450
  }
1382
1451
  } catch (err) {
1383
1452
  log10.catch(err, {}, {
1384
1453
  file: "control-pipeline.ts",
1385
- line: 87,
1454
+ line: 101,
1386
1455
  scope: this,
1387
1456
  callSite: (f, a) => f(...a)
1388
1457
  });
@@ -1392,26 +1461,48 @@ var ControlPipeline = class {
1392
1461
  await this._pipeline.start();
1393
1462
  log10("started", {}, {
1394
1463
  file: "control-pipeline.ts",
1395
- line: 93,
1464
+ line: 107,
1396
1465
  scope: this,
1397
1466
  callSite: (f, a) => f(...a)
1398
1467
  });
1399
1468
  }
1469
+ async _noteTargetStateIfNeeded(timeframe) {
1470
+ if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL2) {
1471
+ this._lastTimeframeSaveTime = Date.now();
1472
+ await this._saveTargetTimeframe(timeframe);
1473
+ }
1474
+ }
1400
1475
  async stop() {
1401
1476
  log10("stopping...", {}, {
1402
1477
  file: "control-pipeline.ts",
1403
- line: 97,
1478
+ line: 121,
1404
1479
  scope: this,
1405
1480
  callSite: (f, a) => f(...a)
1406
1481
  });
1407
1482
  await this._pipeline.stop();
1483
+ await this._saveTargetTimeframe(this._pipeline.state.timeframe);
1408
1484
  log10("stopped", {}, {
1409
1485
  file: "control-pipeline.ts",
1410
- line: 99,
1486
+ line: 124,
1411
1487
  scope: this,
1412
1488
  callSite: (f, a) => f(...a)
1413
1489
  });
1414
1490
  }
1491
+ async _saveTargetTimeframe(timeframe) {
1492
+ var _a;
1493
+ try {
1494
+ const newTimeframe = Timeframe4.merge((_a = this._targetTimeframe) != null ? _a : new Timeframe4(), timeframe);
1495
+ await this._metadata.setSpaceControlLatestTimeframe(this._spaceKey, newTimeframe);
1496
+ this._targetTimeframe = newTimeframe;
1497
+ } catch (err) {
1498
+ log10(err, {}, {
1499
+ file: "control-pipeline.ts",
1500
+ line: 133,
1501
+ scope: this,
1502
+ callSite: (f, a) => f(...a)
1503
+ });
1504
+ }
1505
+ }
1415
1506
  };
1416
1507
 
1417
1508
  // packages/core/echo/echo-pipeline/src/space/space.ts
@@ -1441,7 +1532,8 @@ var Space = class Space2 {
1441
1532
  this._controlPipeline = new ControlPipeline({
1442
1533
  spaceKey: params.spaceKey,
1443
1534
  genesisFeed: params.genesisFeed,
1444
- feedProvider: params.feedProvider
1535
+ feedProvider: params.feedProvider,
1536
+ metadataStore: params.metadataStore
1445
1537
  });
1446
1538
  this._controlPipeline.onFeedAdmitted.set(async (info) => {
1447
1539
  if (info.assertion.designation === AdmittedFeed2.Designation.DATA) {
@@ -1463,7 +1555,7 @@ var Space = class Space2 {
1463
1555
  credential
1464
1556
  }, {
1465
1557
  file: "space.ts",
1466
- line: 106,
1558
+ line: 107,
1467
1559
  scope: this,
1468
1560
  callSite: (f, a) => f(...a)
1469
1561
  });
@@ -1553,7 +1645,7 @@ var Space = class Space2 {
1553
1645
  async open() {
1554
1646
  log11("opening...", {}, {
1555
1647
  file: "space.ts",
1556
- line: 208,
1648
+ line: 209,
1557
1649
  scope: this,
1558
1650
  callSite: (f, a) => f(...a)
1559
1651
  });
@@ -1563,10 +1655,11 @@ var Space = class Space2 {
1563
1655
  await this._controlPipeline.start();
1564
1656
  await this.protocol.start();
1565
1657
  this._dataPipelineCredentialConsumer = this._controlPipeline.spaceState.registerProcessor(this._dataPipeline.createCredentialProcessor());
1658
+ await this._dataPipelineCredentialConsumer.open();
1566
1659
  this._isOpen = true;
1567
1660
  log11("opened", {}, {
1568
1661
  file: "space.ts",
1569
- line: 222,
1662
+ line: 225,
1570
1663
  scope: this,
1571
1664
  callSite: (f, a) => f(...a)
1572
1665
  });
@@ -1577,7 +1670,7 @@ var Space = class Space2 {
1577
1670
  key: this._key
1578
1671
  }, {
1579
1672
  file: "space.ts",
1580
- line: 227,
1673
+ line: 230,
1581
1674
  scope: this,
1582
1675
  callSite: (f, a) => f(...a)
1583
1676
  });
@@ -1592,7 +1685,7 @@ var Space = class Space2 {
1592
1685
  this._isOpen = false;
1593
1686
  log11("closed", {}, {
1594
1687
  file: "space.ts",
1595
- line: 241,
1688
+ line: 244,
1596
1689
  scope: this,
1597
1690
  callSite: (f, a) => f(...a)
1598
1691
  });
@@ -1600,14 +1693,12 @@ var Space = class Space2 {
1600
1693
  async initializeDataPipeline() {
1601
1694
  log11("initializeDataPipeline", {}, {
1602
1695
  file: "space.ts",
1603
- line: 246,
1696
+ line: 249,
1604
1697
  scope: this,
1605
1698
  callSite: (f, a) => f(...a)
1606
1699
  });
1607
1700
  assert9(this._isOpen, "Space must be open to initialize data pipeline.");
1608
1701
  await this._dataPipeline.open();
1609
- assert9(this._dataPipelineCredentialConsumer);
1610
- await this._dataPipelineCredentialConsumer.open();
1611
1702
  }
1612
1703
  };
1613
1704
  __decorate6([
@@ -1934,4 +2025,4 @@ export {
1934
2025
  SpaceProtocolSession,
1935
2026
  SpaceManager
1936
2027
  };
1937
- //# sourceMappingURL=chunk-CSFWTLPD.mjs.map
2028
+ //# sourceMappingURL=chunk-Q7JKCZLC.mjs.map