@dxos/echo-pipeline 0.8.3-main.7f5a14c → 0.8.3-staging.0fa589b

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 (32) hide show
  1. package/dist/lib/browser/index.mjs +202 -94
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +196 -91
  5. package/dist/lib/node/index.cjs.map +3 -3
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +202 -94
  8. package/dist/lib/node-esm/index.mjs.map +3 -3
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/automerge/automerge-host.d.ts +4 -0
  11. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  12. package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
  13. package/dist/types/src/db-host/query-service.d.ts +7 -1
  14. package/dist/types/src/db-host/query-service.d.ts.map +1 -1
  15. package/dist/types/src/query/plan.d.ts +9 -1
  16. package/dist/types/src/query/plan.d.ts.map +1 -1
  17. package/dist/types/src/query/query-executor.d.ts +1 -0
  18. package/dist/types/src/query/query-executor.d.ts.map +1 -1
  19. package/dist/types/src/query/query-planner.d.ts +1 -0
  20. package/dist/types/src/query/query-planner.d.ts.map +1 -1
  21. package/dist/types/src/testing/test-schema.d.ts +20 -22
  22. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  23. package/package.json +35 -35
  24. package/src/automerge/automerge-host.ts +6 -0
  25. package/src/automerge/echo-data-monitor.ts +1 -0
  26. package/src/db-host/echo-host.ts +3 -0
  27. package/src/db-host/query-service.ts +98 -53
  28. package/src/filter/filter-match.test.ts +2 -1
  29. package/src/query/plan.ts +18 -1
  30. package/src/query/query-executor.ts +49 -16
  31. package/src/query/query-planner.test.ts +110 -1
  32. package/src/query/query-planner.ts +15 -0
@@ -809,6 +809,10 @@ var AutomergeHost = class extends Resource3 {
809
809
  shouldSyncCollection: this._shouldSyncCollection.bind(this)
810
810
  });
811
811
  this.collectionStateUpdated = new Event2();
812
+ /**
813
+ * Fired after a batch of documents was saved to disk.
814
+ */
815
+ this.documentsSaved = new Event2();
812
816
  this._db = db;
813
817
  this._storage = new LevelDBStorageAdapter({
814
818
  db: db.sublevel("automerge"),
@@ -955,7 +959,7 @@ var AutomergeHost = class extends Resource3 {
955
959
  await Promise.all(headsToWait.map(async (entry, index) => {
956
960
  const handle = await this.loadDoc(Context.default(void 0, {
957
961
  F: __dxlog_file3,
958
- L: 288
962
+ L: 293
959
963
  }), entry.documentId);
960
964
  await waitForHeads(handle, entry.heads);
961
965
  }));
@@ -968,7 +972,7 @@ var AutomergeHost = class extends Resource3 {
968
972
  documentId
969
973
  }, {
970
974
  F: __dxlog_file3,
971
- L: 302,
975
+ L: 307,
972
976
  S: this,
973
977
  C: (f, a) => f(...a)
974
978
  });
@@ -978,7 +982,7 @@ var AutomergeHost = class extends Resource3 {
978
982
  documentId
979
983
  }, {
980
984
  F: __dxlog_file3,
981
- L: 305,
985
+ L: 310,
982
986
  S: this,
983
987
  C: (f, a) => f(...a)
984
988
  });
@@ -991,7 +995,7 @@ var AutomergeHost = class extends Resource3 {
991
995
  }
992
996
  log3("done re-indexing heads", void 0, {
993
997
  F: __dxlog_file3,
994
- L: 314,
998
+ L: 319,
995
999
  S: this,
996
1000
  C: (f, a) => f(...a)
997
1001
  });
@@ -1059,6 +1063,7 @@ var AutomergeHost = class extends Resource3 {
1059
1063
  const heads = getHeads(document);
1060
1064
  this._onHeadsChanged(documentId, heads);
1061
1065
  }
1066
+ this.documentsSaved.emit();
1062
1067
  }
