@dxos/echo-pipeline 0.6.7 → 0.6.8-main.3be982f

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 (70) hide show
  1. package/dist/lib/browser/chunk-NE5LORNQ.mjs +2028 -0
  2. package/dist/lib/browser/chunk-NE5LORNQ.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-Q4B5JN6L.mjs +2150 -0
  4. package/dist/lib/browser/chunk-Q4B5JN6L.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-XPCF2V5U.mjs +31 -0
  6. package/dist/lib/browser/chunk-XPCF2V5U.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +16 -16
  8. package/dist/lib/browser/light.mjs +32 -0
  9. package/dist/lib/browser/light.mjs.map +7 -0
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/testing/index.mjs +3 -7
  12. package/dist/lib/browser/testing/index.mjs.map +3 -3
  13. package/dist/lib/node/chunk-5KNTTBQK.cjs +2146 -0
  14. package/dist/lib/node/chunk-5KNTTBQK.cjs.map +7 -0
  15. package/dist/lib/node/chunk-DZVH7HDD.cjs +43 -0
  16. package/dist/lib/node/chunk-DZVH7HDD.cjs.map +7 -0
  17. package/dist/lib/node/chunk-IHR4UMVA.cjs +2043 -0
  18. package/dist/lib/node/chunk-IHR4UMVA.cjs.map +7 -0
  19. package/dist/lib/node/index.cjs +35 -37
  20. package/dist/lib/node/index.cjs.map +2 -2
  21. package/dist/lib/node/light.cjs +52 -0
  22. package/dist/lib/node/light.cjs.map +7 -0
  23. package/dist/lib/node/meta.json +1 -1
  24. package/dist/lib/node/testing/index.cjs +12 -15
  25. package/dist/lib/node/testing/index.cjs.map +3 -3
  26. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  27. package/dist/types/src/automerge/network-protocol.d.ts.map +1 -1
  28. package/dist/types/src/common/codec.d.ts +0 -1
  29. package/dist/types/src/common/codec.d.ts.map +1 -1
  30. package/dist/types/src/common/feeds.d.ts.map +1 -1
  31. package/dist/types/src/common/index.d.ts +1 -0
  32. package/dist/types/src/common/index.d.ts.map +1 -1
  33. package/dist/types/src/common/space-id.d.ts +7 -0
  34. package/dist/types/src/common/space-id.d.ts.map +1 -0
  35. package/dist/types/src/db-host/index.d.ts +0 -2
  36. package/dist/types/src/db-host/index.d.ts.map +1 -1
  37. package/dist/types/src/light.d.ts +4 -0
  38. package/dist/types/src/light.d.ts.map +1 -0
  39. package/dist/types/src/pipeline/message-selector.d.ts.map +1 -1
  40. package/dist/types/src/space/space-manager.d.ts +1 -7
  41. package/dist/types/src/space/space-manager.d.ts.map +1 -1
  42. package/dist/types/src/space/space-protocol.d.ts +0 -1
  43. package/dist/types/src/space/space-protocol.d.ts.map +1 -1
  44. package/dist/types/src/space/space.d.ts +1 -10
  45. package/dist/types/src/space/space.d.ts.map +1 -1
  46. package/dist/types/src/testing/test-agent-builder.d.ts +0 -3
  47. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  48. package/package.json +43 -33
  49. package/src/automerge/echo-network-adapter.ts +1 -1
  50. package/src/automerge/mesh-echo-replicator.ts +1 -1
  51. package/src/common/index.ts +1 -0
  52. package/src/common/space-id.ts +27 -0
  53. package/src/db-host/index.ts +0 -2
  54. package/src/light.ts +7 -0
  55. package/src/space/space-manager.ts +3 -19
  56. package/src/space/space.ts +2 -32
  57. package/src/testing/test-agent-builder.ts +0 -7
  58. package/dist/lib/browser/chunk-P6XSIJKM.mjs +0 -4281
  59. package/dist/lib/browser/chunk-P6XSIJKM.mjs.map +0 -7
  60. package/dist/lib/node/chunk-IYTGTZ7D.cjs +0 -4255
  61. package/dist/lib/node/chunk-IYTGTZ7D.cjs.map +0 -7
  62. package/dist/types/src/db-host/snapshot-manager.d.ts +0 -19
  63. package/dist/types/src/db-host/snapshot-manager.d.ts.map +0 -1
  64. package/dist/types/src/db-host/snapshot-store.d.ts +0 -16
  65. package/dist/types/src/db-host/snapshot-store.d.ts.map +0 -1
  66. package/dist/types/src/db-host/snapshot-store.test.d.ts +0 -2
  67. package/dist/types/src/db-host/snapshot-store.test.d.ts.map +0 -1
  68. package/src/db-host/snapshot-manager.ts +0 -54
  69. package/src/db-host/snapshot-store.test.ts +0 -31
  70. package/src/db-host/snapshot-store.ts +0 -61