1063
1068
  _automergePeers() {
1064
1069
  return this._repo.peers;
@@ -1212,7 +1217,7 @@ var AutomergeHost = class extends Resource3 {
1212
1217
  count: toReplicate.length
1213
1218
  }, {
1214
1219
  F: __dxlog_file3,
1215
- L: 557,
1220
+ L: 563,
1216
1221
  S: this,
1217
1222
  C: (f, a) => f(...a)
1218
1223
  });
@@ -1272,7 +1277,7 @@ var changeIsPresentInDoc = (doc, changeHash) => {
1272
1277
  var decodeCollectionState = (state) => {
1273
1278
  invariant2(typeof state === "object" && state !== null, "Invalid state", {
1274
1279
  F: __dxlog_file3,
1275
- L: 608,
1280
+ L: 614,
1276
1281
  S: void 0,
1277
1282
  A: [
1278
1283
  "typeof state === 'object' && state !== null",
@@ -2451,7 +2456,7 @@ var createSelectedDocumentsIterator = (automergeHost) => (
2451
2456
  // packages/core/echo/echo-pipeline/src/db-host/query-service.ts
2452
2457
  import { getHeads as getHeads3 } from "@automerge/automerge";
2453
2458
  import { Schema } from "effect";
2454
- import { DeferredTask } from "@dxos/async";
2459
+ import { DeferredTask, scheduleMicroTask, synchronized as synchronized2 } from "@dxos/async";
2455
2460
  import { Stream as Stream2 } from "@dxos/codec-protobuf/stream";
2456
2461
  import { Context as Context4, Resource as Resource7 } from "@dxos/context";
2457
2462
  import { raise } from "@dxos/debug";
@@ -2539,6 +2544,8 @@ var QueryPlanner = class {
2539
2544
  return this._generateReferenceTraversalClause(query, context);
2540
2545
  case "union":
2541
2546
  return this._generateUnionClause(query, context);
2547
+ case "set-difference":
2548
+ return this._generateSetDifferenceClause(query, context);
2542
2549
  default:
2543
2550
  throw new QueryError(`Unsupported query type: ${query.type}`, {
2544
2551
  context: {
@@ -2690,7 +2697,7 @@ var QueryPlanner = class {
2690
2697
  const typenames = filter.filters.map((f) => {
2691
2698
  invariant9(f.type === "object" && f.typename !== null, void 0, {
2692
2699
  F: __dxlog_file10,
2693
- L: 189,
2700
+ L: 191,
2694
2701
  S: this,
2695
2702
  A: [
2696
2703
  "f.type === 'object' && f.typename !== null",
@@ -2754,6 +2761,15 @@ var QueryPlanner = class {
2754
2761
  }
2755
2762
  ]);
2756
2763
  }
2764
+ _generateSetDifferenceClause(query, context) {
2765
+ return QueryPlan.Plan.make([
2766
+ {
2767
+ _tag: "SetDifferenceStep",
2768
+ source: this._generate(query.source, context),
2769
+ exclude: this._generate(query.exclude, context)
2770
+ }
2771
+ ]);
2772
+ }
2757
2773
  _generateReferenceTraversalClause(query, context) {
2758
2774
  return QueryPlan.Plan.make([
2759
2775
  ...this._generate(query.anchor, context).steps,
@@ -3008,7 +3024,7 @@ var QueryExecutor = class extends Resource6 {
3008
3024
  ]
3009
3025
  });
3010
3026
  const prevResultSet = this._lastResultSet;
3011
- const { workingSet, trace: trace6 } = await this._execPlan(this._plan, this._lastResultSet);
3027
+ const { workingSet, trace: trace6 } = await this._execPlan(this._plan, []);
3012
3028
  this._lastResultSet = workingSet;
3013
3029
  trace6.name = "Root";
3014
3030
  trace6.details = JSON.stringify({
@@ -3025,6 +3041,7 @@ var QueryExecutor = class extends Resource6 {
3025
3041
  }
3026
3042
  async _execPlan(plan, workingSet) {
3027
3043
  const trace6 = ExecutionTrace.makeEmpty();
3044
+ const begin = performance.now();
3028
3045
  for (const step of plan.steps) {
3029
3046
  if (this._ctx.disposed) {
3030
3047
  throw new ContextDisposedError();
@@ -3033,6 +3050,8 @@ var QueryExecutor = class extends Resource6 {
3033
3050
  workingSet = result.workingSet;
3034
3051
  trace6.children.push(result.trace);
3035
3052
  }
3053
+ trace6.objectCount = workingSet.length;
3054
+ trace6.executionTime = performance.now() - begin;
3036
3055
  return {
3037
3056
  workingSet,
3038
3057
  trace: trace6
@@ -3064,6 +3083,9 @@ var QueryExecutor = class extends Resource6 {
3064
3083
  case "UnionStep":
3065
3084
  ({ workingSet: newWorkingSet, trace: trace6 } = await this._execUnionStep(step, workingSet));
3066
3085
  break;
3086
+ case "SetDifferenceStep":
3087
+ ({ workingSet: newWorkingSet, trace: trace6 } = await this._execSetDifferenceStep(step, workingSet));
3088
+ break;
3067
3089
  case "TraverseStep":
3068
3090
  ({ workingSet: newWorkingSet, trace: trace6 } = await this._execTraverseStep(step, workingSet));
3069
3091
  break;
@@ -3190,6 +3212,17 @@ var QueryExecutor = class extends Resource6 {
3190
3212
  };
3191
3213
  }
3192
3214
  async _execFilterDeletedStep(step, workingSet) {
3215
+ if (workingSet.length === 6) {
3216
+ log9.info("FilterDeletedStep", {
3217
+ step,
3218
+ workingSet
3219
+ }, {
3220
+ F: __dxlog_file11,
3221
+ L: 386,
3222
+ S: this,
3223
+ C: (f, a) => f(...a)
3224
+ });
3225
+ }
3193
3226
  const expected = step.mode === "only-deleted";
3194
3227
  const result = workingSet.filter((item) => ObjectStructure.isDeleted(item.doc) === expected);
3195
3228
  return {
@@ -3215,27 +3248,29 @@ var QueryExecutor = class extends Resource6 {
3215
3248
  switch (step.traversal.direction) {
3216
3249
  case "outgoing": {
3217
3250
  const property = EscapedPropPath.unescape(step.traversal.property);
3218
- const refs = workingSet.map((item) => {
3251
+ const refs = workingSet.flatMap((item) => {
3219
3252
  const ref = getDeep(item.doc.data, property);
3220
- if (!isEncodedReference(ref)) {
3221
- return null;
3222
- }
3223
- try {
3224
- return {
3225
- ref: DXN.parse(ref["/"]),
3226
- spaceId: item.spaceId
3227
- };
3228
- } catch {
3229
- log9.warn("Invalid reference", {
3230
- ref: ref["/"]
3231
- }, {
3232
- F: __dxlog_file11,
3233
- L: 421,
3234
- S: this,
3235
- C: (f, a) => f(...a)
3236
- });
3237
- return null;
3238
- }
3253
+ const refs2 = Array.isArray(ref) ? ref : [
3254
+ ref
3255
+ ];
3256
+ return refs2.map((ref2) => {
3257
+ try {
3258
+ return isEncodedReference(ref2) ? {
3259
+ ref: DXN.parse(ref2["/"]),
3260
+ spaceId: item.spaceId
3261
+ } : null;
3262
+ } catch {
3263
+ log9.warn("Invalid reference", {
3264
+ ref: ref2["/"]
3265
+ }, {
3266
+ F: __dxlog_file11,
3267
+ L: 431,
3268
+ S: this,
3269
+ C: (f, a) => f(...a)
3270
+ });
3271
+ return null;
3272
+ }
3273
+ });
3239
3274
  }).filter(isNonNullable2);
3240
3275
  const beginLoad = performance.now();
3241
3276
  const items = await Promise.all(refs.map(({ ref, spaceId }) => this._loadFromDXN(ref, {
@@ -3287,7 +3322,7 @@ var QueryExecutor = class extends Resource6 {
3287
3322
  ref: ref["/"]
3288
3323
  }, {
3289
3324
  F: __dxlog_file11,
3290
- L: 483,
3325
+ L: 494,
3291
3326
  S: this,
3292
3327
  C: (f, a) => f(...a)
3293
3328
  });
@@ -3356,6 +3391,26 @@ var QueryExecutor = class extends Resource6 {
3356
3391
  trace: trace6
3357
3392
  };
3358
3393
  }
3394
+ async _execSetDifferenceStep(step, workingSet) {
3395
+ const trace6 = {
3396
+ ...ExecutionTrace.makeEmpty(),
3397
+ name: "SetDifference"
3398
+ };
3399
+ const sourceResult = await this._execPlan(step.source, [
3400
+ ...workingSet
3401
+ ]);
3402
+ const excludeResult = await this._execPlan(step.exclude, [
3403
+ ...workingSet
3404
+ ]);
3405
+ trace6.children.push(sourceResult.trace, excludeResult.trace);
3406
+ return {
3407
+ workingSet: sourceResult.workingSet.filter((item) => {
3408
+ const index = excludeResult.workingSet.findIndex((i) => i.objectId === item.objectId);
3409
+ return index === -1;
3410
+ }),
3411
+ trace: trace6
3412
+ };
3413
+ }
3359
3414
  async _loadDocumentsAfterIndexQuery(indexHits) {
3360
3415
  return Promise.all(indexHits.map(async (hit) => {
3361
3416
  return this._loadFromIndexHit(hit);
@@ -3365,7 +3420,7 @@ var QueryExecutor = class extends Resource6 {
3365
3420
  const { objectId, documentId, spaceKey: spaceKeyInIndex } = objectPointerCodec3.decode(hit.id);
3366
3421
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
3367
3422
  F: __dxlog_file11,
3368
- L: 571
3423
+ L: 604
3369
3424
  }), documentId);
3370
3425
  const doc = handle.doc();
3371
3426
  if (!doc) {
@@ -3393,7 +3448,7 @@ var QueryExecutor = class extends Resource6 {
3393
3448
  dxn
3394
3449
  }, {
3395
3450
  F: __dxlog_file11,
3396
- L: 598,
3451
+ L: 631,
3397
3452
  S: this,
3398
3453
  C: (f, a) => f(...a)
3399
3454
  });
@@ -3406,7 +3461,7 @@ var QueryExecutor = class extends Resource6 {
3406
3461
  spaceId
3407
3462
  }, {
3408
3463
  F: __dxlog_file11,
3409
- L: 606,
3464
+ L: 639,
3410
3465
  S: this,
3411
3466
  C: (f, a) => f(...a)
3412
3467
  });
@@ -3418,7 +3473,7 @@ var QueryExecutor = class extends Resource6 {
3418
3473
  spaceId
3419
3474
  }, {
3420
3475
  F: __dxlog_file11,
3421
- L: 611,
3476
+ L: 644,
3422
3477
  S: this,
3423
3478
  C: (f, a) => f(...a)
3424
3479
  });
@@ -3439,7 +3494,7 @@ var QueryExecutor = class extends Resource6 {
3439
3494
  }
3440
3495
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
3441
3496
  F: __dxlog_file11,
3442
- L: 630
3497
+ L: 663
3443
3498
  }), link);
3444
3499
  const doc = handle.doc();
3445
3500
  if (!doc) {
@@ -3459,27 +3514,17 @@ var QueryExecutor = class extends Resource6 {
3459
3514
  };
3460
3515
 
3461
3516
  // packages/core/echo/echo-pipeline/src/db-host/query-service.ts
3517
+ function _ts_decorate5(decorators, target, key, desc) {
3518
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3519
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3520
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3521
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3522
+ }
3462
3523
  var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/query-service.ts";
3463
3524
  var QueryServiceImpl = class extends Resource7 {
3464
3525
  // TODO(burdon): OK for options, but not params. Pass separately and type readonly here.
3465
3526
  constructor(_params) {
3466
- super(), this._params = _params, this._queries = /* @__PURE__ */ new Set(), this._updateQueries = new DeferredTask(this._ctx, async () => {
3467
- await Promise.all(Array.from(this._queries).map(async (query) => {
3468
- try {
3469
- const { changed } = await query.executor.execQuery();
3470
- if (changed) {
3471
- query.sendResults(query.executor.getResults());
3472
- }
3473
- } catch (err) {
3474
- log10.catch(err, void 0, {
3475
- F: __dxlog_file12,
3476
- L: 57,
3477
- S: this,
3478
- C: (f, a) => f(...a)
3479
- });
3480
- }
3481
- }));
3482
- });
3527
+ super(), this._params = _params, this._queries = /* @__PURE__ */ new Set();
3483
3528
  trace4.diagnostic({
3484
3529
  id: "active-queries",
3485
3530
  name: "Active Queries",
@@ -3495,9 +3540,11 @@ var QueryServiceImpl = class extends Resource7 {
3495
3540
  });
3496
3541
  }
3497
3542
  async _open() {
3498
- this._params.indexer.updated.on(this._ctx, () => this._updateQueries.schedule());
3543
+ this._params.indexer.updated.on(this._ctx, () => this.invalidateQueries());
3544
+ this._updateQueries = new DeferredTask(this._ctx, this._executeQueries.bind(this));
3499
3545
  }
3500
3546
  async _close() {
3547
+ await this._updateQueries.join();
3501
3548
  await Promise.all(Array.from(this._queries).map((query) => query.close()));
3502
3549
  }
3503
3550
  async setConfig(config) {
@@ -3505,40 +3552,11 @@ var QueryServiceImpl = class extends Resource7 {
3505
3552
  }
3506
3553
  execQuery(request) {
3507
3554
  return new Stream2(({ next, close, ctx }) => {
3508
- const parsedQuery = QueryAST.Query.pipe(Schema.decodeUnknownSync)(JSON.parse(request.query));
3509
- const queryEntry = {
3510
- executor: new QueryExecutor({
3511
- indexer: this._params.indexer,
3512
- automergeHost: this._params.automergeHost,
3513
- queryId: request.queryId ?? raise(new Error("query id required")),
3514
- query: parsedQuery,
3515
- reactivity: request.reactivity,
3516
- spaceStateManager: this._params.spaceStateManager
3517
- }),
3518
- sendResults: (results) => {
3519
- if (ctx.disposed) {
3520
- return;
3521
- }
3522
- next({
3523
- queryId: request.queryId,
3524
- results
3525
- });
3526
- },
3527
- close: async () => {
3528
- close();
3529
- await queryEntry.executor.close();
3530
- this._queries.delete(queryEntry);
3531
- }
3532
- };
3533
- this._queries.add(queryEntry);
3534
- queueMicrotask(async () => {
3555
+ const queryEntry = this._createQuery(ctx, request, next, close, close);
3556
+ scheduleMicroTask(ctx, async () => {
3535
3557
  await queryEntry.executor.open();
3536
- try {
3537
- await queryEntry.executor.execQuery();
3538
- queryEntry.sendResults(queryEntry.executor.getResults());
3539
- } catch (error) {
3540
- close(error);
3541
- }
3558
+ queryEntry.open = true;
3559
+ this._updateQueries.schedule();
3542
3560
  });
3543
3561
  return queryEntry.close;
3544
3562
  });
@@ -3549,7 +3567,7 @@ var QueryServiceImpl = class extends Resource7 {
3549
3567
  async reindex() {
3550
3568
  log10("Reindexing all documents...", void 0, {
3551
3569
  F: __dxlog_file12,
3552
- L: 141,
3570
+ L: 113,
3553
3571
  S: this,
3554
3572
  C: (f, a) => f(...a)
3555
3573
  });
@@ -3564,7 +3582,7 @@ var QueryServiceImpl = class extends Resource7 {
3564
3582
  count: ids.size
3565
3583
  }, {
3566
3584
  F: __dxlog_file12,
3567
- L: 149,
3585
+ L: 121,
3568
3586
  S: this,
3569
3587
  C: (f, a) => f(...a)
3570
3588
  });
@@ -3574,13 +3592,100 @@ var QueryServiceImpl = class extends Resource7 {
3574
3592
  count: ids.size
3575
3593
  }, {
3576
3594
  F: __dxlog_file12,
3577
- L: 153,
3595
+ L: 125,
3578
3596
  S: this,
3579
3597
  C: (f, a) => f(...a)
3580
3598
  });
3581
3599
  await this._params.indexer.reindex(ids);
3582
3600
  }
3601
+ /**
3602
+ * Schedule re-execution of all queries.
3603
+ */
3604
+ invalidateQueries() {
3605
+ for (const query of this._queries) {
3606
+ query.dirty = true;
3607
+ }
3608
+ this._updateQueries.schedule();
3609
+ }
3610
+ _createQuery(ctx, request, onResults, onError, onClose) {
3611
+ const parsedQuery = QueryAST.Query.pipe(Schema.decodeUnknownSync)(JSON.parse(request.query));
3612
+ const queryEntry = {
3613
+ executor: new QueryExecutor({
3614
+ indexer: this._params.indexer,
3615
+ automergeHost: this._params.automergeHost,
3616
+ queryId: request.queryId ?? raise(new Error("query id required")),
3617
+ query: parsedQuery,
3618
+ reactivity: request.reactivity,
3619
+ spaceStateManager: this._params.spaceStateManager
3620
+ }),
3621
+ dirty: true,
3622
+ open: false,
3623
+ firstResult: true,
3624
+ sendResults: (results) => {
3625
+ if (ctx.disposed) {
3626
+ return;
3627
+ }
3628
+ onResults({
3629
+ queryId: request.queryId,
3630
+ results
3631
+ });
3632
+ },
3633
+ onError,
3634
+ close: async () => {
3635
+ onClose();
3636
+ await queryEntry.executor.close();
3637
+ this._queries.delete(queryEntry);
3638
+ }
3639
+ };
3640
+ this._queries.add(queryEntry);
3641
+ return queryEntry;
3642
+ }
3643
+ async _executeQueries() {
3644
+ const begin = performance.now();
3645
+ let count = 0;
3646
+ await Promise.all(Array.from(this._queries).map(async (query) => {
3647
+ if (!query.dirty || !query.open) {
3648
+ return;
3649
+ }
3650
+ count++;
3651
+ try {
3652
+ const { changed } = await query.executor.execQuery();
3653
+ query.dirty = false;
3654
+ if (changed || query.firstResult) {
3655
+ query.firstResult = false;
3656
+ query.sendResults(query.executor.getResults());
3657
+ }
3658
+ } catch (err) {
3659
+ log10.catch(err, void 0, {
3660
+ F: __dxlog_file12,
3661
+ L: 196,
3662
+ S: this,
3663
+ C: (f, a) => f(...a)
3664
+ });
3665
+ }
3666
+ }));
3667
+ log10.verbose("executed queries", {
3668
+ count,
3669
+ duration: performance.now() - begin
3670
+ }, {
3671
+ F: __dxlog_file12,
3672
+ L: 200,
3673
+ S: this,
3674
+ C: (f, a) => f(...a)
3675
+ });
3676
+ }
3583
3677
  };
3678
+ _ts_decorate5([
3679
+ synchronized2
3680
+ ], QueryServiceImpl.prototype, "_close", null);
3681
+ _ts_decorate5([
3682
+ trace4.span({
3683
+ showInBrowserTimeline: true
3684
+ })
3685
+ ], QueryServiceImpl.prototype, "_executeQueries", null);
3686
+ QueryServiceImpl = _ts_decorate5([
3687
+ trace4.resource()
3688
+ ], QueryServiceImpl);
3584
3689
  var createDocumentsIterator = (automergeHost) => (
3585
3690
  /**
3586
3691
  * Recursively get all object data blobs from loaded documents from Automerge Repo.
@@ -3615,7 +3720,7 @@ var createDocumentsIterator = (automergeHost) => (
3615
3720
  }
3616
3721
  const linkHandle = await automergeHost.loadDoc(Context4.default(void 0, {
3617
3722
  F: __dxlog_file12,
3618
- L: 195
3723
+ L: 240
3619
3724
  }), urlString);
3620
3725
  for await (const result of getObjectsFromHandle(linkHandle)) {
3621
3726
  yield result;
@@ -3989,6 +4094,9 @@ var EchoHost = class extends Resource9 {
3989
4094
  void this._automergeHost.updateLocalCollectionState(deriveCollectionIdFromSpaceId(e.spaceId), e.documentIds);
3990
4095
  void this._automergeHost.updateLocalCollectionState(deriveCollectionIdFromSpaceId(e.spaceId, e.spaceRootId), e.documentIds);
3991
4096
  });
4097
+ this._automergeHost.documentsSaved.on(this._ctx, () => {
4098
+ this._queryService.invalidateQueries();
4099
+ });
3992
4100
  }
3993
4101
  async _close(ctx) {
3994
4102
  await this._queryService.close(ctx);
@@ -4029,7 +4137,7 @@ var EchoHost = class extends Resource9 {
4029
4137
  async createSpaceRoot(spaceKey) {
4030
4138
  invariant13(this._lifecycleState === LifecycleState5.OPEN, void 0, {
4031
4139
  F: __dxlog_file16,
4032
- L: 252,
4140
+ L: 255,
4033
4141
  S: this,
4034
4142
  A: [
4035
4143
  "this._lifecycleState === LifecycleState.OPEN",
@@ -4057,7 +4165,7 @@ var EchoHost = class extends Resource9 {
4057
4165
  async openSpaceRoot(spaceId, automergeUrl) {
4058
4166
  invariant13(this._lifecycleState === LifecycleState5.OPEN, void 0, {
4059
4167
  F: __dxlog_file16,
4060
- L: 271,
4168
+ L: 274,
4061
4169
  S: this,
4062
4170
  A: [
4063
4171
  "this._lifecycleState === LifecycleState.OPEN",
@@ -4088,7 +4196,7 @@ var EchoHost = class extends Resource9 {
4088
4196
 
4089
4197
  // packages/core/echo/echo-pipeline/src/edge/echo-edge-replicator.ts
4090
4198
  import { cbor as cbor2 } from "@automerge/automerge-repo";
4091
- import { Mutex, scheduleTask as scheduleTask2, scheduleMicroTask } from "@dxos/async";
4199
+ import { Mutex, scheduleTask as scheduleTask2, scheduleMicroTask as scheduleMicroTask2 } from "@dxos/async";
4092
4200
  import { Context as Context6, Resource as Resource11 } from "@dxos/context";
4093
4201
  import { randomUUID } from "@dxos/crypto";
4094
4202
  import { invariant as invariant14 } from "@dxos/invariant";
@@ -4248,7 +4356,7 @@ var EchoEdgeReplicator = class {
4248
4356
  L: 63
4249
4357
  });
4250
4358
  this._ctx.onDispose(this._edgeConnection.onReconnected(() => {
4251
- this._ctx && scheduleMicroTask(this._ctx, () => this._handleReconnect());
4359
+ this._ctx && scheduleMicroTask2(this._ctx, () => this._handleReconnect());
4252
4360
  }));
4253
4361
  }
4254
4362
  async _handleReconnect() {