@@ -1,4255 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var chunk_IYTGTZ7D_exports = {};
30
- __export(chunk_IYTGTZ7D_exports, {
31
- AuthExtension: () => AuthExtension,
32
- AuthStatus: () => AuthStatus,
33
- AutomergeHost: () => AutomergeHost,
34
- CredentialRetrieverExtension: () => CredentialRetrieverExtension,
35
- CredentialServerExtension: () => CredentialServerExtension,
36
- DataServiceImpl: () => DataServiceImpl,
37
- DocumentsSynchronizer: () => DocumentsSynchronizer,
38
- EchoDataMonitor: () => EchoDataMonitor,
39
- LevelDBStorageAdapter: () => LevelDBStorageAdapter,
40
- MOCK_AUTH_PROVIDER: () => MOCK_AUTH_PROVIDER,
41
- MOCK_AUTH_VERIFIER: () => MOCK_AUTH_VERIFIER,
42
- MeshEchoReplicator: () => MeshEchoReplicator,
43
- MetadataStore: () => MetadataStore,
44
- Pipeline: () => Pipeline,
45
- SnapshotManager: () => SnapshotManager,
46
- SnapshotStore: () => SnapshotStore,
47
- Space: () => Space,
48
- SpaceManager: () => SpaceManager,
49
- SpaceProtocol: () => SpaceProtocol,
50
- SpaceProtocolSession: () => SpaceProtocolSession,
51
- TimeframeClock: () => TimeframeClock,
52
- codec: () => codec,
53
- createIdFromSpaceKey: () => createIdFromSpaceKey,
54
- createMappedFeedWriter: () => createMappedFeedWriter,
55
- deriveCollectionIdFromSpaceId: () => deriveCollectionIdFromSpaceId,
56
- diffCollectionState: () => diffCollectionState,
57
- encodingOptions: () => encodingOptions,
58
- getSpaceIdFromCollectionId: () => getSpaceIdFromCollectionId,
59
- getSpaceKeyFromDoc: () => getSpaceKeyFromDoc,
60
- hasInvitationExpired: () => hasInvitationExpired,
61
- mapFeedIndexesToTimeframe: () => mapFeedIndexesToTimeframe,
62
- mapTimeframeToFeedIndexes: () => mapTimeframeToFeedIndexes,
63
- startAfter: () => startAfter,
64
- valueEncoding: () => valueEncoding
65
- });
66
- module.exports = __toCommonJS(chunk_IYTGTZ7D_exports);
67
- var import_hypercore = require("@dxos/hypercore");
68
- var import_protocols = require("@dxos/protocols");
69
- var import_invariant = require("@dxos/invariant");
70
- var import_context = require("@dxos/context");
71
- var import_keys = require("@dxos/keys");
72
- var import_protocols2 = require("@dxos/protocols");
73
- var import_blob = require("@dxos/protocols/proto/dxos/echo/blob");
74
- var import_crypto = require("@dxos/crypto");
75
- var import_protocols3 = require("@dxos/protocols");
76
- var import_async = require("@dxos/async");
77
- var import_automerge = require("@dxos/automerge/automerge");
78
- var import_context2 = require("@dxos/context");
79
- var import_invariant2 = require("@dxos/invariant");
80
- var import_log = require("@dxos/log");
81
- var import_async2 = require("@dxos/async");
82
- var import_automerge2 = require("@dxos/automerge/automerge");
83
- var import_context3 = require("@dxos/context");
84
- var import_util = require("@dxos/util");
85
- var import_async3 = require("@dxos/async");
86
- var import_context4 = require("@dxos/context");
87
- var import_crypto2 = require("@dxos/crypto");
88
- var import_invariant3 = require("@dxos/invariant");
89
- var import_log2 = require("@dxos/log");
90
- var import_protocols4 = require("@dxos/protocols");
91
- var import_teleport = require("@dxos/teleport");
92
- var import_async4 = require("@dxos/async");
93
- var import_debug = require("@dxos/debug");
94
- var import_log3 = require("@dxos/log");
95
- var import_timeframe = require("@dxos/timeframe");
96
- var import_async5 = require("@dxos/async");
97
- var import_context5 = require("@dxos/context");
98
- var import_debug2 = require("@dxos/debug");
99
- var import_feed_store = require("@dxos/feed-store");
100
- var import_invariant4 = require("@dxos/invariant");
101
- var import_keys2 = require("@dxos/keys");
102
- var import_log4 = require("@dxos/log");
103
- var import_timeframe2 = require("@dxos/timeframe");
104
- var import_util2 = require("@dxos/util");
105
- var import_invariant5 = require("@dxos/invariant");
106
- var import_log5 = require("@dxos/log");
107
- var import_async6 = require("@dxos/async");
108
- var import_context6 = require("@dxos/context");
109
- var import_crypto3 = require("@dxos/crypto");
110
- var import_invariant6 = require("@dxos/invariant");
111
- var import_keys3 = require("@dxos/keys");
112
- var import_log6 = require("@dxos/log");
113
- var import_credentials = require("@dxos/protocols/proto/dxos/halo/credentials");
114
- var import_tracing = require("@dxos/tracing");
115
- var import_util3 = require("@dxos/util");
116
- var import_async7 = require("@dxos/async");
117
- var import_context7 = require("@dxos/context");
118
- var import_credentials2 = require("@dxos/credentials");
119
- var import_keys4 = require("@dxos/keys");
120
- var import_log7 = require("@dxos/log");
121
- var import_credentials3 = require("@dxos/protocols/proto/dxos/halo/credentials");
122
- var import_timeframe3 = require("@dxos/timeframe");
123
- var import_tracing2 = require("@dxos/tracing");
124
- var import_util4 = require("@dxos/util");
125
- var import_async8 = require("@dxos/async");
126
- var import_context8 = require("@dxos/context");
127
- var import_protocols5 = require("@dxos/protocols");
128
- var import_teleport2 = require("@dxos/teleport");
129
- var import_crypto4 = require("@dxos/crypto");
130
- var import_keys5 = require("@dxos/keys");
131
- var import_log8 = require("@dxos/log");
132
- var import_network_manager = require("@dxos/network-manager");
133
- var import_teleport3 = require("@dxos/teleport");
134
- var import_teleport_extension_object_sync = require("@dxos/teleport-extension-object-sync");
135
- var import_teleport_extension_replicator = require("@dxos/teleport-extension-replicator");
136
- var import_tracing3 = require("@dxos/tracing");
137
- var import_util5 = require("@dxos/util");
138
- var import_async9 = require("@dxos/async");
139
- var import_debug3 = require("@dxos/debug");
140
- var import_keys6 = require("@dxos/keys");
141
- var import_log9 = require("@dxos/log");
142
- var import_protocols6 = require("@dxos/protocols");
143
- var import_util6 = require("@dxos/util");
144
- var import_codec_protobuf = require("@dxos/codec-protobuf");
145
- var import_invariant7 = require("@dxos/invariant");
146
- var import_keys7 = require("@dxos/keys");
147
- var import_log10 = require("@dxos/log");
148
- var import_async10 = require("@dxos/async");
149
- var import_automerge3 = require("@dxos/automerge/automerge");
150
- var import_automerge_repo = require("@dxos/automerge/automerge-repo");
151
- var import_context9 = require("@dxos/context");
152
- var import_invariant8 = require("@dxos/invariant");
153
- var import_keys8 = require("@dxos/keys");
154
- var import_log11 = require("@dxos/log");
155
- var import_protocols7 = require("@dxos/protocols");
156
- var import_tracing4 = require("@dxos/tracing");
157
- var import_async11 = require("@dxos/async");
158
- var import_automerge_repo2 = require("@dxos/automerge/automerge-repo");
159
- var import_context10 = require("@dxos/context");
160
- var import_invariant9 = require("@dxos/invariant");
161
- var import_log12 = require("@dxos/log");
162
- var import_util7 = require("@dxos/util");
163
- var import_protocols8 = require("@dxos/protocols");
164
- var import_indexing = require("@dxos/indexing");
165
- var import_context11 = require("@dxos/context");
166
- var import_invariant10 = require("@dxos/invariant");
167
- var import_keys9 = require("@dxos/keys");
168
- var import_log13 = require("@dxos/log");
169
- var import_util8 = require("@dxos/util");
170
- var A2 = __toESM(require("@dxos/automerge/automerge"));
171
- var import_automerge_repo3 = require("@dxos/automerge/automerge-repo");
172
- var import_context12 = require("@dxos/context");
173
- var import_invariant11 = require("@dxos/invariant");
174
- var import_log14 = require("@dxos/log");
175
- var import_teleport_extension_automerge_replicator = require("@dxos/teleport-extension-automerge-replicator");
176
- var import_invariant12 = require("@dxos/invariant");
177
- var import_keys10 = require("@dxos/keys");
178
- var import_tracing5 = require("@dxos/tracing");
179
- var import_util9 = require("@dxos/util");
180
- var import_crc_32 = __toESM(require("crc-32"));
181
- var import_async12 = require("@dxos/async");
182
- var import_context13 = require("@dxos/context");
183
- var import_invariant13 = require("@dxos/invariant");
184
- var import_keys11 = require("@dxos/keys");
185
- var import_log15 = require("@dxos/log");
186
- var import_protocols9 = require("@dxos/protocols");
187
- var import_services = require("@dxos/protocols/proto/dxos/client/services");
188
- var import_util10 = require("@dxos/util");
189
- var codec = import_protocols.schema.getCodecForType("dxos.echo.feed.FeedMessage");
190
- var valueEncoding = (0, import_hypercore.createCodecEncoding)(codec);
191
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/common/feeds.ts";
192
- var createMappedFeedWriter = (mapper, writer) => {
193
- (0, import_invariant.invariant)(mapper, void 0, {
194
- F: __dxlog_file,
195
- L: 16,
196
- S: void 0,
197
- A: [
198
- "mapper",
199
- ""
200
- ]
201
- });
202
- (0, import_invariant.invariant)(writer, void 0, {
203
- F: __dxlog_file,
204
- L: 17,
205
- S: void 0,
206
- A: [
207
- "writer",
208
- ""
209
- ]
210
- });
211
- return {
212
- write: async (data, options) => await writer.write(await mapper(data), options)
213
- };
214
- };
215
- var SpaceSnapshot = import_protocols2.schema.getCodecForType("dxos.echo.snapshot.SpaceSnapshot");
216
- var SnapshotManager = class {
217
- constructor(_snapshotStore, _blobStore, _blobSync) {
218
- this._snapshotStore = _snapshotStore;
219
- this._blobStore = _blobStore;
220
- this._blobSync = _blobSync;
221
- }
222
- async _getBlob(blobId) {
223
- const blob = await this._blobStore.get(blobId);
224
- return SpaceSnapshot.decode(blob);
225
- }
226
- async load(ctx, id) {
227
- const blobId = import_keys.PublicKey.fromHex(id).asUint8Array();
228
- const blobMeta = await this._blobStore.getMeta(blobId);
229
- if (blobMeta && blobMeta.state === import_blob.BlobMeta.State.FULLY_PRESENT) {
230
- return this._getBlob(blobId);
231
- }
232
- const fallbackStore = await (0, import_context.cancelWithContext)(ctx, this._snapshotStore.loadSnapshot(id));
233
- if (fallbackStore) {
234
- return fallbackStore;
235
- }
236
- await this._blobSync.download(ctx, blobId);
237
- return this._getBlob(blobId);
238
- }
239
- async store(snapshot) {
240
- const { id } = await this._blobStore.set(SpaceSnapshot.encode(snapshot));
241
- await this._blobSync.notifyBlobAdded(id);
242
- return import_keys.PublicKey.from(id).toHex();
243
- }
244
- };
245
- var SpaceSnapshot2 = import_protocols3.schema.getCodecForType("dxos.echo.snapshot.SpaceSnapshot");
246
- var SnapshotStore = class {
247
- constructor(_directory) {
248
- this._directory = _directory;
249
- }
250
- async saveSnapshot(snapshot) {
251
- const encoded = SpaceSnapshot2.encode(snapshot);
252
- const key = await import_crypto.subtleCrypto.digest("SHA-256", encoded);
253
- const keyString = Buffer.from(key).toString("hex");
254
- const file = await this._directory.getOrCreateFile(keyString);
255
- try {
256
- await file.write(0, Buffer.from(encoded));
257
- } finally {
258
- await file.close();
259
- }
260
- return keyString;
261
- }
262
- async loadSnapshot(key) {
263
- const file = await this._directory.getOrCreateFile(key);
264
- try {
265
- const { size } = await file.stat();
266
- if (size === 0) {
267
- return void 0;
268
- }
269
- const buffer = await file.read(0, size);
270
- return SpaceSnapshot2.decode(buffer);
271
- } finally {
272
- await file.close();
273
- }
274
- }
275
- async listSnapshots() {
276
- const entries = await this._directory.list();
277
- return await Promise.all(entries.map(async (key) => {
278
- const { size } = await this._directory.getOrCreateFile(key).stat();
279
- return {
280
- key,
281
- size
282
- };
283
- }));
284
- }
285
- };
286
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-synchronizer.ts";
287
- var MAX_UPDATE_FREQ = 10;
288
- var DocumentsSynchronizer = class extends import_context2.Resource {
289
- constructor(_params) {
290
- super();
291
- this._params = _params;
292
- this._syncStates = /* @__PURE__ */ new Map();
293
- this._pendingUpdates = /* @__PURE__ */ new Set();
294
- this._sendUpdatesJob = void 0;
295
- }
296
- addDocuments(documentIds, retryCounter = 0) {
297
- if (retryCounter > 3) {
298
- import_log.log.warn("Failed to load document, retry limit reached", {
299
- documentIds
300
- }, {
301
- F: __dxlog_file2,
302
- L: 49,
303
- S: this,
304
- C: (f, a) => f(...a)
305
- });
306
- return;
307
- }
308
- for (const documentId of documentIds) {
309
- const doc = this._params.repo.find(documentId);
310
- doc.whenReady().then(() => {
311
- this._startSync(doc);
312
- this._pendingUpdates.add(doc.documentId);
313
- this._sendUpdatesJob.trigger();
314
- }).catch((error) => {
315
- import_log.log.warn("Failed to load document, wraparound", {
316
- documentId,
317
- error
318
- }, {
319
- F: __dxlog_file2,
320
- L: 63,
321
- S: this,
322
- C: (f, a) => f(...a)
323
- });
324
- this.addDocuments([
325
- documentId
326
- ], retryCounter + 1);
327
- });
328
- }
329
- }
330
- removeDocuments(documentIds) {
331
- for (const documentId of documentIds) {
332
- this._syncStates.get(documentId)?.clearSubscriptions?.();
333
- this._syncStates.delete(documentId);
334
- this._pendingUpdates.delete(documentId);
335
- }
336
- }
337
- async _open() {
338
- this._sendUpdatesJob = new import_async.UpdateScheduler(this._ctx, this._checkAndSendUpdates.bind(this), {
339
- maxFrequency: MAX_UPDATE_FREQ
340
- });
341
- }
342
- async _close() {
343
- await this._sendUpdatesJob.join();
344
- this._syncStates.clear();
345
- }
346
- update(updates) {
347
- for (const { documentId, mutation, isNew } of updates) {
348
- if (isNew) {
349
- const doc = this._params.repo.find(documentId);
350
- doc.update((doc2) => import_automerge.next.loadIncremental(doc2, mutation));
351
- this._startSync(doc);
352
- } else {
353
- this._writeMutation(documentId, mutation);
354
- }
355
- }
356
- }
357
- _startSync(doc) {
358
- if (this._syncStates.has(doc.documentId)) {
359
- import_log.log.info("Document already being synced", {
360
- documentId: doc.documentId
361
- }, {
362
- F: __dxlog_file2,
363
- L: 102,
364
- S: this,
365
- C: (f, a) => f(...a)
366
- });
367
- return;
368
- }
369
- const syncState = {
370
- handle: doc
371
- };
372
- this._subscribeForChanges(syncState);
373
- this._syncStates.set(doc.documentId, syncState);
374
- }
375
- _subscribeForChanges(syncState) {
376
- const handler = () => {
377
- this._pendingUpdates.add(syncState.handle.documentId);
378
- this._sendUpdatesJob.trigger();
379
- };
380
- syncState.handle.on("heads-changed", handler);
381
- syncState.clearSubscriptions = () => syncState.handle.off("heads-changed", handler);
382
- }
383
- async _checkAndSendUpdates() {
384
- const updates = [];
385
- const docsWithPendingUpdates = Array.from(this._pendingUpdates);
386
- this._pendingUpdates.clear();
387
- for (const documentId of docsWithPendingUpdates) {
388
- const update = this._getPendingChanges(documentId);
389
- if (update) {
390
- updates.push({
391
- documentId,
392
- mutation: update
393
- });
394
- }
395
- }
396
- if (updates.length > 0) {
397
- this._params.sendUpdates({
398
- updates
399
- });
400
- }
401
- }
402
- _getPendingChanges(documentId) {
403
- const syncState = this._syncStates.get(documentId);
404
- (0, import_invariant2.invariant)(syncState, "Sync state for document not found", {
405
- F: __dxlog_file2,
406
- L: 143,
407
- S: this,
408
- A: [
409
- "syncState",
410
- "'Sync state for document not found'"
411
- ]
412
- });
413
- const doc = syncState.handle.docSync();
414
- if (!doc) {
415
- return;
416
- }
417
- const mutation = syncState.lastSentHead ? import_automerge.next.saveSince(doc, syncState.lastSentHead) : import_automerge.next.save(doc);
418
- if (mutation.length === 0) {
419
- return;
420
- }
421
- syncState.lastSentHead = import_automerge.next.getHeads(doc);
422
- return mutation;
423
- }
424
- _writeMutation(documentId, mutation) {
425
- const syncState = this._syncStates.get(documentId);
426
- (0, import_invariant2.invariant)(syncState, "Sync state for document not found", {
427
- F: __dxlog_file2,
428
- L: 158,
429
- S: this,
430
- A: [
431
- "syncState",
432
- "'Sync state for document not found'"
433
- ]
434
- });
435
- syncState.handle.update((doc) => {
436
- const headsBefore = import_automerge.next.getHeads(doc);
437
- const newDoc = import_automerge.next.loadIncremental(doc, mutation);
438
- if (import_automerge.next.equals(headsBefore, syncState.lastSentHead)) {
439
- syncState.lastSentHead = import_automerge.next.getHeads(newDoc);
440
- }
441
- return newDoc;
442
- });
443
- }
444
- };
445
- var MIN_QUERY_INTERVAL = 5e3;
446
- var POLL_INTERVAL = 3e4;
447
- var CollectionSynchronizer = class extends import_context3.Resource {
448
- constructor(params) {
449
- super();
450
- this._perCollectionStates = /* @__PURE__ */ new Map();
451
- this._connectedPeers = /* @__PURE__ */ new Set();
452
- this.remoteStateUpdated = new import_async2.Event();
453
- this._sendCollectionState = params.sendCollectionState;
454
- this._queryCollectionState = params.queryCollectionState;
455
- this._shouldSyncCollection = params.shouldSyncCollection;
456
- }
457
- async _open(ctx) {
458
- (0, import_async2.scheduleTaskInterval)(this._ctx, async () => {
459
- for (const collectionId of this._perCollectionStates.keys()) {
460
- this.refreshCollection(collectionId);
461
- await (0, import_async2.asyncReturn)();
462
- }
463
- }, POLL_INTERVAL);
464
- }
465
- getRegisteredCollectionIds() {
466
- return [
467
- ...this._perCollectionStates.keys()
468
- ];
469
- }
470
- getLocalCollectionState(collectionId) {
471
- return this._getPerCollectionState(collectionId).localState;
472
- }
473
- setLocalCollectionState(collectionId, state) {
474
- this._getPerCollectionState(collectionId).localState = state;
475
- queueMicrotask(async () => {
476
- if (!this._ctx.disposed) {
477
- this._refreshInterestedPeers(collectionId);
478
- this.refreshCollection(collectionId);
479
- }
480
- });
481
- }
482
- getRemoteCollectionStates(collectionId) {
483
- return this._getPerCollectionState(collectionId).remoteStates;
484
- }
485
- refreshCollection(collectionId) {
486
- let scheduleAnotherRefresh = false;
487
- const state = this._getPerCollectionState(collectionId);
488
- for (const peerId of this._connectedPeers) {
489
- if (state.interestedPeers.has(peerId)) {
490
- const lastQueried = state.lastQueried.get(peerId) ?? 0;
491
- if (Date.now() - lastQueried > MIN_QUERY_INTERVAL) {
492
- state.lastQueried.set(peerId, Date.now());
493
- this._queryCollectionState(collectionId, peerId);
494
- } else {
495
- scheduleAnotherRefresh = true;
496
- }
497
- }
498
- }
499
- if (scheduleAnotherRefresh) {
500
- (0, import_async2.scheduleTask)(this._ctx, () => this.refreshCollection(collectionId), MIN_QUERY_INTERVAL);
501
- }
502
- }
503
- /**
504
- * Callback when a connection to a peer is established.
505
- */
506
- onConnectionOpen(peerId) {
507
- this._connectedPeers.add(peerId);
508
- queueMicrotask(async () => {
509
- if (this._ctx.disposed) {
510
- return;
511
- }
512
- for (const [collectionId, state] of this._perCollectionStates.entries()) {
513
- if (this._shouldSyncCollection(collectionId, peerId)) {
514
- state.interestedPeers.add(peerId);
515
- state.lastQueried.set(peerId, Date.now());
516
- this._queryCollectionState(collectionId, peerId);
517
- }
518
- }
519
- });
520
- }
521
- /**
522
- * Callback when a connection to a peer is closed.
523
- */
524
- onConnectionClosed(peerId) {
525
- this._connectedPeers.delete(peerId);
526
- for (const perCollectionState of this._perCollectionStates.values()) {
527
- perCollectionState.remoteStates.delete(peerId);
528
- }
529
- }
530
- /**
531
- * Callback when a peer queries the state of a collection.
532
- */
533
- onCollectionStateQueried(collectionId, peerId) {
534
- const perCollectionState = this._getPerCollectionState(collectionId);
535
- if (perCollectionState.localState) {
536
- this._sendCollectionState(collectionId, peerId, perCollectionState.localState);
537
- }
538
- }
539
- /**
540
- * Callback when a peer sends the state of a collection.
541
- */
542
- onRemoteStateReceived(collectionId, peerId, state) {
543
- const perCollectionState = this._getPerCollectionState(collectionId);
544
- perCollectionState.remoteStates.set(peerId, state);
545
- this.remoteStateUpdated.emit({
546
- peerId,
547
- collectionId
548
- });
549
- }
550
- _getPerCollectionState(collectionId) {
551
- return (0, import_util.defaultMap)(this._perCollectionStates, collectionId, () => ({
552
- localState: void 0,
553
- remoteStates: /* @__PURE__ */ new Map(),
554
- interestedPeers: /* @__PURE__ */ new Set(),
555
- lastQueried: /* @__PURE__ */ new Map()
556
- }));
557
- }
558
- _refreshInterestedPeers(collectionId) {
559
- for (const peerId of this._connectedPeers) {
560
- if (this._shouldSyncCollection(collectionId, peerId)) {
561
- this._getPerCollectionState(collectionId).interestedPeers.add(peerId);
562
- } else {
563
- this._getPerCollectionState(collectionId).interestedPeers.delete(peerId);
564
- }
565
- }
566
- }
567
- };
568
- var diffCollectionState = (local, remote) => {
569
- const allDocuments = /* @__PURE__ */ new Set([
570
- ...Object.keys(local.documents),
571
- ...Object.keys(remote.documents)
572
- ]);
573
- const different = [];
574
- for (const documentId of allDocuments) {
575
- if (!local.documents[documentId] || !remote.documents[documentId] || !import_automerge2.next.equals(local.documents[documentId], remote.documents[documentId])) {
576
- different.push(documentId);
577
- }
578
- }
579
- return {
580
- different
581
- };
582
- };
583
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/auth.ts";
584
- var AuthExtension = class extends import_teleport.RpcExtension {
585
- constructor(_authParams) {
586
- super({
587
- requested: {
588
- AuthService: import_protocols4.schema.getService("dxos.mesh.teleport.auth.AuthService")
589
- },
590
- exposed: {
591
- AuthService: import_protocols4.schema.getService("dxos.mesh.teleport.auth.AuthService")
592
- },
593
- timeout: 60 * 1e3
594
- });
595
- this._authParams = _authParams;
596
- this._ctx = new import_context4.Context({
597
- onError: (err) => {
598
- import_log2.log.catch(err, void 0, {
599
- F: __dxlog_file3,
600
- L: 28,
601
- S: this,
602
- C: (f, a) => f(...a)
603
- });
604
- }
605
- }, {
606
- F: __dxlog_file3,
607
- L: 26
608
- });
609
- }
610
- async getHandlers() {
611
- return {
612
- AuthService: {
613
- authenticate: async ({ challenge }) => {
614
- try {
615
- const credential = await this._authParams.provider(challenge);
616
- if (!credential) {
617
- throw new Error("auth rejected");
618
- }
619
- return {
620
- credential
621
- };
622
- } catch (err) {
623
- import_log2.log.error("failed to generate auth credentials", err, {
624
- F: __dxlog_file3,
625
- L: 55,
626
- S: this,
627
- C: (f, a) => f(...a)
628
- });
629
- throw new Error("auth rejected");
630
- }
631
- }
632
- }
633
- };
634
- }
635
- async onOpen(context) {
636
- await super.onOpen(context);
637
- (0, import_async3.scheduleTask)(this._ctx, async () => {
638
- try {
639
- const challenge = (0, import_crypto2.randomBytes)(32);
640
- const { credential } = await this.rpc.AuthService.authenticate({
641
- challenge
642
- });
643
- (0, import_invariant3.invariant)(credential?.length > 0, "invalid credential", {
644
- F: __dxlog_file3,
645
- L: 69,
646
- S: this,
647
- A: [
648
- "credential?.length > 0",
649
- "'invalid credential'"
650
- ]
651
- });
652
- const success = await this._authParams.verifier(challenge, credential);
653
- (0, import_invariant3.invariant)(success, "credential not verified", {
654
- F: __dxlog_file3,
655
- L: 71,
656
- S: this,
657
- A: [
658
- "success",
659
- "'credential not verified'"
660
- ]
661
- });
662
- (0, import_async3.runInContext)(this._ctx, () => this._authParams.onAuthSuccess());
663
- } catch (err) {
664
- (0, import_log2.log)("auth failed", err, {
665
- F: __dxlog_file3,
666
- L: 74,
667
- S: this,
668
- C: (f, a) => f(...a)
669
- });
670
- this.close();
671
- this._authParams.onAuthFailure();
672
- }
673
- });
674
- }
675
- async onClose() {
676
- await this._ctx.dispose();
677
- await super.onClose();
678
- }
679
- async onAbort() {
680
- await this._ctx.dispose();
681
- await super.onAbort();
682
- }
683
- };
684
- function _ts_decorate(decorators, target, key, desc) {
685
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
686
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
687
- r = Reflect.decorate(decorators, target, key, desc);
688
- else
689
- for (var i = decorators.length - 1; i >= 0; i--)
690
- if (d = decorators[i])
691
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
692
- return c > 3 && r && Object.defineProperty(target, key, r), r;
693
- }
694
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/timeframe-clock.ts";
695
- var mapTimeframeToFeedIndexes = (timeframe) => timeframe.frames().map(([feedKey, index]) => ({
696
- feedKey,
697
- index
698
- }));
699
- var mapFeedIndexesToTimeframe = (indexes) => new import_timeframe.Timeframe(indexes.map(({ feedKey, index }) => [
700
- feedKey,
701
- index
702
- ]));
703
- var startAfter = (timeframe) => timeframe.frames().map(([feedKey, index]) => ({
704
- feedKey,
705
- index: index + 1
706
- }));
707
- var TimeframeClock = class {
708
- constructor(_timeframe = new import_timeframe.Timeframe()) {
709
- this._timeframe = _timeframe;
710
- this.update = new import_async4.Event();
711
- this._pendingTimeframe = _timeframe;
712
- }
713
- /**
714
- * Timeframe that was processed by ECHO.
715
- */
716
- get timeframe() {
717
- return this._timeframe;
718
- }
719
- /**
720
- * Timeframe that is currently being processed by ECHO.
721
- * Will be equal to `timeframe` after the processing is complete.
722
- */
723
- get pendingTimeframe() {
724
- return this._pendingTimeframe;
725
- }
726
- setTimeframe(timeframe) {
727
- this._timeframe = timeframe;
728
- this._pendingTimeframe = timeframe;
729
- this.update.emit(this._timeframe);
730
- }
731
- updatePendingTimeframe(key, seq) {
732
- this._pendingTimeframe = import_timeframe.Timeframe.merge(this._pendingTimeframe, new import_timeframe.Timeframe([
733
- [
734
- key,
735
- seq
736
- ]
737
- ]));
738
- }
739
- updateTimeframe() {
740
- this._timeframe = this._pendingTimeframe;
741
- this.update.emit(this._timeframe);
742
- }
743
- hasGaps(timeframe) {
744
- const gaps = import_timeframe.Timeframe.dependencies(timeframe, this._timeframe);
745
- return !gaps.isEmpty();
746
- }
747
- async waitUntilReached(target) {
748
- (0, import_log3.log)("waitUntilReached", {
749
- target,
750
- current: this._timeframe
751
- }, {
752
- F: __dxlog_file4,
753
- L: 70,
754
- S: this,
755
- C: (f, a) => f(...a)
756
- });
757
- await this.update.waitForCondition(() => {
758
- (0, import_log3.log)("check if reached", {
759
- target,
760
- current: this._timeframe,
761
- deps: import_timeframe.Timeframe.dependencies(target, this._timeframe)
762
- }, {
763
- F: __dxlog_file4,
764
- L: 72,
765
- S: this,
766
- C: (f, a) => f(...a)
767
- });
768
- return import_timeframe.Timeframe.dependencies(target, this._timeframe).isEmpty();
769
- });
770
- }
771
- };
772
- _ts_decorate([
773
- (0, import_debug.timed)(5e3)
774
- ], TimeframeClock.prototype, "waitUntilReached", null);
775
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts";
776
- var createMessageSelector = (timeframeClock) => {
777
- return (messages) => {
778
- for (let i = 0; i < messages.length; i++) {
779
- const { data: { timeframe } } = messages[i];
780
- (0, import_invariant5.invariant)(timeframe, void 0, {
781
- F: __dxlog_file5,
782
- L: 25,
783
- S: void 0,
784
- A: [
785
- "timeframe",
786
- ""
787
- ]
788
- });
789
- if (!timeframeClock.hasGaps(timeframe)) {
790
- return i;
791
- }
792
- }
793
- (0, import_log5.log)("Skipping...", void 0, {
794
- F: __dxlog_file5,
795
- L: 33,
796
- S: void 0,
797
- C: (f, a) => f(...a)
798
- });
799
- };
800
- };
801
- function _ts_decorate2(decorators, target, key, desc) {
802
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
803
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
804
- r = Reflect.decorate(decorators, target, key, desc);
805
- else
806
- for (var i = decorators.length - 1; i >= 0; i--)
807
- if (d = decorators[i])
808
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
809
- return c > 3 && r && Object.defineProperty(target, key, r), r;
810
- }
811
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts";
812
- var PipelineState = class {
813
- constructor(_feeds, _timeframeClock) {
814
- this._feeds = _feeds;
815
- this._timeframeClock = _timeframeClock;
816
- this._ctx = new import_context5.Context(void 0, {
817
- F: __dxlog_file6,
818
- L: 41
819
- });
820
- this.timeframeUpdate = this._timeframeClock.update;
821
- this.stalled = new import_async5.Event();
822
- this._startTimeframe = new import_timeframe2.Timeframe();
823
- this._reachedTarget = false;
824
- }
825
- /**
826
- * Latest theoretical timeframe based on the last mutation in each feed.
827
- * NOTE: This might never be reached if the mutation dependencies
828
- */
829
- // TODO(dmaretskyi): Rename `totalTimeframe`? or `lastTimeframe`.
830
- get endTimeframe() {
831
- return mapFeedIndexesToTimeframe(Array.from(this._feeds.values()).filter((feed) => feed.length > 0).map((feed) => ({
832
- feedKey: feed.key,
833
- index: feed.length - 1
834
- })));
835
- }
836
- get startTimeframe() {
837
- return this._startTimeframe;
838
- }
839
- get timeframe() {
840
- return this._timeframeClock.timeframe;
841
- }
842
- get pendingTimeframe() {
843
- return this._timeframeClock.pendingTimeframe;
844
- }
845
- get targetTimeframe() {
846
- return this._targetTimeframe ? this._targetTimeframe : new import_timeframe2.Timeframe();
847
- }
848
- get reachedTarget() {
849
- return this._reachedTarget;
850
- }
851
- get feeds() {
852
- return Array.from(this._feeds.values());
853
- }
854
- async waitUntilTimeframe(target) {
855
- await this._timeframeClock.waitUntilReached(target);
856
- }
857
- setTargetTimeframe(target) {
858
- this._targetTimeframe = target;
859
- }
860
- /**
861
- * Wait until the pipeline processes all messages in the feed and reaches the target timeframe if that is set.
862
- *
863
- * This function will resolve immediately if the pipeline is stalled.
864
- *
865
- * @param timeout Timeout in milliseconds to specify the maximum wait time.
866
- */
867
- async waitUntilReachedTargetTimeframe({ ctx = new import_context5.Context(void 0, {
868
- F: __dxlog_file6,
869
- L: 129
870
- }), timeout, breakOnStall = true } = {}) {
871
- (0, import_log4.log)("waitUntilReachedTargetTimeframe", {
872
- timeout,
873
- current: this.timeframe,
874
- target: this.targetTimeframe
875
- }, {
876
- F: __dxlog_file6,
877
- L: 133,
878
- S: this,
879
- C: (f, a) => f(...a)
880
- });
881
- this._reachedTargetPromise ??= Promise.race([
882
- this._timeframeClock.update.waitForCondition(() => {
883
- return import_timeframe2.Timeframe.dependencies(this.targetTimeframe, this.timeframe).isEmpty();
884
- }),
885
- ...breakOnStall ? [
886
- this.stalled.discardParameter().waitForCount(1)
887
- ] : []
888
- ]);
889
- let done = false;
890
- if (timeout) {
891
- return Promise.race([
892
- (0, import_context5.rejectOnDispose)(ctx),
893
- (0, import_context5.rejectOnDispose)(this._ctx),
894
- this._reachedTargetPromise.then(() => {
895
- done = true;
896
- this._reachedTarget = true;
897
- }),
898
- (0, import_async5.sleepWithContext)(this._ctx, timeout).then(() => {
899
- if (done) {
900
- return;
901
- }
902
- import_log4.log.warn("waitUntilReachedTargetTimeframe timed out", {
903
- timeout,
904
- current: this.timeframe,
905
- target: this.targetTimeframe,
906
- dependencies: import_timeframe2.Timeframe.dependencies(this.targetTimeframe, this.timeframe)
907
- }, {
908
- F: __dxlog_file6,
909
- L: 161,
910
- S: this,
911
- C: (f, a) => f(...a)
912
- });
913
- })
914
- ]);
915
- } else {
916
- return this._reachedTargetPromise;
917
- }
918
- }
919
- };
920
- var Pipeline = class {
921
- constructor() {
922
- this._timeframeClock = new TimeframeClock(new import_timeframe2.Timeframe());
923
- this._feeds = new import_util2.ComplexMap(import_keys2.PublicKey.hash);
924
- this._state = new PipelineState(this._feeds, this._timeframeClock);
925
- this._processingTrigger = new import_async5.Trigger().wake();
926
- this._pauseTrigger = new import_async5.Trigger().wake();
927
- this._downloads = new import_util2.ComplexMap((value) => import_keys2.PublicKey.hash(value.key));
928
- this._isStopping = false;
929
- this._isStarted = false;
930
- this._isBeingConsumed = false;
931
- this._isPaused = false;
932
- }
933
- get state() {
934
- return this._state;
935
- }
936
- get writer() {
937
- (0, import_invariant4.invariant)(this._writer, "Writer not set.", {
938
- F: __dxlog_file6,
939
- L: 243,
940
- S: this,
941
- A: [
942
- "this._writer",
943
- "'Writer not set.'"
944
- ]
945
- });
946
- return this._writer;
947
- }
948
- hasFeed(feedKey) {
949
- return this._feeds.has(feedKey);
950
- }
951
- getFeeds() {
952
- return this._feedSetIterator.feeds;
953
- }
954
- // NOTE: This cannot be synchronized with `stop` because stop waits for the mutation processing to complete,
955
- // which might be opening feeds during the mutation processing, which w
956
- async addFeed(feed) {
957
- this._feeds.set(feed.key, feed);
958
- if (this._feedSetIterator) {
959
- await this._feedSetIterator.addFeed(feed);
960
- }
961
- if (this._isStarted && !this._isPaused) {
962
- this._setFeedDownloadState(feed);
963
- }
964
- }
965
- setWriteFeed(feed) {
966
- (0, import_invariant4.invariant)(!this._writer, "Writer already set.", {
967
- F: __dxlog_file6,
968
- L: 270,
969
- S: this,
970
- A: [
971
- "!this._writer",
972
- "'Writer already set.'"
973
- ]
974
- });
975
- (0, import_invariant4.invariant)(feed.properties.writable, "Feed must be writable.", {
976
- F: __dxlog_file6,
977
- L: 271,
978
- S: this,
979
- A: [
980
- "feed.properties.writable",
981
- "'Feed must be writable.'"
982
- ]
983
- });
984
- this._writer = createMappedFeedWriter((payload) => ({
985
- timeframe: this._timeframeClock.timeframe,
986
- payload
987
- }), feed.createFeedWriter());
988
- }
989
- async start() {
990
- (0, import_invariant4.invariant)(!this._isStarted, "Pipeline is already started.", {
991
- F: __dxlog_file6,
992
- L: 284,
993
- S: this,
994
- A: [
995
- "!this._isStarted",
996
- "'Pipeline is already started.'"
997
- ]
998
- });
999
- (0, import_log4.log)("starting...", void 0, {
1000
- F: __dxlog_file6,
1001
- L: 285,
1002
- S: this,
1003
- C: (f, a) => f(...a)
1004
- });
1005
- await this._initIterator();
1006
- await this._feedSetIterator.open();
1007
- this._isStarted = true;
1008
- (0, import_log4.log)("started", void 0, {
1009
- F: __dxlog_file6,
1010
- L: 289,
1011
- S: this,
1012
- C: (f, a) => f(...a)
1013
- });
1014
- if (!this._isPaused) {
1015
- for (const feed of this._feeds.values()) {
1016
- this._setFeedDownloadState(feed);
1017
- }
1018
- }
1019
- }
1020
- async stop() {
1021
- (0, import_log4.log)("stopping...", void 0, {
1022
- F: __dxlog_file6,
1023
- L: 300,
1024
- S: this,
1025
- C: (f, a) => f(...a)
1026
- });
1027
- this._isStopping = true;
1028
- for (const [feed, handle] of this._downloads.entries()) {
1029
- feed.undownload(handle);
1030
- }
1031
- this._downloads.clear();
1032
- await this._feedSetIterator?.close();
1033
- await this._processingTrigger.wait();
1034
- await this._state._ctx.dispose();
1035
- this._state._ctx = new import_context5.Context(void 0, {
1036
- F: __dxlog_file6,
1037
- L: 309
1038
- });
1039
- this._state._reachedTargetPromise = void 0;
1040
- this._state._reachedTarget = false;
1041
- this._isStarted = false;
1042
- (0, import_log4.log)("stopped", void 0, {
1043
- F: __dxlog_file6,
1044
- L: 313,
1045
- S: this,
1046
- C: (f, a) => f(...a)
1047
- });
1048
- }
1049
- /**
1050
- * @param timeframe Timeframe of already processed messages.
1051
- * The pipeline will start processing messages AFTER this timeframe.
1052
- */
1053
- async setCursor(timeframe) {
1054
- (0, import_invariant4.invariant)(!this._isStarted || this._isPaused, "Invalid state.", {
1055
- F: __dxlog_file6,
1056
- L: 322,
1057
- S: this,
1058
- A: [
1059
- "!this._isStarted || this._isPaused",
1060
- "'Invalid state.'"
1061
- ]
1062
- });
1063
- this._state._startTimeframe = timeframe;
1064
- this._timeframeClock.setTimeframe(timeframe);
1065
- if (this._feedSetIterator) {
1066
- await this._feedSetIterator.close();
1067
- await this._initIterator();
1068
- await this._feedSetIterator.open();
1069
- }
1070
- }
1071
- /**
1072
- * Calling pause while processing will cause a deadlock.
1073
- */
1074
- async pause() {
1075
- if (this._isPaused) {
1076
- return;
1077
- }
1078
- this._pauseTrigger.reset();
1079
- await this._processingTrigger.wait();
1080
- this._isPaused = true;
1081
- }
1082
- async unpause() {
1083
- (0, import_invariant4.invariant)(this._isPaused, "Pipeline is not paused.", {
1084
- F: __dxlog_file6,
1085
- L: 351,
1086
- S: this,
1087
- A: [
1088
- "this._isPaused",
1089
- "'Pipeline is not paused.'"
1090
- ]
1091
- });
1092
- this._pauseTrigger.wake();
1093
- this._isPaused = false;
1094
- for (const feed of this._feeds.values()) {
1095
- this._setFeedDownloadState(feed);
1096
- }
1097
- }
1098
- /**
1099
- * Starts to iterate over the ordered messages from the added feeds.
1100
- * Updates the timeframe clock after the message has bee processed.
1101
- */
1102
- async *consume() {
1103
- (0, import_invariant4.invariant)(!this._isBeingConsumed, "Pipeline is already being consumed.", {
1104
- F: __dxlog_file6,
1105
- L: 366,
1106
- S: this,
1107
- A: [
1108
- "!this._isBeingConsumed",
1109
- "'Pipeline is already being consumed.'"
1110
- ]
1111
- });
1112
- this._isBeingConsumed = true;
1113
- (0, import_invariant4.invariant)(this._feedSetIterator, "Iterator not initialized.", {
1114
- F: __dxlog_file6,
1115
- L: 369,
1116
- S: this,
1117
- A: [
1118
- "this._feedSetIterator",
1119
- "'Iterator not initialized.'"
1120
- ]
1121
- });
1122
- let lastFeedSetIterator = this._feedSetIterator;
1123
- let iterable = lastFeedSetIterator[Symbol.asyncIterator]();
1124
- while (!this._isStopping) {
1125
- await this._pauseTrigger.wait();
1126
- if (lastFeedSetIterator !== this._feedSetIterator) {
1127
- (0, import_invariant4.invariant)(this._feedSetIterator, "Iterator not initialized.", {
1128
- F: __dxlog_file6,
1129
- L: 378,
1130
- S: this,
1131
- A: [
1132
- "this._feedSetIterator",
1133
- "'Iterator not initialized.'"
1134
- ]
1135
- });
1136
- lastFeedSetIterator = this._feedSetIterator;
1137
- iterable = lastFeedSetIterator[Symbol.asyncIterator]();
1138
- }
1139
- const { done, value } = await iterable.next();
1140
- if (!done) {
1141
- const block = value ?? (0, import_debug2.failUndefined)();
1142
- this._processingTrigger.reset();
1143
- this._timeframeClock.updatePendingTimeframe(import_keys2.PublicKey.from(block.feedKey), block.seq);
1144
- yield block;
1145
- this._processingTrigger.wake();
1146
- this._timeframeClock.updateTimeframe();
1147
- }
1148
- }
1149
- this._isBeingConsumed = false;
1150
- }
1151
- _setFeedDownloadState(feed) {
1152
- let handle = this._downloads.get(feed);
1153
- if (handle) {
1154
- feed.undownload(handle);
1155
- }
1156
- const timeframe = this._state._startTimeframe;
1157
- const seq = timeframe.get(feed.key) ?? -1;
1158
- (0, import_log4.log)("download", {
1159
- feed: feed.key.truncate(),
1160
- seq,
1161
- length: feed.length
1162
- }, {
1163
- F: __dxlog_file6,
1164
- L: 407,
1165
- S: this,
1166
- C: (f, a) => f(...a)
1167
- });
1168
- handle = feed.download({
1169
- start: seq + 1,
1170
- linear: true
1171
- }, (err, data) => {
1172
- if (err) {
1173
- } else {
1174
- import_log4.log.info("downloaded", {
1175
- data
1176
- }, {
1177
- F: __dxlog_file6,
1178
- L: 412,
1179
- S: this,
1180
- C: (f, a) => f(...a)
1181
- });
1182
- }
1183
- });
1184
- this._downloads.set(feed, handle);
1185
- }
1186
- async _initIterator() {
1187
- this._feedSetIterator = new import_feed_store.FeedSetIterator(createMessageSelector(this._timeframeClock), {
1188
- start: startAfter(this._timeframeClock.timeframe),
1189
- stallTimeout: 1e3
1190
- });
1191
- this._feedSetIterator.stalled.on((iterator) => {
1192
- import_log4.log.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, void 0, {
1193
- F: __dxlog_file6,
1194
- L: 426,
1195
- S: this,
1196
- C: (f, a) => f(...a)
1197
- });
1198
- this._state.stalled.emit();
1199
- });
1200
- for (const feed of this._feeds.values()) {
1201
- await this._feedSetIterator.addFeed(feed);
1202
- }
1203
- }
1204
- };
1205
- _ts_decorate2([
1206
- import_async5.synchronized
1207
- ], Pipeline.prototype, "start", null);
1208
- _ts_decorate2([
1209
- import_async5.synchronized
1210
- ], Pipeline.prototype, "stop", null);
1211
- _ts_decorate2([
1212
- import_async5.synchronized
1213
- ], Pipeline.prototype, "setCursor", null);
1214
- _ts_decorate2([
1215
- import_async5.synchronized
1216
- ], Pipeline.prototype, "pause", null);
1217
- _ts_decorate2([
1218
- import_async5.synchronized
1219
- ], Pipeline.prototype, "unpause", null);
1220
- function _ts_decorate3(decorators, target, key, desc) {
1221
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1222
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1223
- r = Reflect.decorate(decorators, target, key, desc);
1224
- else
1225
- for (var i = decorators.length - 1; i >= 0; i--)
1226
- if (d = decorators[i])
1227
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1228
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1229
- }
1230
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/control-pipeline.ts";
1231
- var TIMEFRAME_SAVE_DEBOUNCE_INTERVAL = 500;
1232
- var CONTROL_PIPELINE_SNAPSHOT_DELAY = 1e4;
1233
- var USE_SNAPSHOTS = true;
1234
- var ControlPipeline = class {
1235
- constructor({ spaceKey, genesisFeed, feedProvider, metadataStore }) {
1236
- this._ctx = new import_context7.Context(void 0, {
1237
- F: __dxlog_file7,
1238
- L: 47
1239
- });
1240
- this._lastTimeframeSaveTime = Date.now();
1241
- this.onFeedAdmitted = new import_util4.Callback();
1242
- this._usage = new import_tracing2.TimeUsageCounter();
1243
- this._mutations = new import_tracing2.TimeSeriesCounter();
1244
- this._snapshotTask = new import_async7.DeferredTask(this._ctx, async () => {
1245
- await (0, import_async7.sleepWithContext)(this._ctx, CONTROL_PIPELINE_SNAPSHOT_DELAY);
1246
- await this._saveSnapshot();
1247
- });
1248
- this._spaceKey = spaceKey;
1249
- this._metadata = metadataStore;
1250
- this._pipeline = new Pipeline();
1251
- void this._pipeline.addFeed(genesisFeed);
1252
- this._spaceStateMachine = new import_credentials2.SpaceStateMachine(spaceKey);
1253
- this._spaceStateMachine.onFeedAdmitted.set(async (info) => {
1254
- (0, import_log7.log)("feed admitted", {
1255
- key: info.key
1256
- }, {
1257
- F: __dxlog_file7,
1258
- L: 82,
1259
- S: this,
1260
- C: (f, a) => f(...a)
1261
- });
1262
- if (info.assertion.designation === import_credentials3.AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
1263
- queueMicrotask(async () => {
1264
- try {
1265
- const feed = await feedProvider(info.key);
1266
- if (!this._pipeline.hasFeed(feed.key)) {
1267
- await this._pipeline.addFeed(feed);
1268
- }
1269
- } catch (err) {
1270
- import_log7.log.catch(err, void 0, {
1271
- F: __dxlog_file7,
1272
- L: 93,
1273
- S: this,
1274
- C: (f, a) => f(...a)
1275
- });
1276
- }
1277
- });
1278
- }
1279
- await this.onFeedAdmitted.callIfSet(info);
1280
- });
1281
- this.onMemberRoleChanged = this._spaceStateMachine.onMemberRoleChanged;
1282
- this.onCredentialProcessed = this._spaceStateMachine.onCredentialProcessed;
1283
- this.onDelegatedInvitation = this._spaceStateMachine.onDelegatedInvitation;
1284
- this.onDelegatedInvitationRemoved = this._spaceStateMachine.onDelegatedInvitationRemoved;
1285
- }
1286
- get spaceState() {
1287
- return this._spaceStateMachine;
1288
- }
1289
- get pipeline() {
1290
- return this._pipeline;
1291
- }
1292
- async setWriteFeed(feed) {
1293
- await this._pipeline.addFeed(feed);
1294
- this._pipeline.setWriteFeed(feed);
1295
- }
1296
- async start() {
1297
- const snapshot = this._metadata.getSpaceControlPipelineSnapshot(this._spaceKey);
1298
- (0, import_log7.log)("load snapshot", {
1299
- key: this._spaceKey,
1300
- present: !!snapshot,
1301
- tf: snapshot?.timeframe
1302
- }, {
1303
- F: __dxlog_file7,
1304
- L: 123,
1305
- S: this,
1306
- C: (f, a) => f(...a)
1307
- });
1308
- if (USE_SNAPSHOTS && snapshot) {
1309
- await this._processSnapshot(snapshot);
1310
- }
1311
- (0, import_log7.log)("starting...", void 0, {
1312
- F: __dxlog_file7,
1313
- L: 128,
1314
- S: this,
1315
- C: (f, a) => f(...a)
1316
- });
1317
- setTimeout(async () => {
1318
- void this._consumePipeline(new import_context7.Context(void 0, {
1319
- F: __dxlog_file7,
1320
- L: 130
1321
- }));
1322
- });
1323
- await this._pipeline.start();
1324
- (0, import_log7.log)("started", void 0, {
1325
- F: __dxlog_file7,
1326
- L: 134,
1327
- S: this,
1328
- C: (f, a) => f(...a)
1329
- });
1330
- }
1331
- async _processSnapshot(snapshot) {
1332
- await this._pipeline.setCursor(snapshot.timeframe);
1333
- for (const message of snapshot.messages ?? []) {
1334
- const result = await this._spaceStateMachine.process(message.credential, {
1335
- sourceFeed: message.feedKey,
1336
- skipVerification: true
1337
- });
1338
- if (!result) {
1339
- import_log7.log.warn("credential processing failed from snapshot", {
1340
- message
1341
- }, {
1342
- F: __dxlog_file7,
1343
- L: 147,
1344
- S: this,
1345
- C: (f, a) => f(...a)
1346
- });
1347
- }
1348
- }
1349
- }
1350
- async _saveSnapshot() {
1351
- await this._pipeline.pause();
1352
- const snapshot = {
1353
- timeframe: this._pipeline.state.timeframe,
1354
- messages: this._spaceStateMachine.credentialEntries.map((entry) => ({
1355
- feedKey: entry.sourceFeed,
1356
- credential: entry.credential
1357
- }))
1358
- };
1359
- await this._pipeline.unpause();
1360
- (0, import_log7.log)("save snapshot", {
1361
- key: this._spaceKey,
1362
- snapshot
1363
- }, {
1364
- F: __dxlog_file7,
1365
- L: 163,
1366
- S: this,
1367
- C: (f, a) => f(...a)
1368
- });
1369
- await this._metadata.setSpaceControlPipelineSnapshot(this._spaceKey, snapshot);
1370
- }
1371
- async _consumePipeline(ctx) {
1372
- for await (const msg of this._pipeline.consume()) {
1373
- const span = this._usage.beginRecording();
1374
- this._mutations.inc();
1375
- try {
1376
- await this._processMessage(ctx, msg);
1377
- } catch (err) {
1378
- import_log7.log.catch(err, void 0, {
1379
- F: __dxlog_file7,
1380
- L: 176,
1381
- S: this,
1382
- C: (f, a) => f(...a)
1383
- });
1384
- }
1385
- span.end();
1386
- }
1387
- }
1388
- async _processMessage(ctx, msg) {
1389
- (0, import_log7.log)("processing", {
1390
- key: msg.feedKey,
1391
- seq: msg.seq
1392
- }, {
1393
- F: __dxlog_file7,
1394
- L: 186,
1395
- S: this,
1396
- C: (f, a) => f(...a)
1397
- });
1398
- if (msg.data.payload.credential) {
1399
- const timer = import_util4.tracer.mark("dxos.echo.pipeline.control");
1400
- const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, {
1401
- sourceFeed: import_keys4.PublicKey.from(msg.feedKey)
1402
- });
1403
- timer.end();
1404
- if (!result) {
1405
- import_log7.log.warn("processing failed", {
1406
- msg
1407
- }, {
1408
- F: __dxlog_file7,
1409
- L: 195,
1410
- S: this,
1411
- C: (f, a) => f(...a)
1412
- });
1413
- } else {
1414
- await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
1415
- }
1416
- this._snapshotTask.schedule();
1417
- }
1418
- }
1419
- async _noteTargetStateIfNeeded(timeframe) {
1420
- if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL) {
1421
- this._lastTimeframeSaveTime = Date.now();
1422
- await this._saveTargetTimeframe(timeframe);
1423
- }
1424
- }
1425
- async stop() {
1426
- (0, import_log7.log)("stopping...", void 0, {
1427
- F: __dxlog_file7,
1428
- L: 215,
1429
- S: this,
1430
- C: (f, a) => f(...a)
1431
- });
1432
- await this._ctx.dispose();
1433
- await this._pipeline.stop();
1434
- await this._saveTargetTimeframe(this._pipeline.state.timeframe);
1435
- (0, import_log7.log)("stopped", void 0, {
1436
- F: __dxlog_file7,
1437
- L: 219,
1438
- S: this,
1439
- C: (f, a) => f(...a)
1440
- });
1441
- }
1442
- async _saveTargetTimeframe(timeframe) {
1443
- try {
1444
- const newTimeframe = import_timeframe3.Timeframe.merge(this._targetTimeframe ?? new import_timeframe3.Timeframe(), timeframe);
1445
- await this._metadata.setSpaceControlLatestTimeframe(this._spaceKey, newTimeframe);
1446
- this._targetTimeframe = newTimeframe;
1447
- } catch (err) {
1448
- (0, import_log7.log)(err, void 0, {
1449
- F: __dxlog_file7,
1450
- L: 228,
1451
- S: this,
1452
- C: (f, a) => f(...a)
1453
- });
1454
- }
1455
- }
1456
- };
1457
- _ts_decorate3([
1458
- import_tracing2.trace.metricsCounter()
1459
- ], ControlPipeline.prototype, "_usage", void 0);
1460
- _ts_decorate3([
1461
- import_tracing2.trace.metricsCounter()
1462
- ], ControlPipeline.prototype, "_mutations", void 0);
1463
- _ts_decorate3([
1464
- import_tracing2.trace.span({
1465
- showInBrowserTimeline: true
1466
- })
1467
- ], ControlPipeline.prototype, "start", null);
1468
- _ts_decorate3([
1469
- import_tracing2.trace.span()
1470
- ], ControlPipeline.prototype, "_consumePipeline", null);
1471
- _ts_decorate3([
1472
- import_tracing2.trace.span()
1473
- ], ControlPipeline.prototype, "_processMessage", null);
1474
- ControlPipeline = _ts_decorate3([
1475
- import_tracing2.trace.resource(),
1476
- (0, import_async7.trackLeaks)("start", "stop")
1477
- ], ControlPipeline);
1478
- function _ts_decorate4(decorators, target, key, desc) {
1479
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1480
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1481
- r = Reflect.decorate(decorators, target, key, desc);
1482
- else
1483
- for (var i = decorators.length - 1; i >= 0; i--)
1484
- if (d = decorators[i])
1485
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1486
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1487
- }
1488
- var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space.ts";
1489
- var Space = class extends import_context6.Resource {
1490
- constructor(params) {
1491
- super();
1492
- this.onCredentialProcessed = new import_util3.Callback();
1493
- this.stateUpdate = new import_async6.Event();
1494
- (0, import_invariant6.invariant)(params.spaceKey && params.feedProvider, void 0, {
1495
- F: __dxlog_file8,
1496
- L: 76,
1497
- S: this,
1498
- A: [
1499
- "params.spaceKey && params.feedProvider",
1500
- ""
1501
- ]
1502
- });
1503
- this._id = params.id;
1504
- this._key = params.spaceKey;
1505
- this._genesisFeedKey = params.genesisFeed.key;
1506
- this._feedProvider = params.feedProvider;
1507
- this._snapshotManager = params.snapshotManager;
1508
- this._controlPipeline = new ControlPipeline({
1509
- spaceKey: params.spaceKey,
1510
- genesisFeed: params.genesisFeed,
1511
- feedProvider: params.feedProvider,
1512
- metadataStore: params.metadataStore
1513
- });
1514
- this._controlPipeline.onFeedAdmitted.set(async (info) => {
1515
- const sparse = info.assertion.designation === import_credentials.AdmittedFeed.Designation.DATA;
1516
- if (!info.key.equals(params.genesisFeed.key)) {
1517
- (0, import_async6.scheduleMicroTask)(this._ctx, async () => {
1518
- await this.protocol.addFeed(await params.feedProvider(info.key, {
1519
- sparse
1520
- }));
1521
- });
1522
- }
1523
- });
1524
- this._controlPipeline.onCredentialProcessed.set(async (credential) => {
1525
- await this.onCredentialProcessed.callIfSet(credential);
1526
- (0, import_log6.log)("onCredentialProcessed", {
1527
- credential
1528
- }, {
1529
- F: __dxlog_file8,
1530
- L: 104,
1531
- S: this,
1532
- C: (f, a) => f(...a)
1533
- });
1534
- this.stateUpdate.emit();
1535
- });
1536
- this._controlPipeline.onDelegatedInvitation.set(async (invitation) => {
1537
- (0, import_log6.log)("onDelegatedInvitation", {
1538
- invitation
1539
- }, {
1540
- F: __dxlog_file8,
1541
- L: 108,
1542
- S: this,
1543
- C: (f, a) => f(...a)
1544
- });
1545
- await params.onDelegatedInvitationStatusChange(invitation, true);
1546
- });
1547
- this._controlPipeline.onDelegatedInvitationRemoved.set(async (invitation) => {
1548
- (0, import_log6.log)("onDelegatedInvitationRemoved", {
1549
- invitation
1550
- }, {
1551
- F: __dxlog_file8,
1552
- L: 112,
1553
- S: this,
1554
- C: (f, a) => f(...a)
1555
- });
1556
- await params.onDelegatedInvitationStatusChange(invitation, false);
1557
- });
1558
- this._controlPipeline.onMemberRoleChanged.set(async (changedMembers) => {
1559
- (0, import_log6.log)("onMemberRoleChanged", () => ({
1560
- changedMembers: changedMembers.map((m) => [
1561
- m.key,
1562
- m.role
1563
- ])
1564
- }), {
1565
- F: __dxlog_file8,
1566
- L: 116,
1567
- S: this,
1568
- C: (f, a) => f(...a)
1569
- });
1570
- await params.onMemberRolesChanged(changedMembers);
1571
- });
1572
- this.protocol = params.protocol;
1573
- }
1574
- get id() {
1575
- return this._id;
1576
- }
1577
- get key() {
1578
- return this._key;
1579
- }
1580
- get isOpen() {
1581
- return this._lifecycleState === import_context6.LifecycleState.OPEN;
1582
- }
1583
- get genesisFeedKey() {
1584
- return this._genesisFeedKey;
1585
- }
1586
- get controlFeedKey() {
1587
- return this._controlFeed?.key;
1588
- }
1589
- get dataFeedKey() {
1590
- return this._dataFeed?.key;
1591
- }
1592
- get spaceState() {
1593
- return this._controlPipeline.spaceState;
1594
- }
1595
- /**
1596
- * @test-only
1597
- */
1598
- get controlPipeline() {
1599
- return this._controlPipeline.pipeline;
1600
- }
1601
- get snapshotManager() {
1602
- return this._snapshotManager;
1603
- }
1604
- async setControlFeed(feed) {
1605
- (0, import_invariant6.invariant)(!this._controlFeed, "Control feed already set.", {
1606
- F: __dxlog_file8,
1607
- L: 168,
1608
- S: this,
1609
- A: [
1610
- "!this._controlFeed",
1611
- "'Control feed already set.'"
1612
- ]
1613
- });
1614
- this._controlFeed = feed;
1615
- await this._controlPipeline.setWriteFeed(feed);
1616
- return this;
1617
- }
1618
- async setDataFeed(feed) {
1619
- (0, import_invariant6.invariant)(!this._dataFeed, "Data feed already set.", {
1620
- F: __dxlog_file8,
1621
- L: 175,
1622
- S: this,
1623
- A: [
1624
- "!this._dataFeed",
1625
- "'Data feed already set.'"
1626
- ]
1627
- });
1628
- this._dataFeed = feed;
1629
- return this;
1630
- }
1631
- /**
1632
- * Use for diagnostics.
1633
- */
1634
- getControlFeeds() {
1635
- return Array.from(this._controlPipeline.spaceState.feeds.values());
1636
- }
1637
- async _open(ctx) {
1638
- (0, import_log6.log)("opening...", void 0, {
1639
- F: __dxlog_file8,
1640
- L: 189,
1641
- S: this,
1642
- C: (f, a) => f(...a)
1643
- });
1644
- await this._controlPipeline.start();
1645
- await this.protocol.start();
1646
- await this.protocol.addFeed(await this._feedProvider(this._genesisFeedKey));
1647
- (0, import_log6.log)("opened", void 0, {
1648
- F: __dxlog_file8,
1649
- L: 196,
1650
- S: this,
1651
- C: (f, a) => f(...a)
1652
- });
1653
- }
1654
- async _close() {
1655
- (0, import_log6.log)("closing...", {
1656
- key: this._key
1657
- }, {
1658
- F: __dxlog_file8,
1659
- L: 201,
1660
- S: this,
1661
- C: (f, a) => f(...a)
1662
- });
1663
- await this.protocol.stop();
1664
- await this._controlPipeline.stop();
1665
- (0, import_log6.log)("closed", void 0, {
1666
- F: __dxlog_file8,
1667
- L: 207,
1668
- S: this,
1669
- C: (f, a) => f(...a)
1670
- });
1671
- }
1672
- };
1673
- _ts_decorate4([
1674
- import_tracing.trace.info()
1675
- ], Space.prototype, "protocol", void 0);
1676
- _ts_decorate4([
1677
- import_tracing.trace.info()
1678
- ], Space.prototype, "_controlPipeline", void 0);
1679
- _ts_decorate4([
1680
- import_log6.logInfo,
1681
- import_tracing.trace.info()
1682
- ], Space.prototype, "id", null);
1683
- _ts_decorate4([
1684
- import_log6.logInfo,
1685
- import_tracing.trace.info()
1686
- ], Space.prototype, "key", null);
1687
- _ts_decorate4([
1688
- import_tracing.trace.span()
1689
- ], Space.prototype, "_open", null);
1690
- _ts_decorate4([
1691
- import_async6.synchronized
1692
- ], Space.prototype, "_close", null);
1693
- Space = _ts_decorate4([
1694
- (0, import_async6.trackLeaks)("open", "close"),
1695
- import_tracing.trace.resource()
1696
- ], Space);
1697
- var SPACE_IDS_CACHE = new import_util3.ComplexMap(import_keys3.PublicKey.hash);
1698
- var createIdFromSpaceKey = async (spaceKey) => {
1699
- const cachedValue = SPACE_IDS_CACHE.get(spaceKey);
1700
- if (cachedValue !== void 0) {
1701
- return cachedValue;
1702
- }
1703
- const digest = await import_crypto3.subtleCrypto.digest("SHA-256", spaceKey.asUint8Array());
1704
- const bytes = new Uint8Array(digest).slice(0, import_keys3.SpaceId.byteLength);
1705
- const spaceId = import_keys3.SpaceId.encode(bytes);
1706
- SPACE_IDS_CACHE.set(spaceKey, spaceId);
1707
- return spaceId;
1708
- };
1709
- var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/admission-discovery-extension.ts";
1710
- var CredentialRetrieverExtension = class extends import_teleport2.RpcExtension {
1711
- constructor(_request, _onResult) {
1712
- super({
1713
- requested: {
1714
- AdmissionDiscoveryService: import_protocols5.schema.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
1715
- }
1716
- });
1717
- this._request = _request;
1718
- this._onResult = _onResult;
1719
- this._ctx = new import_context8.Context(void 0, {
1720
- F: __dxlog_file9,
1721
- L: 25
1722
- });
1723
- }
1724
- async getHandlers() {
1725
- return {};
1726
- }
1727
- async onOpen(context) {
1728
- await super.onOpen(context);
1729
- (0, import_async8.scheduleTask)(this._ctx, async () => {
1730
- try {
1731
- const result = await this.rpc.AdmissionDiscoveryService.getAdmissionCredential(this._request);
1732
- this._onResult.wake(result.admissionCredential);
1733
- } catch (err) {
1734
- context.close(err);
1735
- }
1736
- });
1737
- }
1738
- async onClose() {
1739
- await this._ctx.dispose();
1740
- }
1741
- async onAbort() {
1742
- await this._ctx.dispose();
1743
- }
1744
- };
1745
- var CredentialServerExtension = class extends import_teleport2.RpcExtension {
1746
- constructor(_space) {
1747
- super({
1748
- exposed: {
1749
- AdmissionDiscoveryService: import_protocols5.schema.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
1750
- }
1751
- });
1752
- this._space = _space;
1753
- }
1754
- async getHandlers() {
1755
- return {
1756
- AdmissionDiscoveryService: {
1757
- getAdmissionCredential: async (request) => {
1758
- const memberInfo = this._space.spaceState.members.get(request.memberKey);
1759
- if (!memberInfo?.credential) {
1760
- throw new import_protocols5.ProtocolError("Space member not found.", request);
1761
- }
1762
- return {
1763
- admissionCredential: memberInfo.credential
1764
- };
1765
- }
1766
- }
1767
- };
1768
- }
1769
- };
1770
- function _ts_decorate5(decorators, target, key, desc) {
1771
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1772
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1773
- r = Reflect.decorate(decorators, target, key, desc);
1774
- else
1775
- for (var i = decorators.length - 1; i >= 0; i--)
1776
- if (d = decorators[i])
1777
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1778
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1779
- }
1780
- var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space-protocol.ts";
1781
- var MOCK_AUTH_PROVIDER = async (nonce) => Buffer.from("mock");
1782
- var MOCK_AUTH_VERIFIER = async (nonce, credential) => true;
1783
- var SpaceProtocol = class {
1784
- constructor({ topic, swarmIdentity, networkManager, onSessionAuth, onAuthFailure, blobStore, disableP2pReplication }) {
1785
- this._feeds = /* @__PURE__ */ new Set();
1786
- this._sessions = new import_util5.ComplexMap(import_keys5.PublicKey.hash);
1787
- this._topology = new import_network_manager.MMSTTopology({
1788
- originateConnections: 4,
1789
- maxPeers: 10,
1790
- sampleSize: 20
1791
- });
1792
- this.feedAdded = new import_util5.CallbackCollection();
1793
- this._spaceKey = topic;
1794
- this._networkManager = networkManager;
1795
- this._swarmIdentity = swarmIdentity;
1796
- this._onSessionAuth = onSessionAuth;
1797
- this._onAuthFailure = onAuthFailure;
1798
- this.blobSync = new import_teleport_extension_object_sync.BlobSync({
1799
- blobStore
1800
- });
1801
- this._topic = import_crypto4.subtleCrypto.digest("SHA-256", topic.asBuffer()).then(import_crypto4.discoveryKey).then(import_keys5.PublicKey.from);
1802
- this._disableP2pReplication = disableP2pReplication ?? false;
1803
- }
1804
- get sessions() {
1805
- return this._sessions;
1806
- }
1807
- get feeds() {
1808
- return this._feeds;
1809
- }
1810
- get _ownPeerKey() {
1811
- return this._swarmIdentity.peerKey;
1812
- }
1813
- // TODO(burdon): Create abstraction for Space (e.g., add keys and have provider).
1814
- async addFeed(feed) {
1815
- (0, import_log8.log)("addFeed", {
1816
- key: feed.key
1817
- }, {
1818
- F: __dxlog_file10,
1819
- L: 127,
1820
- S: this,
1821
- C: (f, a) => f(...a)
1822
- });
1823
- this._feeds.add(feed);
1824
- for (const session of this._sessions.values()) {
1825
- session.replicator.addFeed(feed);
1826
- }
1827
- await this.feedAdded.callSerial(feed);
1828
- }
1829
- // TODO(burdon): Rename open? Common open/close interfaces for all services?
1830
- async start() {
1831
- if (this._connection) {
1832
- return;
1833
- }
1834
- const credentials = await this._swarmIdentity.credentialProvider(Buffer.from(""));
1835
- await this.blobSync.open();
1836
- (0, import_log8.log)("starting...", void 0, {
1837
- F: __dxlog_file10,
1838
- L: 148,
1839
- S: this,
1840
- C: (f, a) => f(...a)
1841
- });
1842
- const topic = await this._topic;
1843
- this._connection = await this._networkManager.joinSwarm({
1844
- protocolProvider: this._createProtocolProvider(credentials),
1845
- peerId: this._swarmIdentity.peerKey,
1846
- topic,
1847
- topology: this._topology,
1848
- label: `swarm ${topic.truncate()} for space ${this._spaceKey.truncate()}`
1849
- });
1850
- (0, import_log8.log)("started", void 0, {
1851
- F: __dxlog_file10,
1852
- L: 158,
1853
- S: this,
1854
- C: (f, a) => f(...a)
1855
- });
1856
- }
1857
- updateTopology() {
1858
- this._topology.forceUpdate();
1859
- }
1860
- async stop() {
1861
- await this.blobSync.close();
1862
- if (this._connection) {
1863
- (0, import_log8.log)("stopping...", void 0, {
1864
- F: __dxlog_file10,
1865
- L: 169,
1866
- S: this,
1867
- C: (f, a) => f(...a)
1868
- });
1869
- await this._connection.close();
1870
- (0, import_log8.log)("stopped", void 0, {
1871
- F: __dxlog_file10,
1872
- L: 171,
1873
- S: this,
1874
- C: (f, a) => f(...a)
1875
- });
1876
- }
1877
- }
1878
- _createProtocolProvider(credentials) {
1879
- return (wireParams) => {
1880
- const session = new SpaceProtocolSession({
1881
- wireParams,
1882
- swarmIdentity: this._swarmIdentity,
1883
- onSessionAuth: this._onSessionAuth,
1884
- onAuthFailure: this._onAuthFailure,
1885
- blobSync: this.blobSync,
1886
- disableP2pReplication: this._disableP2pReplication
1887
- });
1888
- this._sessions.set(wireParams.remotePeerId, session);
1889
- for (const feed of this._feeds) {
1890
- session.replicator.addFeed(feed);
1891
- }
1892
- return session;
1893
- };
1894
- }
1895
- };
1896
- _ts_decorate5([
1897
- import_log8.logInfo,
1898
- import_tracing3.trace.info()
1899
- ], SpaceProtocol.prototype, "_topic", void 0);
1900
- _ts_decorate5([
1901
- import_tracing3.trace.info()
1902
- ], SpaceProtocol.prototype, "_spaceKey", void 0);
1903
- _ts_decorate5([
1904
- import_log8.logInfo
1905
- ], SpaceProtocol.prototype, "_ownPeerKey", null);
1906
- SpaceProtocol = _ts_decorate5([
1907
- import_tracing3.trace.resource()
1908
- ], SpaceProtocol);
1909
- var AuthStatus;
1910
- (function(AuthStatus2) {
1911
- AuthStatus2["INITIAL"] = "INITIAL";
1912
- AuthStatus2["SUCCESS"] = "SUCCESS";
1913
- AuthStatus2["FAILURE"] = "FAILURE";
1914
- })(AuthStatus || (AuthStatus = {}));
1915
- var SpaceProtocolSession = class {
1916
- // TODO(dmaretskyi): Allow to pass in extra extensions.
1917
- constructor({ wireParams, swarmIdentity, onSessionAuth, onAuthFailure, blobSync, disableP2pReplication }) {
1918
- this.replicator = new import_teleport_extension_replicator.ReplicatorExtension().setOptions({
1919
- upload: true
1920
- });
1921
- this._authStatus = "INITIAL";
1922
- this._wireParams = wireParams;
1923
- this._swarmIdentity = swarmIdentity;
1924
- this._onSessionAuth = onSessionAuth;
1925
- this._onAuthFailure = onAuthFailure;
1926
- this._blobSync = blobSync;
1927
- this._teleport = new import_teleport3.Teleport(wireParams);
1928
- this._disableP2pReplication = disableP2pReplication ?? false;
1929
- }
1930
- get authStatus() {
1931
- return this._authStatus;
1932
- }
1933
- get stats() {
1934
- return this._teleport.stats;
1935
- }
1936
- get stream() {
1937
- return this._teleport.stream;
1938
- }
1939
- async open(sessionId) {
1940
- await this._teleport.open(sessionId);
1941
- this._teleport.addExtension("dxos.mesh.teleport.auth", new AuthExtension({
1942
- provider: this._swarmIdentity.credentialProvider,
1943
- verifier: this._swarmIdentity.credentialAuthenticator,
1944
- onAuthSuccess: () => {
1945
- (0, import_log8.log)("Peer authenticated", void 0, {
1946
- F: __dxlog_file10,
1947
- L: 282,
1948
- S: this,
1949
- C: (f, a) => f(...a)
1950
- });
1951
- this._authStatus = "SUCCESS";
1952
- this._onSessionAuth?.(this._teleport);
1953
- },
1954
- onAuthFailure: () => {
1955
- this._authStatus = "FAILURE";
1956
- this._onAuthFailure?.(this._teleport);
1957
- }
1958
- }));
1959
- if (!this._disableP2pReplication) {
1960
- this._teleport.addExtension("dxos.mesh.teleport.replicator", this.replicator);
1961
- }
1962
- this._teleport.addExtension("dxos.mesh.teleport.blobsync", this._blobSync.createExtension());
1963
- }
1964
- async close() {
1965
- (0, import_log8.log)("close", void 0, {
1966
- F: __dxlog_file10,
1967
- L: 301,
1968
- S: this,
1969
- C: (f, a) => f(...a)
1970
- });
1971
- await this._teleport.close();
1972
- }
1973
- async abort() {
1974
- await this._teleport.abort();
1975
- }
1976
- };
1977
- _ts_decorate5([
1978
- import_log8.logInfo
1979
- ], SpaceProtocolSession.prototype, "_wireParams", void 0);
1980
- _ts_decorate5([
1981
- import_log8.logInfo
1982
- ], SpaceProtocolSession.prototype, "authStatus", null);
1983
- var isCollectionQueryMessage = (message) => message.type === import_protocols8.MESSAGE_TYPE_COLLECTION_QUERY;
1984
- var isCollectionStateMessage = (message) => message.type === import_protocols8.MESSAGE_TYPE_COLLECTION_STATE;
1985
- function _ts_decorate6(decorators, target, key, desc) {
1986
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1987
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1988
- r = Reflect.decorate(decorators, target, key, desc);
1989
- else
1990
- for (var i = decorators.length - 1; i >= 0; i--)
1991
- if (d = decorators[i])
1992
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1993
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1994
- }
1995
- var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
1996
- var EchoNetworkAdapter = class extends import_automerge_repo2.NetworkAdapter {
1997
- constructor(_params) {
1998
- super();
1999
- this._params = _params;
2000
- this._replicators = /* @__PURE__ */ new Set();
2001
- this._connections = /* @__PURE__ */ new Map();
2002
- this._lifecycleState = import_context10.LifecycleState.CLOSED;
2003
- this._connected = new import_async11.Trigger();
2004
- }
2005
- connect(peerId, peerMetadata) {
2006
- this.peerId = peerId;
2007
- this.peerMetadata = peerMetadata;
2008
- this._connected.wake();
2009
- }
2010
- send(message) {
2011
- this._send(message);
2012
- }
2013
- disconnect() {
2014
- }
2015
- async open() {
2016
- if (this._lifecycleState === import_context10.LifecycleState.OPEN) {
2017
- return;
2018
- }
2019
- this._lifecycleState = import_context10.LifecycleState.OPEN;
2020
- (0, import_log12.log)("emit ready", void 0, {
2021
- F: __dxlog_file11,
2022
- L: 81,
2023
- S: this,
2024
- C: (f, a) => f(...a)
2025
- });
2026
- this.emit("ready", {
2027
- network: this
2028
- });
2029
- }
2030
- async close() {
2031
- if (this._lifecycleState === import_context10.LifecycleState.CLOSED) {
2032
- return this;
2033
- }
2034
- for (const replicator of this._replicators) {
2035
- await replicator.disconnect();
2036
- }
2037
- this._replicators.clear();
2038
- this._lifecycleState = import_context10.LifecycleState.CLOSED;
2039
- }
2040
- async whenConnected() {
2041
- await this._connected.wait({
2042
- timeout: 1e4
2043
- });
2044
- }
2045
- async addReplicator(replicator) {
2046
- (0, import_invariant9.invariant)(this._lifecycleState === import_context10.LifecycleState.OPEN, void 0, {
2047
- F: __dxlog_file11,
2048
- L: 107,
2049
- S: this,
2050
- A: [
2051
- "this._lifecycleState === LifecycleState.OPEN",
2052
- ""
2053
- ]
2054
- });
2055
- (0, import_invariant9.invariant)(this.peerId, void 0, {
2056
- F: __dxlog_file11,
2057
- L: 108,
2058
- S: this,
2059
- A: [
2060
- "this.peerId",
2061
- ""
2062
- ]
2063
- });
2064
- (0, import_invariant9.invariant)(!this._replicators.has(replicator), void 0, {
2065
- F: __dxlog_file11,
2066
- L: 109,
2067
- S: this,
2068
- A: [
2069
- "!this._replicators.has(replicator)",
2070
- ""
2071
- ]
2072
- });
2073
- this._replicators.add(replicator);
2074
- await replicator.connect({
2075
- peerId: this.peerId,
2076
- onConnectionOpen: this._onConnectionOpen.bind(this),
2077
- onConnectionClosed: this._onConnectionClosed.bind(this),
2078
- onConnectionAuthScopeChanged: this._onConnectionAuthScopeChanged.bind(this),
2079
- isDocumentInRemoteCollection: this._params.isDocumentInRemoteCollection,
2080
- getContainingSpaceForDocument: this._params.getContainingSpaceForDocument,
2081
- getContainingSpaceIdForDocument: async (documentId) => {
2082
- const key = await this._params.getContainingSpaceForDocument(documentId);
2083
- return key ? createIdFromSpaceKey(key) : null;
2084
- }
2085
- });
2086
- }
2087
- async removeReplicator(replicator) {
2088
- (0, import_invariant9.invariant)(this._lifecycleState === import_context10.LifecycleState.OPEN, void 0, {
2089
- F: __dxlog_file11,
2090
- L: 128,
2091
- S: this,
2092
- A: [
2093
- "this._lifecycleState === LifecycleState.OPEN",
2094
- ""
2095
- ]
2096
- });
2097
- (0, import_invariant9.invariant)(this._replicators.has(replicator), void 0, {
2098
- F: __dxlog_file11,
2099
- L: 129,
2100
- S: this,
2101
- A: [
2102
- "this._replicators.has(replicator)",
2103
- ""
2104
- ]
2105
- });
2106
- await replicator.disconnect();
2107
- this._replicators.delete(replicator);
2108
- }
2109
- async shouldAdvertise(peerId, params) {
2110
- const connection = this._connections.get(peerId);
2111
- if (!connection) {
2112
- return false;
2113
- }
2114
- return connection.connection.shouldAdvertise(params);
2115
- }
2116
- shouldSyncCollection(peerId, params) {
2117
- const connection = this._connections.get(peerId);
2118
- if (!connection) {
2119
- return false;
2120
- }
2121
- return connection.connection.shouldSyncCollection(params);
2122
- }
2123
- queryCollectionState(collectionId, targetId) {
2124
- const message = {
2125
- type: "collection-query",
2126
- senderId: this.peerId,
2127
- targetId,
2128
- collectionId
2129
- };
2130
- this._send(message);
2131
- }
2132
- sendCollectionState(collectionId, targetId, state) {
2133
- const message = {
2134
- type: "collection-state",
2135
- senderId: this.peerId,
2136
- targetId,
2137
- collectionId,
2138
- state
2139
- };
2140
- this._send(message);
2141
- }
2142
- _send(message) {
2143
- const connectionEntry = this._connections.get(message.targetId);
2144
- if (!connectionEntry) {
2145
- throw new Error("Connection not found.");
2146
- }
2147
- const writeStart = Date.now();
2148
- connectionEntry.writer.write(message).then(() => {
2149
- const durationMs = Date.now() - writeStart;
2150
- this._params.monitor?.recordMessageSent(message, durationMs);
2151
- }).catch((err) => {
2152
- if (connectionEntry.isOpen) {
2153
- import_log12.log.catch(err, void 0, {
2154
- F: __dxlog_file11,
2155
- L: 189,
2156
- S: this,
2157
- C: (f, a) => f(...a)
2158
- });
2159
- }
2160
- this._params.monitor?.recordMessageSendingFailed(message);
2161
- });
2162
- }
2163
- // TODO(dmaretskyi): Remove.
2164
- getPeersInterestedInCollection(collectionId) {
2165
- return Array.from(this._connections.values()).map((connection) => {
2166
- return connection.connection.shouldSyncCollection({
2167
- collectionId
2168
- }) ? connection.connection.peerId : null;
2169
- }).filter(import_util7.nonNullable);
2170
- }
2171
- _onConnectionOpen(connection) {
2172
- (0, import_log12.log)("Connection opened", {
2173
- peerId: connection.peerId
2174
- }, {
2175
- F: __dxlog_file11,
2176
- L: 207,
2177
- S: this,
2178
- C: (f, a) => f(...a)
2179
- });
2180
- (0, import_invariant9.invariant)(!this._connections.has(connection.peerId), void 0, {
2181
- F: __dxlog_file11,
2182
- L: 208,
2183
- S: this,
2184
- A: [
2185
- "!this._connections.has(connection.peerId as PeerId)",
2186
- ""
2187
- ]
2188
- });
2189
- const reader = connection.readable.getReader();
2190
- const writer = connection.writable.getWriter();
2191
- const connectionEntry = {
2192
- connection,
2193
- reader,
2194
- writer,
2195
- isOpen: true
2196
- };
2197
- this._connections.set(connection.peerId, connectionEntry);
2198
- queueMicrotask(async () => {
2199
- try {
2200
- while (true) {
2201
- const { done, value } = await reader.read();
2202
- if (done) {
2203
- break;
2204
- }
2205
- this._onMessage(value);
2206
- }
2207
- } catch (err) {
2208
- if (connectionEntry.isOpen) {
2209
- import_log12.log.catch(err, void 0, {
2210
- F: __dxlog_file11,
2211
- L: 227,
2212
- S: this,
2213
- C: (f, a) => f(...a)
2214
- });
2215
- }
2216
- }
2217
- });
2218
- (0, import_log12.log)("emit peer-candidate", {
2219
- peerId: connection.peerId
2220
- }, {
2221
- F: __dxlog_file11,
2222
- L: 232,
2223
- S: this,
2224
- C: (f, a) => f(...a)
2225
- });
2226
- this._emitPeerCandidate(connection);
2227
- this._params.monitor?.recordPeerConnected(connection.peerId);
2228
- }
2229
- _onMessage(message) {
2230
- if (isCollectionQueryMessage(message)) {
2231
- this._params.onCollectionStateQueried(message.collectionId, message.senderId);
2232
- } else if (isCollectionStateMessage(message)) {
2233
- this._params.onCollectionStateReceived(message.collectionId, message.senderId, message.state);
2234
- } else {
2235
- this.emit("message", message);
2236
- }
2237
- this._params.monitor?.recordMessageReceived(message);
2238
- }
2239
- /**
2240
- * Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.
2241
- * TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
2242
- */
2243
- _onConnectionAuthScopeChanged(connection) {
2244
- (0, import_log12.log)("Connection auth scope changed", {
2245
- peerId: connection.peerId
2246
- }, {
2247
- F: __dxlog_file11,
2248
- L: 253,
2249
- S: this,
2250
- C: (f, a) => f(...a)
2251
- });
2252
- const entry = this._connections.get(connection.peerId);
2253
- (0, import_invariant9.invariant)(entry, void 0, {
2254
- F: __dxlog_file11,
2255
- L: 255,
2256
- S: this,
2257
- A: [
2258
- "entry",
2259
- ""
2260
- ]
2261
- });
2262
- this.emit("peer-disconnected", {
2263
- peerId: connection.peerId
2264
- });
2265
- this._emitPeerCandidate(connection);
2266
- }
2267
- _onConnectionClosed(connection) {
2268
- (0, import_log12.log)("Connection closed", {
2269
- peerId: connection.peerId
2270
- }, {
2271
- F: __dxlog_file11,
2272
- L: 261,
2273
- S: this,
2274
- C: (f, a) => f(...a)
2275
- });
2276
- const entry = this._connections.get(connection.peerId);
2277
- (0, import_invariant9.invariant)(entry, void 0, {
2278
- F: __dxlog_file11,
2279
- L: 263,
2280
- S: this,
2281
- A: [
2282
- "entry",
2283
- ""
2284
- ]
2285
- });
2286
- entry.isOpen = false;
2287
- this.emit("peer-disconnected", {
2288
- peerId: connection.peerId
2289
- });
2290
- this._params.monitor?.recordPeerDisconnected(connection.peerId);
2291
- void entry.reader.cancel().catch((err) => import_log12.log.catch(err, void 0, {
2292
- F: __dxlog_file11,
2293
- L: 269,
2294
- S: this,
2295
- C: (f, a) => f(...a)
2296
- }));
2297
- void entry.writer.abort().catch((err) => import_log12.log.catch(err, void 0, {
2298
- F: __dxlog_file11,
2299
- L: 270,
2300
- S: this,
2301
- C: (f, a) => f(...a)
2302
- }));
2303
- this._connections.delete(connection.peerId);
2304
- }
2305
- _emitPeerCandidate(connection) {
2306
- this.emit("peer-candidate", {
2307
- peerId: connection.peerId,
2308
- peerMetadata: createEchoPeerMetadata()
2309
- });
2310
- }
2311
- };
2312
- _ts_decorate6([
2313
- import_async11.synchronized
2314
- ], EchoNetworkAdapter.prototype, "open", null);
2315
- _ts_decorate6([
2316
- import_async11.synchronized
2317
- ], EchoNetworkAdapter.prototype, "close", null);
2318
- _ts_decorate6([
2319
- import_async11.synchronized
2320
- ], EchoNetworkAdapter.prototype, "addReplicator", null);
2321
- _ts_decorate6([
2322
- import_async11.synchronized
2323
- ], EchoNetworkAdapter.prototype, "removeReplicator", null);
2324
- var createEchoPeerMetadata = () => ({
2325
- // TODO(dmaretskyi): Refactor this.
2326
- dxos_peerSource: "EchoNetworkAdapter"
2327
- });
2328
- var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetworkAdapter";
2329
- var HeadsStore = class {
2330
- constructor({ db }) {
2331
- this._db = db;
2332
- }
2333
- setHeads(documentId, heads, batch) {
2334
- batch.put(documentId, heads, {
2335
- sublevel: this._db,
2336
- keyEncoding: "utf8",
2337
- valueEncoding: import_indexing.headsEncoding
2338
- });
2339
- }
2340
- // TODO(dmaretskyi): Make batched.
2341
- async getHeads(documentIds) {
2342
- return this._db.getMany(documentIds, {
2343
- keyEncoding: "utf8",
2344
- valueEncoding: import_indexing.headsEncoding
2345
- });
2346
- }
2347
- };
2348
- var LevelDBStorageAdapter = class extends import_context11.Resource {
2349
- constructor(_params) {
2350
- super();
2351
- this._params = _params;
2352
- }
2353
- async load(keyArray) {
2354
- try {
2355
- if (this._lifecycleState !== import_context11.LifecycleState.OPEN) {
2356
- return void 0;
2357
- }
2358
- const startMs = Date.now();
2359
- const chunk = await this._params.db.get(keyArray, {
2360
- ...encodingOptions
2361
- });
2362
- this._params.monitor?.recordBytesLoaded(chunk.byteLength);
2363
- this._params.monitor?.recordLoadDuration(Date.now() - startMs);
2364
- return chunk;
2365
- } catch (err) {
2366
- if (isLevelDbNotFoundError(err)) {
2367
- return void 0;
2368
- }
2369
- throw err;
2370
- }
2371
- }
2372
- async save(keyArray, binary) {
2373
- if (this._lifecycleState !== import_context11.LifecycleState.OPEN) {
2374
- return void 0;
2375
- }
2376
- const startMs = Date.now();
2377
- const batch = this._params.db.batch();
2378
- await this._params.callbacks?.beforeSave?.({
2379
- path: keyArray,
2380
- batch
2381
- });
2382
- batch.put(keyArray, Buffer.from(binary), {
2383
- ...encodingOptions
2384
- });
2385
- await batch.write();
2386
- this._params.monitor?.recordBytesStored(binary.byteLength);
2387
- await this._params.callbacks?.afterSave?.(keyArray);
2388
- this._params.monitor?.recordStoreDuration(Date.now() - startMs);
2389
- }
2390
- async remove(keyArray) {
2391
- if (this._lifecycleState !== import_context11.LifecycleState.OPEN) {
2392
- return void 0;
2393
- }
2394
- await this._params.db.del(keyArray, {
2395
- ...encodingOptions
2396
- });
2397
- }
2398
- async loadRange(keyPrefix) {
2399
- if (this._lifecycleState !== import_context11.LifecycleState.OPEN) {
2400
- return [];
2401
- }
2402
- const startMs = Date.now();
2403
- const result = [];
2404
- for await (const [key, value] of this._params.db.iterator({
2405
- gte: keyPrefix,
2406
- lte: [
2407
- ...keyPrefix,
2408
- "\uFFFF"
2409
- ],
2410
- ...encodingOptions
2411
- })) {
2412
- result.push({
2413
- key,
2414
- data: value
2415
- });
2416
- this._params.monitor?.recordBytesLoaded(value.byteLength);
2417
- }
2418
- this._params.monitor?.recordLoadDuration(Date.now() - startMs);
2419
- return result;
2420
- }
2421
- async removeRange(keyPrefix) {
2422
- if (this._lifecycleState !== import_context11.LifecycleState.OPEN) {
2423
- return void 0;
2424
- }
2425
- const batch = this._params.db.batch();
2426
- for await (const [key] of this._params.db.iterator({
2427
- gte: keyPrefix,
2428
- lte: [
2429
- ...keyPrefix,
2430
- "\uFFFF"
2431
- ],
2432
- ...encodingOptions
2433
- })) {
2434
- batch.del(key, {
2435
- ...encodingOptions
2436
- });
2437
- }
2438
- await batch.write();
2439
- }
2440
- };
2441
- var keyEncoder = {
2442
- encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
2443
- decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%")),
2444
- format: "buffer"
2445
- };
2446
- var encodingOptions = {
2447
- keyEncoding: keyEncoder,
2448
- valueEncoding: "buffer"
2449
- };
2450
- var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
2451
- function _ts_decorate7(decorators, target, key, desc) {
2452
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2453
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2454
- r = Reflect.decorate(decorators, target, key, desc);
2455
- else
2456
- for (var i = decorators.length - 1; i >= 0; i--)
2457
- if (d = decorators[i])
2458
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2459
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2460
- }
2461
- var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
2462
- var AutomergeHost = class extends import_context9.Resource {
2463
- constructor({ db, indexMetadataStore, dataMonitor }) {
2464
- super();
2465
- this._collectionSynchronizer = new CollectionSynchronizer({
2466
- queryCollectionState: this._queryCollectionState.bind(this),
2467
- sendCollectionState: this._sendCollectionState.bind(this),
2468
- shouldSyncCollection: this._shouldSyncCollection.bind(this)
2469
- });
2470
- this._db = db;
2471
- this._storage = new LevelDBStorageAdapter({
2472
- db: db.sublevel("automerge"),
2473
- callbacks: {
2474
- beforeSave: async (params) => this._beforeSave(params),
2475
- afterSave: async (key) => this._afterSave(key)
2476
- },
2477
- monitor: dataMonitor
2478
- });
2479
- this._echoNetworkAdapter = new EchoNetworkAdapter({
2480
- getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
2481
- isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
2482
- onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
2483
- onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
2484
- monitor: dataMonitor
2485
- });
2486
- this._headsStore = new HeadsStore({
2487
- db: db.sublevel("heads")
2488
- });
2489
- this._indexMetadataStore = indexMetadataStore;
2490
- }
2491
- async _open() {
2492
- this._peerId = `host-${import_keys8.PublicKey.random().toHex()}`;
2493
- await this._storage.open?.();
2494
- this._repo = new import_automerge_repo.Repo({
2495
- peerId: this._peerId,
2496
- sharePolicy: this._sharePolicy.bind(this),
2497
- storage: this._storage,
2498
- network: [
2499
- // Upstream swarm.
2500
- this._echoNetworkAdapter
2501
- ]
2502
- });
2503
- import_async10.Event.wrap(this._echoNetworkAdapter, "peer-candidate").on(this._ctx, (e) => this._onPeerConnected(e.peerId));
2504
- import_async10.Event.wrap(this._echoNetworkAdapter, "peer-disconnected").on(this._ctx, (e) => this._onPeerDisconnected(e.peerId));
2505
- this._collectionSynchronizer.remoteStateUpdated.on(this._ctx, ({ collectionId, peerId }) => {
2506
- this._onRemoteCollectionStateUpdated(collectionId, peerId);
2507
- });
2508
- await this._echoNetworkAdapter.open();
2509
- await this._collectionSynchronizer.open();
2510
- await this._echoNetworkAdapter.open();
2511
- await this._echoNetworkAdapter.whenConnected();
2512
- }
2513
- async _close() {
2514
- await this._collectionSynchronizer.close();
2515
- await this._storage.close?.();
2516
- await this._echoNetworkAdapter.close();
2517
- await this._ctx.dispose();
2518
- }
2519
- /**
2520
- * @deprecated To be abstracted away.
2521
- */
2522
- get repo() {
2523
- return this._repo;
2524
- }
2525
- get peerId() {
2526
- return this._peerId;
2527
- }
2528
- get loadedDocsCount() {
2529
- return Object.keys(this._repo.handles).length;
2530
- }
2531
- async addReplicator(replicator) {
2532
- await this._echoNetworkAdapter.addReplicator(replicator);
2533
- }
2534
- async removeReplicator(replicator) {
2535
- await this._echoNetworkAdapter.removeReplicator(replicator);
2536
- }
2537
- /**
2538
- * Loads the document handle from the repo and waits for it to be ready.
2539
- */
2540
- async loadDoc(ctx, documentId, opts) {
2541
- let handle;
2542
- if (typeof documentId === "string") {
2543
- handle = this._repo.handles[documentId];
2544
- }
2545
- if (!handle) {
2546
- handle = this._repo.find(documentId);
2547
- }
2548
- if (!handle.isReady()) {
2549
- if (!opts?.timeout) {
2550
- await (0, import_context9.cancelWithContext)(ctx, handle.whenReady());
2551
- } else {
2552
- await (0, import_context9.cancelWithContext)(ctx, (0, import_async10.asyncTimeout)(handle.whenReady(), opts.timeout));
2553
- }
2554
- }
2555
- return handle;
2556
- }
2557
- /**
2558
- * Create new persisted document.
2559
- */
2560
- createDoc(initialValue, opts) {
2561
- if (opts?.preserveHistory) {
2562
- if (!(0, import_automerge3.isAutomerge)(initialValue)) {
2563
- throw new TypeError("Initial value must be an Automerge document");
2564
- }
2565
- return this._repo.import((0, import_automerge3.save)(initialValue));
2566
- } else {
2567
- return this._repo.create(initialValue);
2568
- }
2569
- }
2570
- async waitUntilHeadsReplicated(heads) {
2571
- const entries = heads.entries;
2572
- if (!entries?.length) {
2573
- return;
2574
- }
2575
- const documentIds = entries.map((entry) => entry.documentId);
2576
- const documentHeads = await this.getHeads(documentIds);
2577
- const headsToWait = entries.filter((entry, index) => {
2578
- const targetHeads = entry.heads;
2579
- if (!targetHeads || targetHeads.length === 0) {
2580
- return false;
2581
- }
2582
- const currentHeads = documentHeads[index];
2583
- return !(currentHeads !== null && (0, import_automerge3.equals)(currentHeads, targetHeads));
2584
- });
2585
- if (headsToWait.length > 0) {
2586
- await Promise.all(headsToWait.map(async (entry, index) => {
2587
- const handle = await this.loadDoc(import_context9.Context.default(void 0, {
2588
- F: __dxlog_file12,
2589
- L: 227
2590
- }), entry.documentId);
2591
- await waitForHeads(handle, entry.heads);
2592
- }));
2593
- }
2594
- await this._repo.flush(documentIds.filter((documentId) => !!this._repo.handles[documentId]));
2595
- }
2596
- async reIndexHeads(documentIds) {
2597
- for (const documentId of documentIds) {
2598
- import_log11.log.info("re-indexing heads for document", {
2599
- documentId
2600
- }, {
2601
- F: __dxlog_file12,
2602
- L: 239,
2603
- S: this,
2604
- C: (f, a) => f(...a)
2605
- });
2606
- const handle = this._repo.find(documentId);
2607
- await handle.whenReady([
2608
- "ready",
2609
- "requesting"
2610
- ]);
2611
- if (handle.inState([
2612
- "requesting"
2613
- ])) {
2614
- import_log11.log.warn("document is not available locally, skipping", {
2615
- documentId
2616
- }, {
2617
- F: __dxlog_file12,
2618
- L: 243,
2619
- S: this,
2620
- C: (f, a) => f(...a)
2621
- });
2622
- continue;
2623
- }
2624
- const doc = handle.docSync();
2625
- (0, import_invariant8.invariant)(doc, void 0, {
2626
- F: __dxlog_file12,
2627
- L: 248,
2628
- S: this,
2629
- A: [
2630
- "doc",
2631
- ""
2632
- ]
2633
- });
2634
- const heads = (0, import_automerge3.getHeads)(doc);
2635
- const batch = this._db.batch();
2636
- this._headsStore.setHeads(documentId, heads, batch);
2637
- await batch.write();
2638
- }
2639
- import_log11.log.info("done re-indexing heads", void 0, {
2640
- F: __dxlog_file12,
2641
- L: 255,
2642
- S: this,
2643
- C: (f, a) => f(...a)
2644
- });
2645
- }
2646
- // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
2647
- // Hosts, running in the worker, don't share documents unless requested by other peers.
2648
- // NOTE: If both peers return sharePolicy=false the replication will not happen
2649
- // https://github.com/automerge/automerge-repo/pull/292
2650
- async _sharePolicy(peerId, documentId) {
2651
- if (peerId.startsWith("client-")) {
2652
- return false;
2653
- }
2654
- if (!documentId) {
2655
- return false;
2656
- }
2657
- const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
2658
- if (isEchoPeerMetadata(peerMetadata)) {
2659
- return this._echoNetworkAdapter.shouldAdvertise(peerId, {
2660
- documentId
2661
- });
2662
- }
2663
- return false;
2664
- }
2665
- async _beforeSave({ path, batch }) {
2666
- const handle = this._repo.handles[path[0]];
2667
- if (!handle) {
2668
- return;
2669
- }
2670
- const doc = handle.docSync();
2671
- if (!doc) {
2672
- return;
2673
- }
2674
- const heads = (0, import_automerge3.getHeads)(doc);
2675
- this._headsStore.setHeads(handle.documentId, heads, batch);
2676
- const spaceKey = getSpaceKeyFromDoc(doc) ?? void 0;
2677
- const objectIds = Object.keys(doc.objects ?? {});
2678
- const encodedIds = objectIds.map((objectId) => import_protocols7.objectPointerCodec.encode({
2679
- documentId: handle.documentId,
2680
- objectId,
2681
- spaceKey
2682
- }));
2683
- const idToLastHash = new Map(encodedIds.map((id) => [
2684
- id,
2685
- heads
2686
- ]));
2687
- this._indexMetadataStore.markDirty(idToLastHash, batch);
2688
- }
2689
- _shouldSyncCollection(collectionId, peerId) {
2690
- const peerMetadata = this._repo.peerMetadataByPeerId[peerId];
2691
- if (isEchoPeerMetadata(peerMetadata)) {
2692
- return this._echoNetworkAdapter.shouldSyncCollection(peerId, {
2693
- collectionId
2694
- });
2695
- }
2696
- return false;
2697
- }
2698
- /**
2699
- * Called by AutomergeStorageAdapter after levelDB batch commit.
2700
- */
2701
- async _afterSave(path) {
2702
- this._indexMetadataStore.notifyMarkedDirty();
2703
- const documentId = path[0];
2704
- const document = this._repo.handles[documentId]?.docSync();
2705
- if (document) {
2706
- const heads = (0, import_automerge3.getHeads)(document);
2707
- this._onHeadsChanged(documentId, heads);
2708
- }
2709
- }
2710
- _automergePeers() {
2711
- return this._repo.peers;
2712
- }
2713
- async _isDocumentInRemoteCollection(params) {
2714
- for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
2715
- const remoteCollections = this._collectionSynchronizer.getRemoteCollectionStates(collectionId);
2716
- const remotePeerDocs = remoteCollections.get(params.peerId)?.documents;
2717
- if (remotePeerDocs && params.documentId in remotePeerDocs) {
2718
- return true;
2719
- }
2720
- }
2721
- return false;
2722
- }
2723
- async _getContainingSpaceForDocument(documentId) {
2724
- const doc = this._repo.handles[documentId]?.docSync();
2725
- if (!doc) {
2726
- return null;
2727
- }
2728
- const spaceKeyHex = getSpaceKeyFromDoc(doc);
2729
- if (!spaceKeyHex) {
2730
- return null;
2731
- }
2732
- return import_keys8.PublicKey.from(spaceKeyHex);
2733
- }
2734
- /**
2735
- * Flush documents to disk.
2736
- */
2737
- async flush({ documentIds } = {}) {
2738
- await this._repo.flush(documentIds);
2739
- }
2740
- async getHeads(documentIds) {
2741
- const result = [];
2742
- const storeRequestIds = [];
2743
- const storeResultIndices = [];
2744
- for (const documentId of documentIds) {
2745
- const doc = this._repo.handles[documentId]?.docSync();
2746
- if (doc) {
2747
- result.push((0, import_automerge3.getHeads)(doc));
2748
- } else {
2749
- storeRequestIds.push(documentId);
2750
- storeResultIndices.push(result.length);
2751
- result.push(void 0);
2752
- }
2753
- }
2754
- if (storeRequestIds.length > 0) {
2755
- const storedHeads = await this._headsStore.getHeads(storeRequestIds);
2756
- for (let i = 0; i < storedHeads.length; i++) {
2757
- result[storeResultIndices[i]] = storedHeads[i];
2758
- }
2759
- }
2760
- return result;
2761
- }
2762
- //
2763
- // Collection sync.
2764
- //
2765
- getLocalCollectionState(collectionId) {
2766
- return this._collectionSynchronizer.getLocalCollectionState(collectionId);
2767
- }
2768
- getRemoteCollectionStates(collectionId) {
2769
- return this._collectionSynchronizer.getRemoteCollectionStates(collectionId);
2770
- }
2771
- refreshCollection(collectionId) {
2772
- this._collectionSynchronizer.refreshCollection(collectionId);
2773
- }
2774
- async getCollectionSyncState(collectionId) {
2775
- const result = {
2776
- peers: []
2777
- };
2778
- const localState = this.getLocalCollectionState(collectionId);
2779
- const remoteState = this.getRemoteCollectionStates(collectionId);
2780
- if (!localState) {
2781
- return result;
2782
- }
2783
- for (const [peerId, state] of remoteState) {
2784
- const diff = diffCollectionState(localState, state);
2785
- result.peers.push({
2786
- peerId,
2787
- differentDocuments: diff.different.length
2788
- });
2789
- }
2790
- return result;
2791
- }
2792
- /**
2793
- * Update the local collection state based on the locally stored document heads.
2794
- */
2795
- async updateLocalCollectionState(collectionId, documentIds) {
2796
- const heads = await this.getHeads(documentIds);
2797
- const documents = Object.fromEntries(heads.map((heads2, index) => [
2798
- documentIds[index],
2799
- heads2 ?? []
2800
- ]));
2801
- this._collectionSynchronizer.setLocalCollectionState(collectionId, {
2802
- documents
2803
- });
2804
- }
2805
- _onCollectionStateQueried(collectionId, peerId) {
2806
- this._collectionSynchronizer.onCollectionStateQueried(collectionId, peerId);
2807
- }
2808
- _onCollectionStateReceived(collectionId, peerId, state) {
2809
- this._collectionSynchronizer.onRemoteStateReceived(collectionId, peerId, decodeCollectionState(state));
2810
- }
2811
- _queryCollectionState(collectionId, peerId) {
2812
- this._echoNetworkAdapter.queryCollectionState(collectionId, peerId);
2813
- }
2814
- _sendCollectionState(collectionId, peerId, state) {
2815
- this._echoNetworkAdapter.sendCollectionState(collectionId, peerId, encodeCollectionState(state));
2816
- }
2817
- _onPeerConnected(peerId) {
2818
- this._collectionSynchronizer.onConnectionOpen(peerId);
2819
- }
2820
- _onPeerDisconnected(peerId) {
2821
- this._collectionSynchronizer.onConnectionClosed(peerId);
2822
- }
2823
- _onRemoteCollectionStateUpdated(collectionId, peerId) {
2824
- const localState = this._collectionSynchronizer.getLocalCollectionState(collectionId);
2825
- const remoteState = this._collectionSynchronizer.getRemoteCollectionStates(collectionId).get(peerId);
2826
- if (!localState || !remoteState) {
2827
- return;
2828
- }
2829
- const { different } = diffCollectionState(localState, remoteState);
2830
- if (different.length === 0) {
2831
- return;
2832
- }
2833
- import_log11.log.info("replication documents after collection sync", {
2834
- count: different.length
2835
- }, {
2836
- F: __dxlog_file12,
2837
- L: 475,
2838
- S: this,
2839
- C: (f, a) => f(...a)
2840
- });
2841
- for (const documentId of different) {
2842
- this._repo.find(documentId);
2843
- }
2844
- }
2845
- _onHeadsChanged(documentId, heads) {
2846
- for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
2847
- const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
2848
- if (state?.documents[documentId]) {
2849
- const newState = structuredClone(state);
2850
- newState.documents[documentId] = heads;
2851
- this._collectionSynchronizer.setLocalCollectionState(collectionId, newState);
2852
- }
2853
- }
2854
- }
2855
- };
2856
- _ts_decorate7([
2857
- import_tracing4.trace.info()
2858
- ], AutomergeHost.prototype, "_peerId", void 0);
2859
- _ts_decorate7([
2860
- import_tracing4.trace.info({
2861
- depth: null
2862
- })
2863
- ], AutomergeHost.prototype, "_automergePeers", null);
2864
- _ts_decorate7([
2865
- import_tracing4.trace.span({
2866
- showInBrowserTimeline: true
2867
- })
2868
- ], AutomergeHost.prototype, "flush", null);
2869
- AutomergeHost = _ts_decorate7([
2870
- import_tracing4.trace.resource()
2871
- ], AutomergeHost);
2872
- var getSpaceKeyFromDoc = (doc) => {
2873
- const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
2874
- if (rawSpaceKey == null) {
2875
- return null;
2876
- }
2877
- return String(rawSpaceKey);
2878
- };
2879
- var waitForHeads = async (handle, heads) => {
2880
- const unavailableHeads = new Set(heads);
2881
- await handle.whenReady();
2882
- await import_async10.Event.wrap(handle, "change").waitForCondition(() => {
2883
- for (const changeHash of unavailableHeads.values()) {
2884
- if (changeIsPresentInDoc(handle.docSync(), changeHash)) {
2885
- unavailableHeads.delete(changeHash);
2886
- }
2887
- }
2888
- return unavailableHeads.size === 0;
2889
- });
2890
- };
2891
- var changeIsPresentInDoc = (doc, changeHash) => {
2892
- return !!(0, import_automerge3.getBackend)(doc).getChangeByHash(changeHash);
2893
- };
2894
- var decodeCollectionState = (state) => {
2895
- (0, import_invariant8.invariant)(typeof state === "object" && state !== null, "Invalid state", {
2896
- F: __dxlog_file12,
2897
- L: 528,
2898
- S: void 0,
2899
- A: [
2900
- "typeof state === 'object' && state !== null",
2901
- "'Invalid state'"
2902
- ]
2903
- });
2904
- return state;
2905
- };
2906
- var encodeCollectionState = (state) => {
2907
- return state;
2908
- };
2909
- var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
2910
- var DEFAULT_FACTORY = (params) => new import_teleport_extension_automerge_replicator.AutomergeReplicator(...params);
2911
- var MeshReplicatorConnection = class extends import_context12.Resource {
2912
- constructor(_params) {
2913
- super();
2914
- this._params = _params;
2915
- this.remoteDeviceKey = null;
2916
- this._remotePeerId = null;
2917
- this._isEnabled = false;
2918
- let readableStreamController;
2919
- this.readable = new ReadableStream({
2920
- start: (controller) => {
2921
- readableStreamController = controller;
2922
- this._ctx.onDispose(() => controller.close());
2923
- }
2924
- });
2925
- this.writable = new WritableStream({
2926
- write: async (message, controller) => {
2927
- (0, import_invariant11.invariant)(this._isEnabled, "Writing to a disabled connection", {
2928
- F: __dxlog_file13,
2929
- L: 49,
2930
- S: this,
2931
- A: [
2932
- "this._isEnabled",
2933
- "'Writing to a disabled connection'"
2934
- ]
2935
- });
2936
- try {
2937
- logSendSync(message);
2938
- await this.replicatorExtension.sendSyncMessage({
2939
- payload: import_automerge_repo3.cbor.encode(message)
2940
- });
2941
- } catch (err) {
2942
- controller.error(err);
2943
- this._disconnectIfEnabled();
2944
- }
2945
- }
2946
- });
2947
- const createAutomergeReplicator = this._params.replicatorFactory ?? DEFAULT_FACTORY;
2948
- this.replicatorExtension = createAutomergeReplicator([
2949
- {
2950
- peerId: this._params.ownPeerId
2951
- },
2952
- {
2953
- onStartReplication: async (info, remotePeerId) => {
2954
- this.remoteDeviceKey = remotePeerId;
2955
- this._remotePeerId = info.id;
2956
- (0, import_log14.log)("onStartReplication", {
2957
- id: info.id,
2958
- thisPeerId: this.peerId,
2959
- remotePeerId: remotePeerId.toHex()
2960
- }, {
2961
- F: __dxlog_file13,
2962
- L: 84,
2963
- S: this,
2964
- C: (f, a) => f(...a)
2965
- });
2966
- this._params.onRemoteConnected();
2967
- },
2968
- onSyncMessage: async ({ payload }) => {
2969
- if (!this._isEnabled) {
2970
- return;
2971
- }
2972
- const message = import_automerge_repo3.cbor.decode(payload);
2973
- readableStreamController.enqueue(message);
2974
- },
2975
- onClose: async () => {
2976
- this._disconnectIfEnabled();
2977
- }
2978
- }
2979
- ]);
2980
- }
2981
- _disconnectIfEnabled() {
2982
- if (this._isEnabled) {
2983
- this._params.onRemoteDisconnected();
2984
- }
2985
- }
2986
- get peerId() {
2987
- (0, import_invariant11.invariant)(this._remotePeerId != null, "Remote peer has not connected yet.", {
2988
- F: __dxlog_file13,
2989
- L: 110,
2990
- S: this,
2991
- A: [
2992
- "this._remotePeerId != null",
2993
- "'Remote peer has not connected yet.'"
2994
- ]
2995
- });
2996
- return this._remotePeerId;
2997
- }
2998
- async shouldAdvertise(params) {
2999
- return this._params.shouldAdvertise(params);
3000
- }
3001
- shouldSyncCollection(params) {
3002
- return this._params.shouldSyncCollection(params);
3003
- }
3004
- /**
3005
- * Start exchanging messages with the remote peer.
3006
- * Call after the remote peer has connected.
3007
- */
3008
- enable() {
3009
- (0, import_invariant11.invariant)(this._remotePeerId != null, "Remote peer has not connected yet.", {
3010
- F: __dxlog_file13,
3011
- L: 127,
3012
- S: this,
3013
- A: [
3014
- "this._remotePeerId != null",
3015
- "'Remote peer has not connected yet.'"
3016
- ]
3017
- });
3018
- this._isEnabled = true;
3019
- }
3020
- /**
3021
- * Stop exchanging messages with the remote peer.
3022
- */
3023
- disable() {
3024
- this._isEnabled = false;
3025
- }
3026
- };
3027
- var logSendSync = (message) => {
3028
- (0, import_log14.log)("sendSyncMessage", () => {
3029
- const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
3030
- return {
3031
- sync: decodedSyncMessage && {
3032
- headsLength: decodedSyncMessage.heads.length,
3033
- requesting: decodedSyncMessage.need.length > 0,
3034
- sendingChanges: decodedSyncMessage.changes.length > 0
3035
- },
3036
- type: message.type,
3037
- from: message.senderId,
3038
- to: message.targetId
3039
- };
3040
- }, {
3041
- F: __dxlog_file13,
3042
- L: 140,
3043
- S: void 0,
3044
- C: (f, a) => f(...a)
3045
- });
3046
- };
3047
- var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
3048
- var deriveCollectionIdFromSpaceId = (spaceId) => `space:${spaceId}`;
3049
- var getSpaceIdFromCollectionId = (collectionId) => {
3050
- const spaceId = collectionId.replace(/^space:/, "");
3051
- (0, import_invariant12.invariant)(import_keys10.SpaceId.isValid(spaceId), void 0, {
3052
- F: __dxlog_file14,
3053
- L: 12,
3054
- S: void 0,
3055
- A: [
3056
- "SpaceId.isValid(spaceId)",
3057
- ""
3058
- ]
3059
- });
3060
- return spaceId;
3061
- };
3062
- var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
3063
- var MeshEchoReplicator = class {
3064
- constructor() {
3065
- this._connections = /* @__PURE__ */ new Set();
3066
- this._connectionsPerPeer = /* @__PURE__ */ new Map();
3067
- this._authorizedDevices = /* @__PURE__ */ new Map();
3068
- this._context = null;
3069
- }
3070
- async connect(context) {
3071
- this._context = context;
3072
- }
3073
- async disconnect() {
3074
- for (const connection of this._connectionsPerPeer.values()) {
3075
- this._context?.onConnectionClosed(connection);
3076
- }
3077
- for (const connection of this._connections) {
3078
- await connection.close();
3079
- }
3080
- this._connections.clear();
3081
- this._connectionsPerPeer.clear();
3082
- this._context = null;
3083
- }
3084
- createExtension(extensionFactory) {
3085
- (0, import_invariant10.invariant)(this._context, void 0, {
3086
- F: __dxlog_file15,
3087
- L: 56,
3088
- S: this,
3089
- A: [
3090
- "this._context",
3091
- ""
3092
- ]
3093
- });
3094
- const connection = new MeshReplicatorConnection({
3095
- ownPeerId: this._context.peerId,
3096
- replicatorFactory: extensionFactory,
3097
- onRemoteConnected: async () => {
3098
- (0, import_log13.log)("onRemoteConnected", {
3099
- peerId: connection.peerId
3100
- }, {
3101
- F: __dxlog_file15,
3102
- L: 62,
3103
- S: this,
3104
- C: (f, a) => f(...a)
3105
- });
3106
- (0, import_invariant10.invariant)(this._context, void 0, {
3107
- F: __dxlog_file15,
3108
- L: 63,
3109
- S: this,
3110
- A: [
3111
- "this._context",
3112
- ""
3113
- ]
3114
- });
3115
- if (this._connectionsPerPeer.has(connection.peerId)) {
3116
- this._context.onConnectionAuthScopeChanged(connection);
3117
- } else {
3118
- this._connectionsPerPeer.set(connection.peerId, connection);
3119
- this._context.onConnectionOpen(connection);
3120
- connection.enable();
3121
- }
3122
- },
3123
- onRemoteDisconnected: async () => {
3124
- (0, import_log13.log)("onRemoteDisconnected", {
3125
- peerId: connection.peerId
3126
- }, {
3127
- F: __dxlog_file15,
3128
- L: 74,
3129
- S: this,
3130
- C: (f, a) => f(...a)
3131
- });
3132
- this._context?.onConnectionClosed(connection);
3133
- this._connectionsPerPeer.delete(connection.peerId);
3134
- connection.disable();
3135
- this._connections.delete(connection);
3136
- },
3137
- shouldAdvertise: async (params) => {
3138
- (0, import_log13.log)("shouldAdvertise", {
3139
- peerId: connection.peerId,
3140
- documentId: params.documentId
3141
- }, {
3142
- F: __dxlog_file15,
3143
- L: 81,
3144
- S: this,
3145
- C: (f, a) => f(...a)
3146
- });
3147
- (0, import_invariant10.invariant)(this._context, void 0, {
3148
- F: __dxlog_file15,
3149
- L: 82,
3150
- S: this,
3151
- A: [
3152
- "this._context",
3153
- ""
3154
- ]
3155
- });
3156
- try {
3157
- const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
3158
- if (!spaceKey) {
3159
- const remoteDocumentExists = await this._context.isDocumentInRemoteCollection({
3160
- documentId: params.documentId,
3161
- peerId: connection.peerId
3162
- });
3163
- (0, import_log13.log)("document not found locally for share policy check, accepting the remote document", {
3164
- peerId: connection.peerId,
3165
- documentId: params.documentId,
3166
- remoteDocumentExists
3167
- }, {
3168
- F: __dxlog_file15,
3169
- L: 90,
3170
- S: this,
3171
- C: (f, a) => f(...a)
3172
- });
3173
- return remoteDocumentExists;
3174
- }
3175
- const spaceId = await createIdFromSpaceKey(spaceKey);
3176
- const authorizedDevices = this._authorizedDevices.get(spaceId);
3177
- if (!connection.remoteDeviceKey) {
3178
- (0, import_log13.log)("device key not found for share policy check", {
3179
- peerId: connection.peerId,
3180
- documentId: params.documentId
3181
- }, {
3182
- F: __dxlog_file15,
3183
- L: 106,
3184
- S: this,
3185
- C: (f, a) => f(...a)
3186
- });
3187
- return false;
3188
- }
3189
- const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
3190
- (0, import_log13.log)("share policy check", {
3191
- localPeer: this._context.peerId,
3192
- remotePeer: connection.peerId,
3193
- documentId: params.documentId,
3194
- deviceKey: connection.remoteDeviceKey,
3195
- spaceKey,
3196
- isAuthorized
3197
- }, {
3198
- F: __dxlog_file15,
3199
- L: 114,
3200
- S: this,
3201
- C: (f, a) => f(...a)
3202
- });
3203
- return isAuthorized;
3204
- } catch (err) {
3205
- import_log13.log.catch(err, void 0, {
3206
- F: __dxlog_file15,
3207
- L: 124,
3208
- S: this,
3209
- C: (f, a) => f(...a)
3210
- });
3211
- return false;
3212
- }
3213
- },
3214
- shouldSyncCollection: ({ collectionId }) => {
3215
- const spaceId = getSpaceIdFromCollectionId(collectionId);
3216
- const authorizedDevices = this._authorizedDevices.get(spaceId);
3217
- if (!connection.remoteDeviceKey) {
3218
- (0, import_log13.log)("device key not found for collection sync check", {
3219
- peerId: connection.peerId,
3220
- collectionId
3221
- }, {
3222
- F: __dxlog_file15,
3223
- L: 134,
3224
- S: this,
3225
- C: (f, a) => f(...a)
3226
- });
3227
- return false;
3228
- }
3229
- const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
3230
- return isAuthorized;
3231
- }
3232
- });
3233
- this._connections.add(connection);
3234
- return connection.replicatorExtension;
3235
- }
3236
- async authorizeDevice(spaceKey, deviceKey) {
3237
- (0, import_log13.log)("authorizeDevice", {
3238
- spaceKey,
3239
- deviceKey
3240
- }, {
3241
- F: __dxlog_file15,
3242
- L: 151,
3243
- S: this,
3244
- C: (f, a) => f(...a)
3245
- });
3246
- const spaceId = await createIdFromSpaceKey(spaceKey);
3247
- (0, import_util8.defaultMap)(this._authorizedDevices, spaceId, () => new import_util8.ComplexSet(import_keys9.PublicKey.hash)).add(deviceKey);
3248
- for (const connection of this._connections) {
3249
- if (connection.remoteDeviceKey && connection.remoteDeviceKey.equals(deviceKey)) {
3250
- if (this._connectionsPerPeer.has(connection.peerId)) {
3251
- this._context?.onConnectionAuthScopeChanged(connection);
3252
- }
3253
- }
3254
- }
3255
- }
3256
- };
3257
- function _ts_decorate8(decorators, target, key, desc) {
3258
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3259
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3260
- r = Reflect.decorate(decorators, target, key, desc);
3261
- else
3262
- for (var i = decorators.length - 1; i >= 0; i--)
3263
- if (d = decorators[i])
3264
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3265
- return c > 3 && r && Object.defineProperty(target, key, r), r;
3266
- }
3267
- var PER_SECOND_RATE_AVG_WINDOW_SIZE = 5;
3268
- var DEFAULT_AVG_WINDOW_SIZE = 25;
3269
- var EchoDataMonitor = class {
3270
- constructor(_params = {
3271
- timeSeriesLength: 30
3272
- }) {
3273
- this._params = _params;
3274
- this._lastTick = 0;
3275
- this._activeCounters = createLocalCounters();
3276
- this._localTimeSeries = createLocalTimeSeries();
3277
- this._storageAverages = createStorageAverages();
3278
- this._replicationAverages = createNetworkAverages();
3279
- this._sizeByMessageType = {};
3280
- this._lastReceivedMessages = new import_util9.CircularBuffer(100);
3281
- this._lastSentMessages = new import_util9.CircularBuffer(100);
3282
- this._connectionsCount = 0;
3283
- }
3284
- tick(timeMs) {
3285
- this._advanceTimeWindow(timeMs - this._lastTick);
3286
- this._lastTick = timeMs;
3287
- }
3288
- computeStats() {
3289
- return {
3290
- meta: {
3291
- rateAverageOverSeconds: PER_SECOND_RATE_AVG_WINDOW_SIZE
3292
- },
3293
- storage: {
3294
- reads: {
3295
- payloadSize: this._storageAverages.loadedChunkSize.average(),
3296
- opDuration: this._storageAverages.loadDuration.average(),
3297
- countPerSecond: this._storageAverages.loadsPerSecond.average()
3298
- },
3299
- writes: {
3300
- payloadSize: this._storageAverages.storedChunkSize.average(),
3301
- opDuration: this._storageAverages.storeDuration.average(),
3302
- countPerSecond: this._storageAverages.storesPerSecond.average()
3303
- }
3304
- },
3305
- replicator: {
3306
- connections: this._connectionsCount,
3307
- receivedMessages: {
3308
- payloadSize: this._replicationAverages.receivedMessageSize.average(),
3309
- countPerSecond: this._replicationAverages.receivedPerSecond.average()
3310
- },
3311
- sentMessages: {
3312
- payloadSize: this._replicationAverages.sentMessageSize.average(),
3313
- opDuration: this._replicationAverages.sendDuration.average(),
3314
- countPerSecond: this._replicationAverages.sentPerSecond.average(),
3315
- failedPerSecond: this._replicationAverages.sendsFailedPerSecond.average()
3316
- },
3317
- countByMessageType: this._computeMessageHistogram("type"),
3318
- avgSizeByMessageType: (0, import_util9.mapValues)(this._sizeByMessageType, (summary) => summary.average())
3319
- }
3320
- };
3321
- }
3322
- get connectionsCount() {
3323
- return this._connectionsCount;
3324
- }
3325
- /**
3326
- * @internal
3327
- */
3328
- get lastPerSecondStats() {
3329
- return this._lastCompleteCounters;
3330
- }
3331
- /**
3332
- * @internal
3333
- */
3334
- get timeSeries() {
3335
- return {
3336
- ...this._localTimeSeries.storage,
3337
- ...this._localTimeSeries.replication
3338
- };
3339
- }
3340
- /**
3341
- * @internal
3342
- */
3343
- get messagesByPeerId() {
3344
- return this._computeMessageHistogram("peerId");
3345
- }
3346
- _advanceTimeWindow(millisPassed) {
3347
- const oldMetrics = Object.freeze(this._activeCounters);
3348
- this._activeCounters = createLocalCounters();
3349
- this._lastCompleteCounters = oldMetrics;
3350
- for (const peerId of Object.keys(oldMetrics.byPeerId)) {
3351
- this._activeCounters.byPeerId[peerId] = createMessageCounter();
3352
- }
3353
- this._addToTimeSeries(oldMetrics.replication, this._localTimeSeries.replication);
3354
- this._addToTimeSeries(oldMetrics.storage, this._localTimeSeries.storage);
3355
- if (Math.abs(millisPassed - 1e3) < 100) {
3356
- this._reportPerSecondRate(oldMetrics);
3357
- }
3358
- }
3359
- _addToTimeSeries(values, timeSeries) {
3360
- for (const [key, value] of Object.entries(values)) {
3361
- const values2 = timeSeries[key];
3362
- values2.push(value);
3363
- if (values2.length > this._params.timeSeriesLength) {
3364
- values2.shift();
3365
- }
3366
- }
3367
- }
3368
- _reportPerSecondRate(metrics) {
3369
- const toReport = [
3370
- [
3371
- "storage.load",
3372
- metrics.storage.loadedChunks,
3373
- this._storageAverages.loadsPerSecond
3374
- ],
3375
- [
3376
- "storage.store",
3377
- metrics.storage.storedChunks,
3378
- this._storageAverages.storesPerSecond
3379
- ],
3380
- [
3381
- "network.receive",
3382
- metrics.replication.received,
3383
- this._replicationAverages.receivedPerSecond
3384
- ],
3385
- [
3386
- "network.send",
3387
- metrics.replication.sent,
3388
- this._replicationAverages.sentPerSecond
3389
- ]
3390
- ];
3391
- for (const [metricName, metric, summary] of toReport) {
3392
- summary.record(metric);
3393
- if (metric > 0) {
3394
- import_tracing5.trace.metrics.distribution(`dxos.echo.${metricName}-rate`, metric);
3395
- import_tracing5.trace.metrics.increment(`dxos.echo.${metricName}`, 1, {
3396
- tags: {
3397
- status: "busy"
3398
- }
3399
- });
3400
- } else {
3401
- import_tracing5.trace.metrics.increment(`dxos.echo.${metricName}`, 1, {
3402
- tags: {
3403
- status: "idle"
3404
- }
3405
- });
3406
- }
3407
- }
3408
- this._replicationAverages.sendsFailedPerSecond.record(metrics.replication.failed);
3409
- }
3410
- recordPeerConnected(peerId) {
3411
- this._activeCounters.byPeerId[peerId] = createMessageCounter();
3412
- this._connectionsCount++;
3413
- }
3414
- recordPeerDisconnected(peerId) {
3415
- this._connectionsCount--;
3416
- delete this._activeCounters.byPeerId[peerId];
3417
- }
3418
- recordBytesStored(count) {
3419
- this._activeCounters.storage.storedChunks++;
3420
- this._activeCounters.storage.storedBytes += count;
3421
- this._storageAverages.storedChunkSize.record(count);
3422
- import_tracing5.trace.metrics.distribution("dxos.echo.storage.bytes-stored", count, {
3423
- unit: "bytes"
3424
- });
3425
- }
3426
- recordLoadDuration(durationMs) {
3427
- this._storageAverages.loadDuration.record(durationMs);
3428
- }
3429
- recordStoreDuration(durationMs) {
3430
- this._storageAverages.storeDuration.record(durationMs);
3431
- }
3432
- recordBytesLoaded(count) {
3433
- this._activeCounters.storage.loadedChunks++;
3434
- this._activeCounters.storage.loadedBytes += count;
3435
- this._storageAverages.loadedChunkSize.record(count);
3436
- import_tracing5.trace.metrics.distribution("dxos.echo.storage.bytes-loaded", count, {
3437
- unit: "bytes"
3438
- });
3439
- }
3440
- recordMessageSent(message, duration) {
3441
- let metricsGroupName;
3442
- const bytes = getByteCount(message);
3443
- const tags = {
3444
- type: message.type
3445
- };
3446
- if (isAutomergeProtocolMessage(message)) {
3447
- this._activeCounters.replication.sent++;
3448
- this._replicationAverages.sendDuration.record(duration);
3449
- this._replicationAverages.sentMessageSize.record(bytes);
3450
- metricsGroupName = "replication";
3451
- } else {
3452
- metricsGroupName = "collection-sync";
3453
- }
3454
- import_tracing5.trace.metrics.distribution(`dxos.echo.${metricsGroupName}.bytes-sent`, bytes, {
3455
- unit: "bytes",
3456
- tags
3457
- });
3458
- import_tracing5.trace.metrics.distribution(`dxos.echo.${metricsGroupName}.send-duration`, duration, {
3459
- unit: "millisecond",
3460
- tags
3461
- });
3462
- import_tracing5.trace.metrics.increment(`dxos.echo.${metricsGroupName}.send-status`, 1, {
3463
- tags: {
3464
- ...tags,
3465
- success: true
3466
- }
3467
- });
3468
- const { messageSize, messageCounts } = this._getStatsForType(message);
3469
- messageSize.record(bytes);
3470
- messageCounts.sent++;
3471
- this._lastSentMessages.push({
3472
- type: message.type,
3473
- peerId: message.targetId
3474
- });
3475
- }
3476
- recordMessageReceived(message) {
3477
- const bytes = getByteCount(message);
3478
- const tags = {
3479
- type: message.type
3480
- };
3481
- if (isAutomergeProtocolMessage(message)) {
3482
- this._activeCounters.replication.received++;
3483
- this._replicationAverages.receivedMessageSize.record(bytes);
3484
- import_tracing5.trace.metrics.distribution("dxos.echo.replication.bytes-received", bytes, {
3485
- unit: "bytes",
3486
- tags
3487
- });
3488
- } else {
3489
- import_tracing5.trace.metrics.distribution("dxos.echo.collection-sync.bytes-received", bytes, {
3490
- unit: "bytes",
3491
- tags
3492
- });
3493
- }
3494
- const { messageSize, messageCounts } = this._getStatsForType(message);
3495
- messageSize.record(bytes);
3496
- messageCounts.received++;
3497
- this._lastReceivedMessages.push({
3498
- type: message.type,
3499
- peerId: message.senderId
3500
- });
3501
- }
3502
- recordMessageSendingFailed(message) {
3503
- const tags = {
3504
- type: message.type,
3505
- success: false
3506
- };
3507
- if (isAutomergeProtocolMessage(message)) {
3508
- this._activeCounters.replication.failed++;
3509
- import_tracing5.trace.metrics.increment("dxos.echo.replication.send-status", 1, {
3510
- unit: "bytes",
3511
- tags
3512
- });
3513
- } else {
3514
- import_tracing5.trace.metrics.increment("dxos.echo.collection-sync.send-status", 1, {
3515
- unit: "bytes",
3516
- tags
3517
- });
3518
- }
3519
- const { messageCounts } = this._getStatsForType(message);
3520
- messageCounts.failed++;
3521
- }
3522
- _getStatsForType(message) {
3523
- const messageSize = this._sizeByMessageType[message.type] ??= createSlidingWindow();
3524
- const messageCounts = this._activeCounters.byType[message.type] ??= createMessageCounter();
3525
- return {
3526
- messageCounts,
3527
- messageSize
3528
- };
3529
- }
3530
- _computeMessageHistogram(groupKey) {
3531
- const result = {};
3532
- for (const receivedMessage of this._lastReceivedMessages) {
3533
- const counters = result[receivedMessage[groupKey]] ??= {
3534
- received: 0,
3535
- sent: 0
3536
- };
3537
- counters.received++;
3538
- }
3539
- for (const receivedMessage of this._lastSentMessages) {
3540
- const counters = result[receivedMessage[groupKey]] ??= {
3541
- received: 0,
3542
- sent: 0
3543
- };
3544
- counters.sent++;
3545
- }
3546
- return result;
3547
- }
3548
- };
3549
- EchoDataMonitor = _ts_decorate8([
3550
- import_tracing5.trace.resource()
3551
- ], EchoDataMonitor);
3552
- var isAutomergeProtocolMessage = (message) => {
3553
- return !(isCollectionQueryMessage(message) || isCollectionStateMessage(message));
3554
- };
3555
- var createSlidingWindow = (overrides) => new import_util9.SlidingWindowSummary({
3556
- dataPoints: DEFAULT_AVG_WINDOW_SIZE,
3557
- precision: 2,
3558
- ...overrides
3559
- });
3560
- var createLocalCounters = () => ({
3561
- storage: {
3562
- loadedBytes: 0,
3563
- storedBytes: 0,
3564
- storedChunks: 0,
3565
- loadedChunks: 0
3566
- },
3567
- replication: createMessageCounter(),
3568
- byPeerId: {},
3569
- byType: {}
3570
- });
3571
- var createLocalTimeSeries = () => ({
3572
- storage: {
3573
- loadedBytes: [],
3574
- storedBytes: [],
3575
- storedChunks: [],
3576
- loadedChunks: []
3577
- },
3578
- replication: {
3579
- sent: [],
3580
- failed: [],
3581
- received: []
3582
- }
3583
- });
3584
- var createMessageCounter = () => ({
3585
- sent: 0,
3586
- received: 0,
3587
- failed: 0
3588
- });
3589
- var createNetworkAverages = () => ({
3590
- receivedMessageSize: createSlidingWindow(),
3591
- sentMessageSize: createSlidingWindow(),
3592
- sendDuration: createSlidingWindow(),
3593
- receivedPerSecond: createSlidingWindow({
3594
- dataPoints: PER_SECOND_RATE_AVG_WINDOW_SIZE
3595
- }),
3596
- sentPerSecond: createSlidingWindow({
3597
- dataPoints: PER_SECOND_RATE_AVG_WINDOW_SIZE
3598
- }),
3599
- sendsFailedPerSecond: createSlidingWindow({
3600
- dataPoints: PER_SECOND_RATE_AVG_WINDOW_SIZE
3601
- })
3602
- });
3603
- var createStorageAverages = () => ({
3604
- storedChunkSize: createSlidingWindow(),
3605
- loadedChunkSize: createSlidingWindow(),
3606
- loadDuration: createSlidingWindow(),
3607
- storeDuration: createSlidingWindow(),
3608
- loadsPerSecond: createSlidingWindow({
3609
- dataPoints: PER_SECOND_RATE_AVG_WINDOW_SIZE
3610
- }),
3611
- storesPerSecond: createSlidingWindow({
3612
- dataPoints: PER_SECOND_RATE_AVG_WINDOW_SIZE
3613
- })
3614
- });
3615
- var getByteCount = (message) => {
3616
- return message.type.length + message.senderId.length + message.targetId.length + (message.data?.byteLength ?? 0) + (message.documentId?.length ?? 0);
3617
- };
3618
- var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
3619
- var DataServiceImpl = class {
3620
- constructor(params) {
3621
- this._subscriptions = /* @__PURE__ */ new Map();
3622
- this._automergeHost = params.automergeHost;
3623
- this._updateIndexes = params.updateIndexes;
3624
- }
3625
- subscribe(request) {
3626
- return new import_codec_protobuf.Stream(({ next, ready }) => {
3627
- const synchronizer = new DocumentsSynchronizer({
3628
- repo: this._automergeHost.repo,
3629
- sendUpdates: (updates) => next(updates)
3630
- });
3631
- synchronizer.open().then(() => {
3632
- this._subscriptions.set(request.subscriptionId, synchronizer);
3633
- ready();
3634
- }).catch((err) => import_log10.log.catch(err, void 0, {
3635
- F: __dxlog_file16,
3636
- L: 64,
3637
- S: this,
3638
- C: (f, a) => f(...a)
3639
- }));
3640
- return () => synchronizer.close();
3641
- });
3642
- }
3643
- async updateSubscription(request) {
3644
- const synchronizer = this._subscriptions.get(request.subscriptionId);
3645
- (0, import_invariant7.invariant)(synchronizer, "Subscription not found", {
3646
- F: __dxlog_file16,
3647
- L: 71,
3648
- S: this,
3649
- A: [
3650
- "synchronizer",
3651
- "'Subscription not found'"
3652
- ]
3653
- });
3654
- if (request.addIds?.length) {
3655
- await synchronizer.addDocuments(request.addIds);
3656
- }
3657
- if (request.removeIds?.length) {
3658
- await synchronizer.removeDocuments(request.removeIds);
3659
- }
3660
- }
3661
- async update(request) {
3662
- if (!request.updates) {
3663
- return;
3664
- }
3665
- const synchronizer = this._subscriptions.get(request.subscriptionId);
3666
- (0, import_invariant7.invariant)(synchronizer, "Subscription not found", {
3667
- F: __dxlog_file16,
3668
- L: 86,
3669
- S: this,
3670
- A: [
3671
- "synchronizer",
3672
- "'Subscription not found'"
3673
- ]
3674
- });
3675
- synchronizer.update(request.updates);
3676
- }
3677
- async flush(request) {
3678
- await this._automergeHost.flush(request);
3679
- }
3680
- async getDocumentHeads(request) {
3681
- const documentIds = request.documentIds;
3682
- if (!documentIds) {
3683
- return {
3684
- heads: {
3685
- entries: []
3686
- }
3687
- };
3688
- }
3689
- const heads = await this._automergeHost.getHeads(documentIds);
3690
- return {
3691
- heads: {
3692
- entries: heads.map((heads2, idx) => ({
3693
- documentId: documentIds[idx],
3694
- heads: heads2
3695
- }))
3696
- }
3697
- };
3698
- }
3699
- async waitUntilHeadsReplicated(request, options) {
3700
- await this._automergeHost.waitUntilHeadsReplicated(request.heads);
3701
- }
3702
- async reIndexHeads(request, options) {
3703
- await this._automergeHost.reIndexHeads(request.documentIds ?? []);
3704
- }
3705
- async updateIndexes() {
3706
- await this._updateIndexes();
3707
- }
3708
- async getSpaceSyncState(request, options) {
3709
- (0, import_invariant7.invariant)(import_keys7.SpaceId.isValid(request.spaceId), void 0, {
3710
- F: __dxlog_file16,
3711
- L: 127,
3712
- S: this,
3713
- A: [
3714
- "SpaceId.isValid(request.spaceId)",
3715
- ""
3716
- ]
3717
- });
3718
- const collectionId = deriveCollectionIdFromSpaceId(request.spaceId);
3719
- const state = await this._automergeHost.getCollectionSyncState(collectionId);
3720
- return {
3721
- peers: state.peers.map((peer) => ({
3722
- peerId: peer.peerId,
3723
- documentsToReconcile: peer.differentDocuments
3724
- }))
3725
- };
3726
- }
3727
- };
3728
- function _ts_decorate9(decorators, target, key, desc) {
3729
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3730
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3731
- r = Reflect.decorate(decorators, target, key, desc);
3732
- else
3733
- for (var i = decorators.length - 1; i >= 0; i--)
3734
- if (d = decorators[i])
3735
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3736
- return c > 3 && r && Object.defineProperty(target, key, r), r;
3737
- }
3738
- var __dxlog_file17 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space-manager.ts";
3739
- var SpaceManager = class {
3740
- constructor({ feedStore, networkManager, metadataStore, snapshotStore, blobStore, disableP2pReplication }) {
3741
- this._spaces = new import_util6.ComplexMap(import_keys6.PublicKey.hash);
3742
- this._instanceId = import_keys6.PublicKey.random().toHex();
3743
- this._feedStore = feedStore;
3744
- this._networkManager = networkManager;
3745
- this._metadataStore = metadataStore;
3746
- this._snapshotStore = snapshotStore;
3747
- this._blobStore = blobStore;
3748
- this._disableP2pReplication = disableP2pReplication ?? false;
3749
- }
3750
- // TODO(burdon): Remove.
3751
- get spaces() {
3752
- return this._spaces;
3753
- }
3754
- async open() {
3755
- }
3756
- async close() {
3757
- await Promise.all([
3758
- ...this._spaces.values()
3759
- ].map((space) => space.close()));
3760
- }
3761
- async constructSpace({ metadata, swarmIdentity, onAuthorizedConnection, onAuthFailure, onDelegatedInvitationStatusChange, onMemberRolesChanged, memberKey }) {
3762
- import_log9.log.trace("dxos.echo.space-manager.construct-space", import_protocols6.trace.begin({
3763
- id: this._instanceId
3764
- }), {
3765
- F: __dxlog_file17,
3766
- L: 114,
3767
- S: this,
3768
- C: (f, a) => f(...a)
3769
- });
3770
- (0, import_log9.log)("constructing space...", {
3771
- spaceKey: metadata.genesisFeedKey
3772
- }, {
3773
- F: __dxlog_file17,
3774
- L: 115,
3775
- S: this,
3776
- C: (f, a) => f(...a)
3777
- });
3778
- const genesisFeed = await this._feedStore.openFeed(metadata.genesisFeedKey ?? (0, import_debug3.failUndefined)());
3779
- const spaceKey = metadata.key;
3780
- const spaceId = await createIdFromSpaceKey(spaceKey);
3781
- const protocol = new SpaceProtocol({
3782
- topic: spaceKey,
3783
- swarmIdentity,
3784
- networkManager: this._networkManager,
3785
- onSessionAuth: onAuthorizedConnection,
3786
- onAuthFailure,
3787
- blobStore: this._blobStore,
3788
- disableP2pReplication: this._disableP2pReplication
3789
- });
3790
- const snapshotManager = new SnapshotManager(this._snapshotStore, this._blobStore, protocol.blobSync);
3791
- const space = new Space({
3792
- id: spaceId,
3793
- spaceKey,
3794
- protocol,
3795
- genesisFeed,
3796
- feedProvider: (feedKey, opts) => this._feedStore.openFeed(feedKey, opts),
3797
- metadataStore: this._metadataStore,
3798
- snapshotManager,
3799
- memberKey,
3800
- onDelegatedInvitationStatusChange,
3801
- onMemberRolesChanged
3802
- });
3803
- this._spaces.set(space.key, space);
3804
- import_log9.log.trace("dxos.echo.space-manager.construct-space", import_protocols6.trace.end({
3805
- id: this._instanceId
3806
- }), {
3807
- F: __dxlog_file17,
3808
- L: 147,
3809
- S: this,
3810
- C: (f, a) => f(...a)
3811
- });
3812
- return space;
3813
- }
3814
- async requestSpaceAdmissionCredential(params) {
3815
- const traceKey = "dxos.echo.space-manager.request-space-admission";
3816
- import_log9.log.trace(traceKey, import_protocols6.trace.begin({
3817
- id: this._instanceId
3818
- }), {
3819
- F: __dxlog_file17,
3820
- L: 153,
3821
- S: this,
3822
- C: (f, a) => f(...a)
3823
- });
3824
- (0, import_log9.log)("requesting space admission credential...", {
3825
- spaceKey: params.spaceKey
3826
- }, {
3827
- F: __dxlog_file17,
3828
- L: 154,
3829
- S: this,
3830
- C: (f, a) => f(...a)
3831
- });
3832
- const onCredentialResolved = new import_async9.Trigger();
3833
- const protocol = new SpaceProtocol({
3834
- topic: params.spaceKey,
3835
- swarmIdentity: params.swarmIdentity,
3836
- networkManager: this._networkManager,
3837
- onSessionAuth: (session) => {
3838
- session.addExtension("dxos.mesh.teleport.admission-discovery", new CredentialRetrieverExtension({
3839
- spaceKey: params.spaceKey,
3840
- memberKey: params.identityKey
3841
- }, onCredentialResolved));
3842
- },
3843
- onAuthFailure: (session) => session.close(),
3844
- blobStore: this._blobStore,
3845
- disableP2pReplication: this._disableP2pReplication
3846
- });
3847
- try {
3848
- await protocol.start();
3849
- const credential = await onCredentialResolved.wait({
3850
- timeout: params.timeout
3851
- });
3852
- import_log9.log.trace(traceKey, import_protocols6.trace.end({
3853
- id: this._instanceId
3854
- }), {
3855
- F: __dxlog_file17,
3856
- L: 178,
3857
- S: this,
3858
- C: (f, a) => f(...a)
3859
- });
3860
- return credential;
3861
- } catch (err) {
3862
- import_log9.log.trace(traceKey, import_protocols6.trace.error({
3863
- id: this._instanceId,
3864
- error: err
3865
- }), {
3866
- F: __dxlog_file17,
3867
- L: 181,
3868
- S: this,
3869
- C: (f, a) => f(...a)
3870
- });
3871
- throw err;
3872
- } finally {
3873
- await protocol.stop();
3874
- }
3875
- }
3876
- };
3877
- _ts_decorate9([
3878
- import_async9.synchronized
3879
- ], SpaceManager.prototype, "open", null);
3880
- _ts_decorate9([
3881
- import_async9.synchronized
3882
- ], SpaceManager.prototype, "close", null);
3883
- SpaceManager = _ts_decorate9([
3884
- (0, import_async9.trackLeaks)("open", "close")
3885
- ], SpaceManager);
3886
- function _ts_decorate10(decorators, target, key, desc) {
3887
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3888
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3889
- r = Reflect.decorate(decorators, target, key, desc);
3890
- else
3891
- for (var i = decorators.length - 1; i >= 0; i--)
3892
- if (d = decorators[i])
3893
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3894
- return c > 3 && r && Object.defineProperty(target, key, r), r;
3895
- }
3896
- var __dxlog_file18 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/metadata/metadata-store.ts";
3897
- var EXPIRED_INVITATION_CLEANUP_INTERVAL = 60 * 60 * 1e3;
3898
- var emptyEchoMetadata = () => ({
3899
- version: import_protocols9.STORAGE_VERSION,
3900
- spaces: [],
3901
- created: /* @__PURE__ */ new Date(),
3902
- updated: /* @__PURE__ */ new Date()
3903
- });
3904
- var emptyLargeSpaceMetadata = () => ({});
3905
- var EchoMetadata = import_protocols9.schema.getCodecForType("dxos.echo.metadata.EchoMetadata");
3906
- var LargeSpaceMetadata = import_protocols9.schema.getCodecForType("dxos.echo.metadata.LargeSpaceMetadata");
3907
- var MetadataStore = class {
3908
- constructor(directory) {
3909
- this._metadata = emptyEchoMetadata();
3910
- this._spaceLargeMetadata = new import_util10.ComplexMap(import_keys11.PublicKey.hash);
3911
- this._metadataFile = void 0;
3912
- this.update = new import_async12.Event();
3913
- this._invitationCleanupCtx = new import_context13.Context(void 0, {
3914
- F: __dxlog_file18,
3915
- L: 53
3916
- });
3917
- this._directory = directory;
3918
- }
3919
- get metadata() {
3920
- return this._metadata;
3921
- }
3922
- get version() {
3923
- return this._metadata.version ?? 0;
3924
- }
3925
- /**
3926
- * Returns a list of currently saved spaces. The list and objects in it can be modified addSpace and
3927
- * addSpaceFeed functions.
3928
- */
3929
- get spaces() {
3930
- return this._metadata.spaces ?? [];
3931
- }
3932
- async _readFile(file, codec2) {
3933
- try {
3934
- const { size: fileLength } = await file.stat();
3935
- if (fileLength < 8) {
3936
- return;
3937
- }
3938
- const dataSize = fromBytesInt32(await file.read(0, 4));
3939
- const checksum = fromBytesInt32(await file.read(4, 4));
3940
- (0, import_log15.log)("loaded", {
3941
- size: dataSize,
3942
- checksum,
3943
- name: file.filename
3944
- }, {
3945
- F: __dxlog_file18,
3946
- L: 89,
3947
- S: this,
3948
- C: (f, a) => f(...a)
3949
- });
3950
- if (fileLength < dataSize + 8) {
3951
- throw new import_protocols9.DataCorruptionError("Metadata size is smaller than expected.", {
3952
- fileLength,
3953
- dataSize
3954
- });
3955
- }
3956
- const data = await file.read(8, dataSize);
3957
- const calculatedChecksum = import_crc_32.default.buf(data);
3958
- if (calculatedChecksum !== checksum) {
3959
- throw new import_protocols9.DataCorruptionError("Metadata checksum is invalid.");
3960
- }
3961
- return codec2.decode(data);
3962
- } finally {
3963
- await file.close();
3964
- }
3965
- }
3966
- /**
3967
- * @internal
3968
- */
3969
- async _writeFile(file, codec2, data) {
3970
- const encoded = (0, import_util10.arrayToBuffer)(codec2.encode(data));
3971
- const checksum = import_crc_32.default.buf(encoded);
3972
- const result = Buffer.alloc(8 + encoded.length);
3973
- result.writeInt32LE(encoded.length, 0);
3974
- result.writeInt32LE(checksum, 4);
3975
- encoded.copy(result, 8);
3976
- await file.write(0, result);
3977
- (0, import_log15.log)("saved", {
3978
- size: encoded.length,
3979
- checksum
3980
- }, {
3981
- F: __dxlog_file18,
3982
- L: 124,
3983
- S: this,
3984
- C: (f, a) => f(...a)
3985
- });
3986
- }
3987
- async close() {
3988
- await this._invitationCleanupCtx.dispose();
3989
- await this.flush();
3990
- await this._metadataFile?.close();
3991
- this._metadataFile = void 0;
3992
- this._metadata = emptyEchoMetadata();
3993
- this._spaceLargeMetadata.clear();
3994
- }
3995
- /**
3996
- * Loads metadata from persistent storage.
3997
- */
3998
- async load() {
3999
- if (!this._metadataFile || this._metadataFile.closed) {
4000
- this._metadataFile = this._directory.getOrCreateFile("EchoMetadata");
4001
- }
4002
- try {
4003
- const metadata = await this._readFile(this._metadataFile, EchoMetadata);
4004
- if (metadata) {
4005
- this._metadata = metadata;
4006
- }
4007
- this._metadata.spaces?.forEach((space) => {
4008
- space.state ??= import_services.SpaceState.SPACE_ACTIVE;
4009
- });
4010
- } catch (err) {
4011
- import_log15.log.error("failed to load metadata", {
4012
- err
4013
- }, {
4014
- F: __dxlog_file18,
4015
- L: 156,
4016
- S: this,
4017
- C: (f, a) => f(...a)
4018
- });
4019
- this._metadata = emptyEchoMetadata();
4020
- }
4021
- await (0, import_util10.forEachAsync)([
4022
- this._metadata.identity?.haloSpace.key,
4023
- ...this._metadata.spaces?.map((space) => space.key) ?? []
4024
- ].filter(import_util10.isNotNullOrUndefined), async (key) => {
4025
- try {
4026
- await this._loadSpaceLargeMetadata(key);
4027
- } catch (err) {
4028
- import_log15.log.error("failed to load space large metadata", {
4029
- err
4030
- }, {
4031
- F: __dxlog_file18,
4032
- L: 168,
4033
- S: this,
4034
- C: (f, a) => f(...a)
4035
- });
4036
- }
4037
- });
4038
- (0, import_async12.scheduleTaskInterval)(this._invitationCleanupCtx, async () => {
4039
- for (const invitation of this._metadata.invitations ?? []) {
4040
- if (hasInvitationExpired(invitation) || isLegacyInvitationFormat(invitation)) {
4041
- await this.removeInvitation(invitation.invitationId);
4042
- }
4043
- }
4044
- }, EXPIRED_INVITATION_CLEANUP_INTERVAL);
4045
- }
4046
- async _save() {
4047
- const data = {
4048
- ...this._metadata,
4049
- version: import_protocols9.STORAGE_VERSION,
4050
- created: this._metadata.created ?? /* @__PURE__ */ new Date(),
4051
- updated: /* @__PURE__ */ new Date()
4052
- };
4053
- this.update.emit(data);
4054
- const file = this._directory.getOrCreateFile("EchoMetadata");
4055
- await this._writeFile(file, EchoMetadata, data);
4056
- }
4057
- async _loadSpaceLargeMetadata(key) {
4058
- const file = this._directory.getOrCreateFile(`space_${key.toHex()}_large`);
4059
- try {
4060
- const metadata = await this._readFile(file, LargeSpaceMetadata);
4061
- if (metadata) {
4062
- this._spaceLargeMetadata.set(key, metadata);
4063
- }
4064
- } catch (err) {
4065
- import_log15.log.error("failed to load space large metadata", {
4066
- err
4067
- }, {
4068
- F: __dxlog_file18,
4069
- L: 210,
4070
- S: this,
4071
- C: (f, a) => f(...a)
4072
- });
4073
- }
4074
- }
4075
- async _saveSpaceLargeMetadata(key) {
4076
- const data = this._getLargeSpaceMetadata(key);
4077
- const file = this._directory.getOrCreateFile(`space_${key.toHex()}_large`);
4078
- await this._writeFile(file, LargeSpaceMetadata, data);
4079
- }
4080
- async flush() {
4081
- await this._directory.flush();
4082
- }
4083
- _getSpace(spaceKey) {
4084
- if (this._metadata.identity?.haloSpace.key.equals(spaceKey)) {
4085
- return this._metadata.identity.haloSpace;
4086
- }
4087
- const space = this.spaces.find((space2) => space2.key === spaceKey);
4088
- (0, import_invariant13.invariant)(space, "Space not found", {
4089
- F: __dxlog_file18,
4090
- L: 232,
4091
- S: this,
4092
- A: [
4093
- "space",
4094
- "'Space not found'"
4095
- ]
4096
- });
4097
- return space;
4098
- }
4099
- _getLargeSpaceMetadata(key) {
4100
- let entry = this._spaceLargeMetadata.get(key);
4101
- if (entry) {
4102
- return entry;
4103
- }
4104
- entry = emptyLargeSpaceMetadata();
4105
- this._spaceLargeMetadata.set(key, entry);
4106
- return entry;
4107
- }
4108
- /**
4109
- * Clears storage - doesn't work for now.
4110
- */
4111
- async clear() {
4112
- (0, import_log15.log)("clearing all metadata", void 0, {
4113
- F: __dxlog_file18,
4114
- L: 251,
4115
- S: this,
4116
- C: (f, a) => f(...a)
4117
- });
4118
- await this._directory.delete();
4119
- this._metadata = emptyEchoMetadata();
4120
- }
4121
- getIdentityRecord() {
4122
- return this._metadata.identity;
4123
- }
4124
- async setIdentityRecord(record) {
4125
- (0, import_invariant13.invariant)(!this._metadata.identity, "Cannot overwrite existing identity in metadata", {
4126
- F: __dxlog_file18,
4127
- L: 261,
4128
- S: this,
4129
- A: [
4130
- "!this._metadata.identity",
4131
- "'Cannot overwrite existing identity in metadata'"
4132
- ]
4133
- });
4134
- this._metadata.identity = record;
4135
- await this._save();
4136
- await this.flush();
4137
- }
4138
- getInvitations() {
4139
- return this._metadata.invitations ?? [];
4140
- }
4141
- async addInvitation(invitation) {
4142
- if (this._metadata.invitations?.find((i) => i.invitationId === invitation.invitationId)) {
4143
- return;
4144
- }
4145
- (this._metadata.invitations ??= []).push(invitation);
4146
- await this._save();
4147
- await this.flush();
4148
- }
4149
- async removeInvitation(invitationId) {
4150
- this._metadata.invitations = (this._metadata.invitations ?? []).filter((i) => i.invitationId !== invitationId);
4151
- await this._save();
4152
- await this.flush();
4153
- }
4154
- async addSpace(record) {
4155
- (0, import_invariant13.invariant)(!(this._metadata.spaces ?? []).find((space) => space.key === record.key), "Cannot overwrite existing space in metadata", {
4156
- F: __dxlog_file18,
4157
- L: 289,
4158
- S: this,
4159
- A: [
4160
- "!(this._metadata.spaces ?? []).find((space) => space.key === record.key)",
4161
- "'Cannot overwrite existing space in metadata'"
4162
- ]
4163
- });
4164
- (this._metadata.spaces ??= []).push(record);
4165
- await this._save();
4166
- await this.flush();
4167
- }
4168
- async setSpaceDataLatestTimeframe(spaceKey, timeframe) {
4169
- this._getSpace(spaceKey).dataTimeframe = timeframe;
4170
- await this._save();
4171
- }
4172
- async setSpaceControlLatestTimeframe(spaceKey, timeframe) {
4173
- this._getSpace(spaceKey).controlTimeframe = timeframe;
4174
- await this._save();
4175
- await this.flush();
4176
- }
4177
- async setCache(spaceKey, cache) {
4178
- this._getSpace(spaceKey).cache = cache;
4179
- await this._save();
4180
- }
4181
- async setWritableFeedKeys(spaceKey, controlFeedKey, dataFeedKey) {
4182
- const space = this._getSpace(spaceKey);
4183
- space.controlFeedKey = controlFeedKey;
4184
- space.dataFeedKey = dataFeedKey;
4185
- await this._save();
4186
- await this.flush();
4187
- }
4188
- async setSpaceState(spaceKey, state) {
4189
- this._getSpace(spaceKey).state = state;
4190
- await this._save();
4191
- await this.flush();
4192
- }
4193
- getSpaceControlPipelineSnapshot(spaceKey) {
4194
- return this._getLargeSpaceMetadata(spaceKey).controlPipelineSnapshot;
4195
- }
4196
- async setSpaceControlPipelineSnapshot(spaceKey, snapshot) {
4197
- this._getLargeSpaceMetadata(spaceKey).controlPipelineSnapshot = snapshot;
4198
- await this._saveSpaceLargeMetadata(spaceKey);
4199
- await this.flush();
4200
- }
4201
- };
4202
- _ts_decorate10([
4203
- import_async12.synchronized
4204
- ], MetadataStore.prototype, "load", null);
4205
- _ts_decorate10([
4206
- import_async12.synchronized
4207
- ], MetadataStore.prototype, "_save", null);
4208
- _ts_decorate10([
4209
- import_async12.synchronized
4210
- ], MetadataStore.prototype, "_saveSpaceLargeMetadata", null);
4211
- var fromBytesInt32 = (buf) => buf.readInt32LE(0);
4212
- var hasInvitationExpired = (invitation) => {
4213
- return Boolean(invitation.created && invitation.lifetime && invitation.lifetime !== 0 && invitation.created.getTime() + invitation.lifetime * 1e3 < Date.now());
4214
- };
4215
- var isLegacyInvitationFormat = (invitation) => {
4216
- return invitation.type === import_services.Invitation.Type.MULTIUSE;
4217
- };
4218
- // Annotate the CommonJS export names for ESM import in node:
4219
- 0 && (module.exports = {
4220
- AuthExtension,
4221
- AuthStatus,
4222
- AutomergeHost,
4223
- CredentialRetrieverExtension,
4224
- CredentialServerExtension,
4225
- DataServiceImpl,
4226
- DocumentsSynchronizer,
4227
- EchoDataMonitor,
4228
- LevelDBStorageAdapter,
4229
- MOCK_AUTH_PROVIDER,
4230
- MOCK_AUTH_VERIFIER,
4231
- MeshEchoReplicator,
4232
- MetadataStore,
4233
- Pipeline,
4234
- SnapshotManager,
4235
- SnapshotStore,
4236
- Space,
4237
- SpaceManager,
4238
- SpaceProtocol,
4239
- SpaceProtocolSession,
4240
- TimeframeClock,
4241
- codec,
4242
- createIdFromSpaceKey,
4243
- createMappedFeedWriter,
4244
- deriveCollectionIdFromSpaceId,
4245
- diffCollectionState,
4246
- encodingOptions,
4247
- getSpaceIdFromCollectionId,
4248
- getSpaceKeyFromDoc,
4249
- hasInvitationExpired,
4250
- mapFeedIndexesToTimeframe,
4251
- mapTimeframeToFeedIndexes,
4252
- startAfter,
4253
- valueEncoding
4254
- });
4255
- //# sourceMappingURL=chunk-IYTGTZ7D.cjs.map