@dxos/echo-pipeline 0.1.41 → 0.1.45-next.45667d4
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.
- package/dist/lib/browser/{chunk-4YAT2XJW.mjs → chunk-2NGLSBL4.mjs} +1128 -1017
- package/dist/lib/browser/chunk-2NGLSBL4.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -3
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +72 -48
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/index.cjs +1048 -938
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +735 -540
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/dbhost/database-host.d.ts +2 -4
- package/dist/types/src/dbhost/database-host.d.ts.map +1 -1
- package/dist/types/src/dbhost/snapshot-store.d.ts +2 -0
- package/dist/types/src/dbhost/snapshot-store.d.ts.map +1 -1
- package/dist/types/src/metadata/metadata-store.d.ts +3 -2
- package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
- package/dist/types/src/pipeline/pipeline.d.ts +27 -11
- package/dist/types/src/pipeline/pipeline.d.ts.map +1 -1
- package/dist/types/src/pipeline/timeframe-clock.d.ts +1 -0
- package/dist/types/src/pipeline/timeframe-clock.d.ts.map +1 -1
- package/dist/types/src/space/auth.d.ts +4 -4
- package/dist/types/src/space/auth.d.ts.map +1 -1
- package/dist/types/src/space/control-pipeline.d.ts +2 -4
- package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
- package/dist/types/src/space/data-pipeline.d.ts +19 -10
- package/dist/types/src/space/data-pipeline.d.ts.map +1 -1
- package/dist/types/src/space/index.d.ts +0 -1
- package/dist/types/src/space/index.d.ts.map +1 -1
- package/dist/types/src/space/space-manager.d.ts +14 -14
- package/dist/types/src/space/space-manager.d.ts.map +1 -1
- package/dist/types/src/space/space-protocol.d.ts +2 -2
- package/dist/types/src/space/space-protocol.d.ts.map +1 -1
- package/dist/types/src/space/space.d.ts +20 -7
- package/dist/types/src/space/space.d.ts.map +1 -1
- package/dist/types/src/testing/database-test-rig.d.ts.map +1 -1
- package/dist/types/src/testing/test-agent-builder.d.ts +15 -5
- package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
- package/package.json +30 -30
- package/src/common/feeds.ts +2 -2
- package/src/dbhost/data-service-host.ts +10 -10
- package/src/dbhost/data-service.ts +1 -1
- package/src/dbhost/database-host.ts +1 -9
- package/src/dbhost/snapshot-store.test.ts +2 -2
- package/src/dbhost/snapshot-store.ts +16 -1
- package/src/metadata/metadata-store.ts +14 -16
- package/src/pipeline/message-selector.ts +1 -1
- package/src/pipeline/pipeline.test.ts +68 -44
- package/src/pipeline/pipeline.ts +118 -35
- package/src/pipeline/timeframe-clock.ts +8 -2
- package/src/space/auth.ts +6 -6
- package/src/space/control-pipeline.test.ts +19 -20
- package/src/space/control-pipeline.ts +3 -5
- package/src/space/data-pipeline.ts +131 -69
- package/src/space/index.ts +0 -1
- package/src/space/replication.browser.test.ts +8 -8
- package/src/space/space-manager.browser.test.ts +3 -3
- package/src/space/space-manager.ts +25 -20
- package/src/space/space-protocol.browser.test.ts +1 -1
- package/src/space/space-protocol.test.ts +6 -6
- package/src/space/space-protocol.ts +7 -7
- package/src/space/space.test.ts +137 -48
- package/src/space/space.ts +82 -40
- package/src/testing/database-test-rig.ts +25 -24
- package/src/testing/test-agent-builder.ts +88 -49
- package/src/testing/test-feed-builder.ts +1 -1
- package/src/testing/util.ts +15 -15
- package/src/tests/database-unit.test.ts +4 -4
- package/src/tests/database.test.ts +1 -1
- package/dist/lib/browser/chunk-4YAT2XJW.mjs.map +0 -7
- package/dist/types/src/space/genesis.d.ts +0 -5
- package/dist/types/src/space/genesis.d.ts.map +0 -1
- package/src/space/genesis.ts +0 -69
|
@@ -116,13 +116,18 @@ var MetadataStore = class {
|
|
|
116
116
|
await file.close();
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
+
_getSpace(spaceKey) {
|
|
120
|
+
const space = this.spaces.find((space2) => space2.key === spaceKey);
|
|
121
|
+
assert(space, "Space not found");
|
|
122
|
+
return space;
|
|
123
|
+
}
|
|
119
124
|
/**
|
|
120
125
|
* Clears storage - doesn't work for now.
|
|
121
126
|
*/
|
|
122
127
|
async clear() {
|
|
123
128
|
log("clearing all metadata", {}, {
|
|
124
129
|
file: "metadata-store.ts",
|
|
125
|
-
line:
|
|
130
|
+
line: 132,
|
|
126
131
|
scope: this,
|
|
127
132
|
callSite: (f, a) => f(...a)
|
|
128
133
|
});
|
|
@@ -143,20 +148,15 @@ var MetadataStore = class {
|
|
|
143
148
|
await this._save();
|
|
144
149
|
}
|
|
145
150
|
async setSpaceLatestTimeframe(spaceKey, timeframe) {
|
|
146
|
-
|
|
147
|
-
assert(space, "Space not found");
|
|
148
|
-
space.dataTimeframe = timeframe;
|
|
151
|
+
this._getSpace(spaceKey).dataTimeframe = timeframe;
|
|
149
152
|
await this._save();
|
|
150
153
|
}
|
|
151
|
-
async
|
|
152
|
-
|
|
153
|
-
assert(space, "Space not found");
|
|
154
|
-
space.snapshot = snapshot;
|
|
154
|
+
async setCache(spaceKey, cache) {
|
|
155
|
+
this._getSpace(spaceKey).cache = cache;
|
|
155
156
|
await this._save();
|
|
156
157
|
}
|
|
157
158
|
async setWritableFeedKeys(spaceKey, controlFeedKey, dataFeedKey) {
|
|
158
|
-
const space = this.
|
|
159
|
-
assert(space, "Space not found");
|
|
159
|
+
const space = this._getSpace(spaceKey);
|
|
160
160
|
space.controlFeedKey = controlFeedKey;
|
|
161
161
|
space.dataFeedKey = dataFeedKey;
|
|
162
162
|
await this._save();
|
|
@@ -233,6 +233,11 @@ var TimeframeClock = class {
|
|
|
233
233
|
get pendingTimeframe() {
|
|
234
234
|
return this._pendingTimeframe;
|
|
235
235
|
}
|
|
236
|
+
setTimeframe(timeframe) {
|
|
237
|
+
this._timeframe = timeframe;
|
|
238
|
+
this._pendingTimeframe = timeframe;
|
|
239
|
+
this.update.emit(this._timeframe);
|
|
240
|
+
}
|
|
236
241
|
updatePendingTimeframe(key, seq) {
|
|
237
242
|
this._pendingTimeframe = Timeframe.merge(this._pendingTimeframe, new Timeframe([
|
|
238
243
|
[
|
|
@@ -250,12 +255,12 @@ var TimeframeClock = class {
|
|
|
250
255
|
return !gaps.isEmpty();
|
|
251
256
|
}
|
|
252
257
|
async waitUntilReached(target) {
|
|
253
|
-
log2
|
|
258
|
+
log2("waitUntilReached", {
|
|
254
259
|
target,
|
|
255
260
|
current: this._timeframe
|
|
256
261
|
}, {
|
|
257
262
|
file: "timeframe-clock.ts",
|
|
258
|
-
line:
|
|
263
|
+
line: 73,
|
|
259
264
|
scope: this,
|
|
260
265
|
callSite: (f, a) => f(...a)
|
|
261
266
|
});
|
|
@@ -266,7 +271,7 @@ var TimeframeClock = class {
|
|
|
266
271
|
deps: Timeframe.dependencies(target, this._timeframe)
|
|
267
272
|
}, {
|
|
268
273
|
file: "timeframe-clock.ts",
|
|
269
|
-
line:
|
|
274
|
+
line: 75,
|
|
270
275
|
scope: this,
|
|
271
276
|
callSite: (f, a) => f(...a)
|
|
272
277
|
});
|
|
@@ -280,12 +285,14 @@ __decorate2([
|
|
|
280
285
|
|
|
281
286
|
// packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
|
|
282
287
|
import assert4 from "@dxos/node-std/assert";
|
|
283
|
-
import { sleep, synchronized as synchronized2, Trigger } from "@dxos/async";
|
|
288
|
+
import { Event as Event2, sleep, synchronized as synchronized2, Trigger } from "@dxos/async";
|
|
284
289
|
import { Context, rejectOnDispose } from "@dxos/context";
|
|
290
|
+
import { failUndefined } from "@dxos/debug";
|
|
285
291
|
import { FeedSetIterator } from "@dxos/feed-store";
|
|
286
292
|
import { PublicKey } from "@dxos/keys";
|
|
287
293
|
import { log as log4 } from "@dxos/log";
|
|
288
294
|
import { Timeframe as Timeframe2 } from "@dxos/timeframe";
|
|
295
|
+
import { ComplexMap } from "@dxos/util";
|
|
289
296
|
|
|
290
297
|
// packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts
|
|
291
298
|
import debug from "debug";
|
|
@@ -317,10 +324,11 @@ var __decorate3 = function(decorators, target, key, desc) {
|
|
|
317
324
|
};
|
|
318
325
|
var PipelineState = class {
|
|
319
326
|
// prettier-ignore
|
|
320
|
-
constructor(
|
|
321
|
-
this.
|
|
327
|
+
constructor(_feeds, _timeframeClock) {
|
|
328
|
+
this._feeds = _feeds;
|
|
322
329
|
this._timeframeClock = _timeframeClock;
|
|
323
330
|
this.timeframeUpdate = this._timeframeClock.update;
|
|
331
|
+
this.stalled = new Event2();
|
|
324
332
|
}
|
|
325
333
|
/**
|
|
326
334
|
* Latest theoretical timeframe based on the last mutation in each feed.
|
|
@@ -328,7 +336,7 @@ var PipelineState = class {
|
|
|
328
336
|
*/
|
|
329
337
|
// TODO(dmaretskyi): Rename `totalTimeframe`? or `lastTimeframe`.
|
|
330
338
|
get endTimeframe() {
|
|
331
|
-
return mapFeedIndexesToTimeframe(this.
|
|
339
|
+
return mapFeedIndexesToTimeframe(Array.from(this._feeds.values()).filter((feed) => feed.length > 0).map((feed) => ({
|
|
332
340
|
feedKey: feed.key,
|
|
333
341
|
index: feed.length - 1
|
|
334
342
|
})));
|
|
@@ -343,7 +351,7 @@ var PipelineState = class {
|
|
|
343
351
|
return this._targetTimeframe ? this._targetTimeframe : new Timeframe2();
|
|
344
352
|
}
|
|
345
353
|
get feeds() {
|
|
346
|
-
return this.
|
|
354
|
+
return Array.from(this._feeds.values());
|
|
347
355
|
}
|
|
348
356
|
async waitUntilTimeframe(target) {
|
|
349
357
|
await this._timeframeClock.waitUntilReached(target);
|
|
@@ -366,7 +374,7 @@ var PipelineState = class {
|
|
|
366
374
|
target: this.targetTimeframe
|
|
367
375
|
}, {
|
|
368
376
|
file: "pipeline.ts",
|
|
369
|
-
line:
|
|
377
|
+
line: 109,
|
|
370
378
|
scope: this,
|
|
371
379
|
callSite: (f, a) => f(...a)
|
|
372
380
|
});
|
|
@@ -375,7 +383,7 @@ var PipelineState = class {
|
|
|
375
383
|
return Timeframe2.dependencies(this.targetTimeframe, this.timeframe).isEmpty();
|
|
376
384
|
}),
|
|
377
385
|
...breakOnStall ? [
|
|
378
|
-
this.
|
|
386
|
+
this.stalled.discardParameter().waitForCount(1)
|
|
379
387
|
] : []
|
|
380
388
|
]);
|
|
381
389
|
let done = false;
|
|
@@ -396,7 +404,7 @@ var PipelineState = class {
|
|
|
396
404
|
dependencies: Timeframe2.dependencies(this.targetTimeframe, this.timeframe)
|
|
397
405
|
}, {
|
|
398
406
|
file: "pipeline.ts",
|
|
399
|
-
line:
|
|
407
|
+
line: 135,
|
|
400
408
|
scope: this,
|
|
401
409
|
callSite: (f, a) => f(...a)
|
|
402
410
|
});
|
|
@@ -408,25 +416,18 @@ var PipelineState = class {
|
|
|
408
416
|
}
|
|
409
417
|
};
|
|
410
418
|
var Pipeline = class {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
this.
|
|
414
|
-
|
|
415
|
-
this.
|
|
416
|
-
|
|
417
|
-
stallTimeout: 1e3
|
|
418
|
-
});
|
|
419
|
-
this._state = new PipelineState(this._feedSetIterator, this._timeframeClock);
|
|
419
|
+
constructor() {
|
|
420
|
+
this._timeframeClock = new TimeframeClock(new Timeframe2());
|
|
421
|
+
this._feeds = new ComplexMap(PublicKey.hash);
|
|
422
|
+
// External state accessor.
|
|
423
|
+
this._state = new PipelineState(this._feeds, this._timeframeClock);
|
|
424
|
+
// Waits for the message consumer to process the message and yield control back to the pipeline.
|
|
420
425
|
this._processingTrigger = new Trigger().wake();
|
|
426
|
+
this._pauseTrigger = new Trigger().wake();
|
|
427
|
+
this._isStopping = false;
|
|
428
|
+
this._isStarted = false;
|
|
421
429
|
this._isOpen = false;
|
|
422
|
-
this.
|
|
423
|
-
log4.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, {}, {
|
|
424
|
-
file: "pipeline.ts",
|
|
425
|
-
line: 207,
|
|
426
|
-
scope: this,
|
|
427
|
-
callSite: (f, a) => f(...a)
|
|
428
|
-
});
|
|
429
|
-
});
|
|
430
|
+
this._isPaused = false;
|
|
430
431
|
}
|
|
431
432
|
get state() {
|
|
432
433
|
return this._state;
|
|
@@ -441,10 +442,13 @@ var Pipeline = class {
|
|
|
441
442
|
// NOTE: This cannot be synchronized with `stop` because stop waits for the mutation processing to complete,
|
|
442
443
|
// which might be opening feeds during the mutation processing, which w
|
|
443
444
|
async addFeed(feed) {
|
|
444
|
-
|
|
445
|
+
this._feeds.set(feed.key, feed);
|
|
446
|
+
if (this._feedSetIterator) {
|
|
447
|
+
await this._feedSetIterator.addFeed(feed);
|
|
448
|
+
}
|
|
445
449
|
}
|
|
446
450
|
hasFeed(feedKey) {
|
|
447
|
-
return this.
|
|
451
|
+
return this._feeds.has(feedKey);
|
|
448
452
|
}
|
|
449
453
|
setWriteFeed(feed) {
|
|
450
454
|
assert4(!this._writer, "Writer already set.");
|
|
@@ -457,33 +461,68 @@ var Pipeline = class {
|
|
|
457
461
|
async start() {
|
|
458
462
|
log4("starting...", {}, {
|
|
459
463
|
file: "pipeline.ts",
|
|
460
|
-
line:
|
|
464
|
+
line: 254,
|
|
461
465
|
scope: this,
|
|
462
466
|
callSite: (f, a) => f(...a)
|
|
463
467
|
});
|
|
468
|
+
await this._initIterator();
|
|
464
469
|
await this._feedSetIterator.open();
|
|
465
470
|
log4("started", {}, {
|
|
466
471
|
file: "pipeline.ts",
|
|
467
|
-
line:
|
|
472
|
+
line: 257,
|
|
468
473
|
scope: this,
|
|
469
474
|
callSite: (f, a) => f(...a)
|
|
470
475
|
});
|
|
476
|
+
this._isStarted = true;
|
|
471
477
|
}
|
|
472
478
|
async stop() {
|
|
479
|
+
var _a;
|
|
473
480
|
log4("stopping...", {}, {
|
|
474
481
|
file: "pipeline.ts",
|
|
475
|
-
line:
|
|
482
|
+
line: 263,
|
|
476
483
|
scope: this,
|
|
477
484
|
callSite: (f, a) => f(...a)
|
|
478
485
|
});
|
|
479
|
-
|
|
486
|
+
this._isStopping = true;
|
|
487
|
+
await ((_a = this._feedSetIterator) == null ? void 0 : _a.close());
|
|
480
488
|
await this._processingTrigger.wait();
|
|
481
489
|
log4("stopped", {}, {
|
|
482
490
|
file: "pipeline.ts",
|
|
483
|
-
line:
|
|
491
|
+
line: 267,
|
|
484
492
|
scope: this,
|
|
485
493
|
callSite: (f, a) => f(...a)
|
|
486
494
|
});
|
|
495
|
+
this._isStarted = false;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* @param timeframe Timeframe of already processed messages. The pipeline will start processing messages AFTER this timeframe.
|
|
499
|
+
*/
|
|
500
|
+
async setCursor(timeframe) {
|
|
501
|
+
assert4(!this._isStarted || this._isPaused, "Invalid state.");
|
|
502
|
+
this._timeframeClock.setTimeframe(timeframe);
|
|
503
|
+
if (this._feedSetIterator) {
|
|
504
|
+
await this._feedSetIterator.close();
|
|
505
|
+
await this._initIterator();
|
|
506
|
+
await this._feedSetIterator.open();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Calling pause while processing will cause a deadlock.
|
|
511
|
+
*/
|
|
512
|
+
async pause() {
|
|
513
|
+
assert4(this._isStarted, "Pipeline is not open.");
|
|
514
|
+
if (this._isPaused) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
this._pauseTrigger.reset();
|
|
518
|
+
await this._processingTrigger.wait();
|
|
519
|
+
this._isPaused = true;
|
|
520
|
+
}
|
|
521
|
+
async unpause() {
|
|
522
|
+
assert4(this._isStarted, "Pipeline is not open.");
|
|
523
|
+
assert4(this._isPaused, "Pipeline is not paused.");
|
|
524
|
+
this._pauseTrigger.wake();
|
|
525
|
+
this._isPaused = false;
|
|
487
526
|
}
|
|
488
527
|
/**
|
|
489
528
|
* Starts to iterate over the ordered messages from the added feeds.
|
|
@@ -492,7 +531,21 @@ var Pipeline = class {
|
|
|
492
531
|
async *consume() {
|
|
493
532
|
assert4(!this._isOpen, "Pipeline is already being consumed.");
|
|
494
533
|
this._isOpen = true;
|
|
495
|
-
|
|
534
|
+
assert4(this._feedSetIterator, "Iterator not initialized.");
|
|
535
|
+
let lastFeedSetIterator = this._feedSetIterator;
|
|
536
|
+
let iterable = lastFeedSetIterator[Symbol.asyncIterator]();
|
|
537
|
+
while (!this._isStopping) {
|
|
538
|
+
await this._pauseTrigger.wait();
|
|
539
|
+
if (lastFeedSetIterator !== this._feedSetIterator) {
|
|
540
|
+
assert4(this._feedSetIterator, "Iterator not initialized.");
|
|
541
|
+
lastFeedSetIterator = this._feedSetIterator;
|
|
542
|
+
iterable = lastFeedSetIterator[Symbol.asyncIterator]();
|
|
543
|
+
}
|
|
544
|
+
const { done, value } = await iterable.next();
|
|
545
|
+
if (done) {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
const block = value != null ? value : failUndefined();
|
|
496
549
|
this._processingTrigger.reset();
|
|
497
550
|
this._timeframeClock.updatePendingTimeframe(PublicKey.from(block.feedKey), block.seq);
|
|
498
551
|
yield block;
|
|
@@ -501,6 +554,24 @@ var Pipeline = class {
|
|
|
501
554
|
}
|
|
502
555
|
this._isOpen = false;
|
|
503
556
|
}
|
|
557
|
+
async _initIterator() {
|
|
558
|
+
this._feedSetIterator = new FeedSetIterator(createMessageSelector(this._timeframeClock), {
|
|
559
|
+
start: startAfter(this._timeframeClock.timeframe),
|
|
560
|
+
stallTimeout: 1e3
|
|
561
|
+
});
|
|
562
|
+
this._feedSetIterator.stalled.on((iterator) => {
|
|
563
|
+
log4.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, {}, {
|
|
564
|
+
file: "pipeline.ts",
|
|
565
|
+
line: 357,
|
|
566
|
+
scope: this,
|
|
567
|
+
callSite: (f, a) => f(...a)
|
|
568
|
+
});
|
|
569
|
+
this._state.stalled.emit();
|
|
570
|
+
});
|
|
571
|
+
for (const feed of this._feeds.values()) {
|
|
572
|
+
await this._feedSetIterator.addFeed(feed);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
504
575
|
};
|
|
505
576
|
__decorate3([
|
|
506
577
|
synchronized2
|
|
@@ -508,6 +579,15 @@ __decorate3([
|
|
|
508
579
|
__decorate3([
|
|
509
580
|
synchronized2
|
|
510
581
|
], Pipeline.prototype, "stop", null);
|
|
582
|
+
__decorate3([
|
|
583
|
+
synchronized2
|
|
584
|
+
], Pipeline.prototype, "setCursor", null);
|
|
585
|
+
__decorate3([
|
|
586
|
+
synchronized2
|
|
587
|
+
], Pipeline.prototype, "pause", null);
|
|
588
|
+
__decorate3([
|
|
589
|
+
synchronized2
|
|
590
|
+
], Pipeline.prototype, "unpause", null);
|
|
511
591
|
|
|
512
592
|
// packages/core/echo/echo-pipeline/src/space/auth.ts
|
|
513
593
|
import assert5 from "@dxos/node-std/assert";
|
|
@@ -527,7 +607,6 @@ var AuthExtension = class extends RpcExtension {
|
|
|
527
607
|
AuthService: schema3.getService("dxos.mesh.teleport.auth.AuthService")
|
|
528
608
|
},
|
|
529
609
|
timeout: 60 * 1e3
|
|
530
|
-
// Long timeout because auth can wait for sync in certain cases.
|
|
531
610
|
});
|
|
532
611
|
this._authParams = _authParams;
|
|
533
612
|
this._ctx = new Context2({
|
|
@@ -596,131 +675,150 @@ var AuthExtension = class extends RpcExtension {
|
|
|
596
675
|
}
|
|
597
676
|
};
|
|
598
677
|
|
|
599
|
-
// packages/core/echo/echo-pipeline/src/
|
|
678
|
+
// packages/core/echo/echo-pipeline/src/dbhost/data-service-host.ts
|
|
600
679
|
import assert6 from "@dxos/node-std/assert";
|
|
601
|
-
import {
|
|
602
|
-
import {
|
|
603
|
-
import { AdmittedFeed as AdmittedFeed2 } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
604
|
-
import { Callback as Callback2 } from "@dxos/util";
|
|
605
|
-
|
|
606
|
-
// packages/core/echo/echo-pipeline/src/space/control-pipeline.ts
|
|
607
|
-
import { SpaceStateMachine } from "@dxos/credentials";
|
|
608
|
-
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
680
|
+
import { Stream } from "@dxos/codec-protobuf";
|
|
681
|
+
import { tagMutationsInBatch, setMetadataOnObject } from "@dxos/echo-db";
|
|
609
682
|
import { log as log6 } from "@dxos/log";
|
|
610
|
-
import {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
this.
|
|
615
|
-
this.
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
683
|
+
import { ComplexMap as ComplexMap2 } from "@dxos/util";
|
|
684
|
+
var DataServiceHost = class {
|
|
685
|
+
constructor(_itemManager, _itemDemuxer, _writeStream) {
|
|
686
|
+
this._itemManager = _itemManager;
|
|
687
|
+
this._itemDemuxer = _itemDemuxer;
|
|
688
|
+
this._writeStream = _writeStream;
|
|
689
|
+
this._clientTagMap = new ComplexMap2(([feedKey, seq]) => `${feedKey.toHex()}:${seq}`);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Real-time subscription to data objects in a space.
|
|
693
|
+
*/
|
|
694
|
+
subscribe() {
|
|
695
|
+
return new Stream(({ next, ctx }) => {
|
|
696
|
+
const objects = Array.from(this._itemManager.entities.values()).map((entity) => entity.createSnapshot());
|
|
697
|
+
next({
|
|
698
|
+
batch: {
|
|
699
|
+
objects
|
|
700
|
+
}
|
|
626
701
|
});
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
702
|
+
this._itemDemuxer.mutation.on(ctx, (message) => {
|
|
703
|
+
var _a;
|
|
704
|
+
const { batch, meta } = message;
|
|
705
|
+
log6("message", {
|
|
706
|
+
batch,
|
|
707
|
+
meta
|
|
708
|
+
}, {
|
|
709
|
+
file: "data-service-host.ts",
|
|
710
|
+
line: 49,
|
|
711
|
+
scope: this,
|
|
712
|
+
callSite: (f, a) => f(...a)
|
|
713
|
+
});
|
|
714
|
+
const clientTag = this._clientTagMap.get([
|
|
715
|
+
message.meta.feedKey,
|
|
716
|
+
message.meta.seq
|
|
717
|
+
]);
|
|
718
|
+
(_a = batch.objects) == null ? void 0 : _a.forEach((object) => {
|
|
719
|
+
setMetadataOnObject(object, meta);
|
|
720
|
+
});
|
|
721
|
+
if (clientTag) {
|
|
722
|
+
tagMutationsInBatch(batch, clientTag);
|
|
638
723
|
}
|
|
639
|
-
|
|
640
|
-
|
|
724
|
+
next({
|
|
725
|
+
clientTag,
|
|
726
|
+
feedKey: message.meta.feedKey,
|
|
727
|
+
seq: message.meta.seq,
|
|
728
|
+
batch
|
|
729
|
+
});
|
|
730
|
+
});
|
|
641
731
|
});
|
|
642
|
-
this.onMemberAdmitted = this._spaceStateMachine.onMemberAdmitted;
|
|
643
|
-
this.onCredentialProcessed = this._spaceStateMachine.onCredentialProcessed;
|
|
644
|
-
}
|
|
645
|
-
get spaceState() {
|
|
646
|
-
return this._spaceStateMachine;
|
|
647
|
-
}
|
|
648
|
-
get pipeline() {
|
|
649
|
-
return this._pipeline;
|
|
650
|
-
}
|
|
651
|
-
setWriteFeed(feed) {
|
|
652
|
-
this._pipeline.setWriteFeed(feed);
|
|
653
732
|
}
|
|
654
|
-
async
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
733
|
+
async write(request) {
|
|
734
|
+
var _a, _b, _c;
|
|
735
|
+
assert6(this._writeStream, "Cannot write mutations in readonly mode");
|
|
736
|
+
log6("write", {
|
|
737
|
+
clientTag: request.clientTag,
|
|
738
|
+
objectCount: (_b = (_a = request.batch.objects) == null ? void 0 : _a.length) != null ? _b : 0
|
|
739
|
+
}, {
|
|
740
|
+
file: "data-service-host.ts",
|
|
741
|
+
line: 77,
|
|
658
742
|
scope: this,
|
|
659
743
|
callSite: (f, a) => f(...a)
|
|
660
744
|
});
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
745
|
+
const message = {
|
|
746
|
+
batch: {
|
|
747
|
+
objects: (_c = request.batch.objects) == null ? void 0 : _c.map((object) => {
|
|
748
|
+
var _a2;
|
|
749
|
+
return {
|
|
750
|
+
...object,
|
|
751
|
+
mutations: (_a2 = object.mutations) == null ? void 0 : _a2.map((mutation) => ({
|
|
752
|
+
...mutation,
|
|
753
|
+
meta: void 0
|
|
754
|
+
})),
|
|
755
|
+
meta: void 0
|
|
756
|
+
};
|
|
757
|
+
})
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
const receipt = await this._writeStream.write(message, {
|
|
761
|
+
afterWrite: async (receipt2) => {
|
|
762
|
+
if (request.clientTag) {
|
|
763
|
+
log6("tag", {
|
|
764
|
+
clientTag: request.clientTag,
|
|
765
|
+
feedKey: receipt2.feedKey,
|
|
766
|
+
seq: receipt2.seq
|
|
667
767
|
}, {
|
|
668
|
-
file: "
|
|
669
|
-
line:
|
|
670
|
-
scope: this,
|
|
671
|
-
callSite: (f, a) => f(...a)
|
|
672
|
-
});
|
|
673
|
-
if (msg.data.payload.credential) {
|
|
674
|
-
const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, PublicKey2.from(msg.feedKey));
|
|
675
|
-
if (!result) {
|
|
676
|
-
log6.warn("processing failed", {
|
|
677
|
-
msg
|
|
678
|
-
}, {
|
|
679
|
-
file: "control-pipeline.ts",
|
|
680
|
-
line: 85,
|
|
681
|
-
scope: this,
|
|
682
|
-
callSite: (f, a) => f(...a)
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
} catch (err) {
|
|
687
|
-
log6.catch(err, {}, {
|
|
688
|
-
file: "control-pipeline.ts",
|
|
689
|
-
line: 89,
|
|
768
|
+
file: "data-service-host.ts",
|
|
769
|
+
line: 96,
|
|
690
770
|
scope: this,
|
|
691
771
|
callSite: (f, a) => f(...a)
|
|
692
772
|
});
|
|
773
|
+
this._clientTagMap.set([
|
|
774
|
+
receipt2.feedKey,
|
|
775
|
+
receipt2.seq
|
|
776
|
+
], request.clientTag);
|
|
693
777
|
}
|
|
694
778
|
}
|
|
695
779
|
});
|
|
696
|
-
|
|
697
|
-
log6("started", {}, {
|
|
698
|
-
file: "control-pipeline.ts",
|
|
699
|
-
line: 95,
|
|
700
|
-
scope: this,
|
|
701
|
-
callSite: (f, a) => f(...a)
|
|
702
|
-
});
|
|
780
|
+
return receipt;
|
|
703
781
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// packages/core/echo/echo-pipeline/src/dbhost/database-host.ts
|
|
785
|
+
import { ItemDemuxer } from "@dxos/echo-db";
|
|
786
|
+
var DatabaseHost = class {
|
|
787
|
+
constructor(_outboundStream) {
|
|
788
|
+
this._outboundStream = _outboundStream;
|
|
789
|
+
}
|
|
790
|
+
get isReadOnly() {
|
|
791
|
+
return !!this._outboundStream;
|
|
792
|
+
}
|
|
793
|
+
get echoProcessor() {
|
|
794
|
+
return this._echoProcessor;
|
|
795
|
+
}
|
|
796
|
+
async open(itemManager, modelFactory) {
|
|
797
|
+
this._itemManager = itemManager;
|
|
798
|
+
this._itemManager._debugLabel = "host";
|
|
799
|
+
this._itemDemuxer = new ItemDemuxer(itemManager, modelFactory);
|
|
800
|
+
this._echoProcessor = this._itemDemuxer.open();
|
|
801
|
+
}
|
|
802
|
+
async close() {
|
|
803
|
+
}
|
|
804
|
+
getWriteStream() {
|
|
805
|
+
return this._outboundStream;
|
|
806
|
+
}
|
|
807
|
+
createSnapshot() {
|
|
808
|
+
return this._itemDemuxer.createSnapshot();
|
|
809
|
+
}
|
|
810
|
+
createDataServiceHost() {
|
|
811
|
+
var _a;
|
|
812
|
+
return new DataServiceHost(this._itemManager, this._itemDemuxer, (_a = this._outboundStream) != null ? _a : void 0);
|
|
718
813
|
}
|
|
719
814
|
};
|
|
720
815
|
|
|
721
|
-
// packages/core/echo/echo-pipeline/src/
|
|
722
|
-
|
|
723
|
-
|
|
816
|
+
// packages/core/echo/echo-pipeline/src/dbhost/snapshot-manager.ts
|
|
817
|
+
import { trackLeaks } from "@dxos/async";
|
|
818
|
+
import { schema as schema4 } from "@dxos/protocols";
|
|
819
|
+
import { ObjectSync } from "@dxos/teleport-extension-object-sync";
|
|
820
|
+
var __decorate4 = function(decorators, target, key, desc) {
|
|
821
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
724
822
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
725
823
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
726
824
|
else
|
|
@@ -729,183 +827,164 @@ var __decorate4 = function(decorators, target, key, desc) {
|
|
|
729
827
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
730
828
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
731
829
|
};
|
|
732
|
-
var
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
this.
|
|
736
|
-
this.
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
await this.
|
|
750
|
-
if (this._dataPipeline) {
|
|
751
|
-
if (!this._dataPipeline.hasFeed(info.key)) {
|
|
752
|
-
return this._dataPipeline.addFeed(await this._feedProvider(info.key));
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
if (!info.key.equals(genesisFeed.key)) {
|
|
758
|
-
this.protocol.addFeed(await feedProvider(info.key));
|
|
830
|
+
var SnapshotManager = class SnapshotManager2 {
|
|
831
|
+
// prettier-ignore
|
|
832
|
+
constructor(_snapshotStore) {
|
|
833
|
+
this._snapshotStore = _snapshotStore;
|
|
834
|
+
this._objectSync = new ObjectSync({
|
|
835
|
+
getObject: async (id) => {
|
|
836
|
+
const snapshot = await this._snapshotStore.loadSnapshot(id);
|
|
837
|
+
if (!snapshot) {
|
|
838
|
+
return void 0;
|
|
839
|
+
}
|
|
840
|
+
return {
|
|
841
|
+
id,
|
|
842
|
+
payload: schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").encodeAsAny(snapshot)
|
|
843
|
+
};
|
|
844
|
+
},
|
|
845
|
+
setObject: async (data) => {
|
|
846
|
+
const snapshot = schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(data.payload);
|
|
847
|
+
await this._snapshotStore.saveSnapshot(snapshot);
|
|
759
848
|
}
|
|
760
849
|
});
|
|
761
|
-
this._controlPipeline.onCredentialProcessed.set(async (credential) => {
|
|
762
|
-
await this.onCredentialProcessed.callIfSet(credential);
|
|
763
|
-
log7("onCredentialProcessed", {
|
|
764
|
-
credential
|
|
765
|
-
}, {
|
|
766
|
-
file: "space.ts",
|
|
767
|
-
line: 87,
|
|
768
|
-
scope: this,
|
|
769
|
-
callSite: (f, a) => f(...a)
|
|
770
|
-
});
|
|
771
|
-
this.stateUpdate.emit();
|
|
772
|
-
});
|
|
773
|
-
this.protocol = protocol;
|
|
774
|
-
this.protocol.addFeed(genesisFeed);
|
|
775
850
|
}
|
|
776
|
-
get
|
|
777
|
-
return this.
|
|
851
|
+
get objectSync() {
|
|
852
|
+
return this._objectSync;
|
|
778
853
|
}
|
|
779
|
-
|
|
780
|
-
|
|
854
|
+
async open() {
|
|
855
|
+
await this._objectSync.open();
|
|
781
856
|
}
|
|
782
|
-
|
|
783
|
-
|
|
857
|
+
async close() {
|
|
858
|
+
await this._objectSync.close();
|
|
784
859
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
860
|
+
async load(id) {
|
|
861
|
+
const local = await this._snapshotStore.loadSnapshot(id);
|
|
862
|
+
if (local) {
|
|
863
|
+
return local;
|
|
864
|
+
}
|
|
865
|
+
const remote = await this._objectSync.download(id);
|
|
866
|
+
return schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(remote.payload);
|
|
788
867
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return
|
|
868
|
+
async store(snapshot) {
|
|
869
|
+
const id = await this._snapshotStore.saveSnapshot(snapshot);
|
|
870
|
+
return id;
|
|
792
871
|
}
|
|
793
|
-
|
|
794
|
-
|
|
872
|
+
};
|
|
873
|
+
SnapshotManager = __decorate4([
|
|
874
|
+
trackLeaks("open", "close")
|
|
875
|
+
], SnapshotManager);
|
|
876
|
+
|
|
877
|
+
// packages/core/echo/echo-pipeline/src/dbhost/snapshot-store.ts
|
|
878
|
+
import { subtleCrypto } from "@dxos/crypto";
|
|
879
|
+
import { schema as schema5 } from "@dxos/protocols";
|
|
880
|
+
var SnapshotStore = class {
|
|
881
|
+
// prettier-ignore
|
|
882
|
+
constructor(_directory) {
|
|
883
|
+
this._directory = _directory;
|
|
795
884
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
885
|
+
async saveSnapshot(snapshot) {
|
|
886
|
+
const encoded = schema5.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").encode(snapshot);
|
|
887
|
+
const key = await subtleCrypto.digest("SHA-256", encoded);
|
|
888
|
+
const keyString = Buffer.from(key).toString("hex");
|
|
889
|
+
const file = await this._directory.getOrCreateFile(keyString);
|
|
890
|
+
try {
|
|
891
|
+
await file.write(0, Buffer.from(encoded));
|
|
892
|
+
} finally {
|
|
893
|
+
await file.close();
|
|
894
|
+
}
|
|
895
|
+
return keyString;
|
|
801
896
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
897
|
+
async loadSnapshot(key) {
|
|
898
|
+
const file = await this._directory.getOrCreateFile(key);
|
|
899
|
+
try {
|
|
900
|
+
const { size } = await file.stat();
|
|
901
|
+
if (size === 0) {
|
|
902
|
+
return void 0;
|
|
903
|
+
}
|
|
904
|
+
const buffer = await file.read(0, size);
|
|
905
|
+
return schema5.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(buffer);
|
|
906
|
+
} finally {
|
|
907
|
+
await file.close();
|
|
908
|
+
}
|
|
807
909
|
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
910
|
+
async listSnapshots() {
|
|
911
|
+
const entries = await this._directory.list();
|
|
912
|
+
return await Promise.all(entries.map(async (key) => {
|
|
913
|
+
const { size } = await this._directory.getOrCreateFile(key).stat();
|
|
914
|
+
return {
|
|
915
|
+
key,
|
|
916
|
+
size
|
|
917
|
+
};
|
|
918
|
+
}));
|
|
814
919
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// packages/core/echo/echo-pipeline/src/dbhost/data-service.ts
|
|
923
|
+
import assert7 from "@dxos/node-std/assert";
|
|
924
|
+
import { raise } from "@dxos/debug";
|
|
925
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
926
|
+
import { log as log7 } from "@dxos/log";
|
|
927
|
+
import { ComplexMap as ComplexMap3 } from "@dxos/util";
|
|
928
|
+
var DataServiceSubscriptions = class {
|
|
929
|
+
constructor() {
|
|
930
|
+
this._spaces = new ComplexMap3(PublicKey2.hash);
|
|
820
931
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
*/
|
|
824
|
-
// getDataFeeds(): FeedInfo[] {
|
|
825
|
-
// return this._dataPipeline?.getFeeds();
|
|
826
|
-
// }
|
|
827
|
-
async open() {
|
|
828
|
-
log7("opening...", {}, {
|
|
829
|
-
file: "space.ts",
|
|
830
|
-
line: 157,
|
|
831
|
-
scope: this,
|
|
832
|
-
callSite: (f, a) => f(...a)
|
|
833
|
-
});
|
|
834
|
-
if (this._isOpen) {
|
|
835
|
-
return;
|
|
836
|
-
}
|
|
837
|
-
await this._controlPipeline.start();
|
|
838
|
-
await this.protocol.start();
|
|
839
|
-
this._isOpen = true;
|
|
840
|
-
log7("opened", {}, {
|
|
841
|
-
file: "space.ts",
|
|
842
|
-
line: 167,
|
|
843
|
-
scope: this,
|
|
844
|
-
callSite: (f, a) => f(...a)
|
|
845
|
-
});
|
|
932
|
+
clear() {
|
|
933
|
+
this._spaces.clear();
|
|
846
934
|
}
|
|
847
|
-
|
|
848
|
-
log7("
|
|
849
|
-
|
|
935
|
+
registerSpace(spaceKey, host) {
|
|
936
|
+
log7("Registering space", {
|
|
937
|
+
spaceKey
|
|
850
938
|
}, {
|
|
851
|
-
file: "
|
|
852
|
-
line:
|
|
939
|
+
file: "data-service.ts",
|
|
940
|
+
line: 31,
|
|
853
941
|
scope: this,
|
|
854
942
|
callSite: (f, a) => f(...a)
|
|
855
943
|
});
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
line: 182,
|
|
944
|
+
this._spaces.set(spaceKey, host);
|
|
945
|
+
}
|
|
946
|
+
unregisterSpace(spaceKey) {
|
|
947
|
+
log7("Unregistering space", {
|
|
948
|
+
spaceKey
|
|
949
|
+
}, {
|
|
950
|
+
file: "data-service.ts",
|
|
951
|
+
line: 36,
|
|
865
952
|
scope: this,
|
|
866
953
|
callSite: (f, a) => f(...a)
|
|
867
954
|
});
|
|
955
|
+
this._spaces.delete(spaceKey);
|
|
868
956
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
957
|
+
getDataService(spaceKey) {
|
|
958
|
+
return this._spaces.get(spaceKey);
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
var DataServiceImpl = class {
|
|
962
|
+
constructor(_subscriptions) {
|
|
963
|
+
this._subscriptions = _subscriptions;
|
|
964
|
+
}
|
|
965
|
+
subscribe(request) {
|
|
966
|
+
var _a;
|
|
967
|
+
assert7(request.spaceKey);
|
|
968
|
+
const host = (_a = this._subscriptions.getDataService(request.spaceKey)) != null ? _a : raise(new Error(`space not found: ${request.spaceKey}`));
|
|
969
|
+
return host.subscribe();
|
|
970
|
+
}
|
|
971
|
+
write(request) {
|
|
972
|
+
var _a;
|
|
973
|
+
assert7(request.spaceKey);
|
|
974
|
+
assert7(request.batch);
|
|
975
|
+
const host = (_a = this._subscriptions.getDataService(request.spaceKey)) != null ? _a : raise(new Error(`space not found: ${request.spaceKey}`));
|
|
976
|
+
return host.write(request);
|
|
886
977
|
}
|
|
887
978
|
};
|
|
888
|
-
__decorate4([
|
|
889
|
-
logInfo
|
|
890
|
-
], Space.prototype, "key", null);
|
|
891
|
-
__decorate4([
|
|
892
|
-
synchronized3
|
|
893
|
-
], Space.prototype, "open", null);
|
|
894
|
-
__decorate4([
|
|
895
|
-
synchronized3
|
|
896
|
-
], Space.prototype, "close", null);
|
|
897
|
-
Space = __decorate4([
|
|
898
|
-
trackLeaks("open", "close")
|
|
899
|
-
], Space);
|
|
900
979
|
|
|
901
|
-
// packages/core/echo/echo-pipeline/src/space/
|
|
902
|
-
import
|
|
903
|
-
import {
|
|
904
|
-
import {
|
|
905
|
-
import {
|
|
906
|
-
import {
|
|
907
|
-
import {
|
|
908
|
-
import {
|
|
980
|
+
// packages/core/echo/echo-pipeline/src/space/data-pipeline.ts
|
|
981
|
+
import assert8 from "@dxos/node-std/assert";
|
|
982
|
+
import { Event as Event3, scheduleTask as scheduleTask2, synchronized as synchronized3, trackLeaks as trackLeaks2 } from "@dxos/async";
|
|
983
|
+
import { Context as Context3 } from "@dxos/context";
|
|
984
|
+
import { getCredentialAssertion } from "@dxos/credentials";
|
|
985
|
+
import { getStateMachineFromItem, ItemManager } from "@dxos/echo-db";
|
|
986
|
+
import { log as log8 } from "@dxos/log";
|
|
987
|
+
import { Timeframe as Timeframe3 } from "@dxos/timeframe";
|
|
909
988
|
var __decorate5 = function(decorators, target, key, desc) {
|
|
910
989
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
911
990
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
@@ -916,468 +995,594 @@ var __decorate5 = function(decorators, target, key, desc) {
|
|
|
916
995
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
917
996
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
918
997
|
};
|
|
919
|
-
var
|
|
920
|
-
var
|
|
921
|
-
var
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
this.
|
|
925
|
-
this.
|
|
926
|
-
this.
|
|
927
|
-
this.
|
|
928
|
-
this.
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
return this._sessions;
|
|
998
|
+
var MESSAGES_PER_SNAPSHOT = 10;
|
|
999
|
+
var AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL = 5e3;
|
|
1000
|
+
var TIMEFRAME_SAVE_DEBOUNCE_INTERVAL = 500;
|
|
1001
|
+
var DataPipeline = class DataPipeline2 {
|
|
1002
|
+
constructor(_params) {
|
|
1003
|
+
this._params = _params;
|
|
1004
|
+
this._ctx = new Context3();
|
|
1005
|
+
this._lastAutomaticSnapshotTimeframe = new Timeframe3();
|
|
1006
|
+
this._isOpen = false;
|
|
1007
|
+
this._lastTimeframeSaveTime = 0;
|
|
1008
|
+
this._lastSnapshotSaveTime = 0;
|
|
1009
|
+
this.onNewEpoch = new Event3();
|
|
932
1010
|
}
|
|
933
|
-
get
|
|
934
|
-
return this.
|
|
1011
|
+
get isOpen() {
|
|
1012
|
+
return this._isOpen;
|
|
935
1013
|
}
|
|
936
|
-
get
|
|
937
|
-
return this.
|
|
1014
|
+
get pipeline() {
|
|
1015
|
+
return this._pipeline;
|
|
938
1016
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
key: feed.key
|
|
943
|
-
}, {
|
|
944
|
-
file: "space-protocol.ts",
|
|
945
|
-
line: 84,
|
|
946
|
-
scope: this,
|
|
947
|
-
callSite: (f, a) => f(...a)
|
|
948
|
-
});
|
|
949
|
-
this._feeds.add(feed);
|
|
950
|
-
for (const session of this._sessions.values()) {
|
|
951
|
-
session.replicator.addFeed(feed);
|
|
952
|
-
}
|
|
1017
|
+
get pipelineState() {
|
|
1018
|
+
var _a;
|
|
1019
|
+
return (_a = this._pipeline) == null ? void 0 : _a.state;
|
|
953
1020
|
}
|
|
954
|
-
|
|
955
|
-
|
|
1021
|
+
setTargetTimeframe(timeframe) {
|
|
1022
|
+
var _a;
|
|
1023
|
+
this._targetTimeframe = timeframe;
|
|
1024
|
+
(_a = this._pipeline) == null ? void 0 : _a.state.setTargetTimeframe(timeframe);
|
|
1025
|
+
}
|
|
1026
|
+
createCredentialProcessor() {
|
|
1027
|
+
return {
|
|
1028
|
+
process: async (credential) => {
|
|
1029
|
+
const assertion = getCredentialAssertion(credential);
|
|
1030
|
+
if (assertion["@type"] !== "dxos.halo.credentials.Epoch") {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
log8("new epoch", {
|
|
1034
|
+
credential
|
|
1035
|
+
}, {
|
|
1036
|
+
file: "data-pipeline.ts",
|
|
1037
|
+
line: 110,
|
|
1038
|
+
scope: this,
|
|
1039
|
+
callSite: (f, a) => f(...a)
|
|
1040
|
+
});
|
|
1041
|
+
await this._processEpoch(assertion);
|
|
1042
|
+
this.currentEpoch = credential;
|
|
1043
|
+
this.onNewEpoch.emit(credential);
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
async open() {
|
|
1048
|
+
if (this._isOpen) {
|
|
956
1049
|
return;
|
|
957
1050
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1051
|
+
this._pipeline = new Pipeline();
|
|
1052
|
+
await this._params.onPipelineCreated(this._pipeline);
|
|
1053
|
+
await this._pipeline.start();
|
|
1054
|
+
await this._pipeline.pause();
|
|
1055
|
+
if (this._targetTimeframe) {
|
|
1056
|
+
this._pipeline.state.setTargetTimeframe(this._targetTimeframe);
|
|
1057
|
+
}
|
|
1058
|
+
const feedWriter = {
|
|
1059
|
+
write: (data, options) => {
|
|
1060
|
+
assert8(this._pipeline, "Pipeline is not initialized.");
|
|
1061
|
+
assert8(this.currentEpoch, "Epoch is not initialized.");
|
|
1062
|
+
return this._pipeline.writer.write({
|
|
1063
|
+
data
|
|
1064
|
+
}, options);
|
|
1065
|
+
}
|
|
963
1066
|
};
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
});
|
|
970
|
-
this._connection = await this._networkManager.joinSwarm({
|
|
971
|
-
protocolProvider: this._createProtocolProvider(credentials),
|
|
972
|
-
peerId: this._swarmIdentity.peerKey,
|
|
973
|
-
topic: this._topic,
|
|
974
|
-
topology: new MMSTTopology(topologyConfig),
|
|
975
|
-
label: `Protocol swarm: ${this._topic}`
|
|
1067
|
+
this.databaseHost = new DatabaseHost(feedWriter);
|
|
1068
|
+
this.itemManager = new ItemManager(this._params.modelFactory);
|
|
1069
|
+
await this.databaseHost.open(this.itemManager, this._params.modelFactory);
|
|
1070
|
+
scheduleTask2(this._ctx, async () => {
|
|
1071
|
+
await this._consumePipeline();
|
|
976
1072
|
});
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1073
|
+
this._isOpen = true;
|
|
1074
|
+
}
|
|
1075
|
+
async close() {
|
|
1076
|
+
var _a, _b, _c;
|
|
1077
|
+
if (!this._isOpen) {
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
log8("close", {}, {
|
|
1081
|
+
file: "data-pipeline.ts",
|
|
1082
|
+
line: 162,
|
|
980
1083
|
scope: this,
|
|
981
1084
|
callSite: (f, a) => f(...a)
|
|
982
1085
|
});
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1086
|
+
this._isOpen = false;
|
|
1087
|
+
await this._ctx.dispose();
|
|
1088
|
+
await ((_a = this._pipeline) == null ? void 0 : _a.stop());
|
|
1089
|
+
try {
|
|
1090
|
+
await this._saveCache();
|
|
1091
|
+
if (this._pipeline) {
|
|
1092
|
+
await this._saveTargetTimeframe(this._pipeline.state.timeframe);
|
|
1093
|
+
}
|
|
1094
|
+
} catch (err) {
|
|
1095
|
+
log8.catch(err, {}, {
|
|
1096
|
+
file: "data-pipeline.ts",
|
|
1097
|
+
line: 175,
|
|
989
1098
|
scope: this,
|
|
990
1099
|
callSite: (f, a) => f(...a)
|
|
991
1100
|
});
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1101
|
+
}
|
|
1102
|
+
await ((_b = this.databaseHost) == null ? void 0 : _b.close());
|
|
1103
|
+
await ((_c = this.itemManager) == null ? void 0 : _c.destroy());
|
|
1104
|
+
await this._params.snapshotManager.close();
|
|
1105
|
+
}
|
|
1106
|
+
async _consumePipeline() {
|
|
1107
|
+
assert8(this._pipeline, "Pipeline is not initialized.");
|
|
1108
|
+
for await (const msg of this._pipeline.consume()) {
|
|
1109
|
+
const { feedKey, seq, data } = msg;
|
|
1110
|
+
log8("processing message", {
|
|
1111
|
+
feedKey,
|
|
1112
|
+
seq
|
|
1113
|
+
}, {
|
|
1114
|
+
file: "data-pipeline.ts",
|
|
1115
|
+
line: 187,
|
|
996
1116
|
scope: this,
|
|
997
1117
|
callSite: (f, a) => f(...a)
|
|
998
1118
|
});
|
|
1119
|
+
try {
|
|
1120
|
+
if (data.payload.data) {
|
|
1121
|
+
const feedInfo = this._params.feedInfoProvider(feedKey);
|
|
1122
|
+
if (!feedInfo) {
|
|
1123
|
+
log8.error("Could not find feed.", {
|
|
1124
|
+
feedKey
|
|
1125
|
+
}, {
|
|
1126
|
+
file: "data-pipeline.ts",
|
|
1127
|
+
line: 193,
|
|
1128
|
+
scope: this,
|
|
1129
|
+
callSite: (f, a) => f(...a)
|
|
1130
|
+
});
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
await this.databaseHost.echoProcessor({
|
|
1134
|
+
batch: data.payload.data.batch,
|
|
1135
|
+
meta: {
|
|
1136
|
+
feedKey,
|
|
1137
|
+
seq,
|
|
1138
|
+
timeframe: data.timeframe,
|
|
1139
|
+
memberKey: feedInfo.assertion.identityKey
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
|
|
1143
|
+
}
|
|
1144
|
+
} catch (err) {
|
|
1145
|
+
log8.catch(err, {}, {
|
|
1146
|
+
file: "data-pipeline.ts",
|
|
1147
|
+
line: 211,
|
|
1148
|
+
scope: this,
|
|
1149
|
+
callSite: (f, a) => f(...a)
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
999
1152
|
}
|
|
1000
1153
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1154
|
+
_createSnapshot() {
|
|
1155
|
+
assert8(this.databaseHost, "Database backend is not initialized.");
|
|
1156
|
+
return {
|
|
1157
|
+
spaceKey: this._params.spaceKey.asUint8Array(),
|
|
1158
|
+
timeframe: this._pipeline.state.timeframe,
|
|
1159
|
+
database: this.databaseHost.createSnapshot()
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
async _saveTargetTimeframe(timeframe) {
|
|
1163
|
+
var _a;
|
|
1164
|
+
const newTimeframe = Timeframe3.merge((_a = this._targetTimeframe) != null ? _a : new Timeframe3(), timeframe);
|
|
1165
|
+
await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, newTimeframe);
|
|
1166
|
+
this._targetTimeframe = newTimeframe;
|
|
1167
|
+
}
|
|
1168
|
+
async _saveCache() {
|
|
1169
|
+
var _a;
|
|
1170
|
+
const cache = {};
|
|
1171
|
+
try {
|
|
1172
|
+
const propertiesItem = this.itemManager.items.find((item) => {
|
|
1173
|
+
var _a2, _b;
|
|
1174
|
+
return ((_a2 = item.modelMeta) == null ? void 0 : _a2.type) === "dxos:model/document" && ((_b = getStateMachineFromItem(item)) == null ? void 0 : _b.snapshot().type) === "dxos.sdk.client.Properties";
|
|
1007
1175
|
});
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
session.replicator.addFeed(feed);
|
|
1176
|
+
if (propertiesItem) {
|
|
1177
|
+
cache.properties = (_a = getStateMachineFromItem(propertiesItem)) == null ? void 0 : _a.snapshot();
|
|
1011
1178
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1179
|
+
} catch (err) {
|
|
1180
|
+
log8.warn("Failed to cache properties", err, {
|
|
1181
|
+
file: "data-pipeline.ts",
|
|
1182
|
+
line: 245,
|
|
1183
|
+
scope: this,
|
|
1184
|
+
callSite: (f, a) => f(...a)
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
await this._params.metadataStore.setCache(this._params.spaceKey, cache);
|
|
1014
1188
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
(function(AuthStatus2) {
|
|
1024
|
-
AuthStatus2["INITIAL"] = "INITIAL";
|
|
1025
|
-
AuthStatus2["SUCCESS"] = "SUCCESS";
|
|
1026
|
-
AuthStatus2["FAILURE"] = "FAILURE";
|
|
1027
|
-
})(AuthStatus || (AuthStatus = {}));
|
|
1028
|
-
var SpaceProtocolSession = class {
|
|
1029
|
-
// TODO(dmaretskyi): Allow to pass in extra extensions.
|
|
1030
|
-
constructor({ wireParams, swarmIdentity, onSessionAuth }) {
|
|
1031
|
-
// TODO(dmaretskyi): Start with upload=false when switching it on the fly works.
|
|
1032
|
-
this.replicator = new ReplicatorExtension().setOptions({
|
|
1033
|
-
upload: true
|
|
1034
|
-
});
|
|
1035
|
-
this._authStatus = AuthStatus.INITIAL;
|
|
1036
|
-
this._wireParams = wireParams;
|
|
1037
|
-
this._swarmIdentity = swarmIdentity;
|
|
1038
|
-
this._onSessionAuth = onSessionAuth;
|
|
1039
|
-
this._teleport = new Teleport(wireParams);
|
|
1189
|
+
async _noteTargetStateIfNeeded(timeframe) {
|
|
1190
|
+
if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL) {
|
|
1191
|
+
this._lastTimeframeSaveTime = Date.now();
|
|
1192
|
+
await this._saveTargetTimeframe(timeframe);
|
|
1193
|
+
}
|
|
1194
|
+
if (Date.now() - this._lastSnapshotSaveTime > AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL && timeframe.totalMessages() - this._lastAutomaticSnapshotTimeframe.totalMessages() > MESSAGES_PER_SNAPSHOT) {
|
|
1195
|
+
await this._saveCache();
|
|
1196
|
+
}
|
|
1040
1197
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1198
|
+
async _processEpoch(epoch) {
|
|
1199
|
+
assert8(this._isOpen);
|
|
1200
|
+
assert8(this._pipeline);
|
|
1201
|
+
if (epoch.snapshotCid) {
|
|
1202
|
+
const snapshot = await this._params.snapshotManager.load(epoch.snapshotCid);
|
|
1203
|
+
this.databaseHost._itemDemuxer.restoreFromSnapshot(snapshot.database);
|
|
1204
|
+
}
|
|
1205
|
+
await this._pipeline.pause();
|
|
1206
|
+
await this._pipeline.setCursor(epoch.timeframe);
|
|
1207
|
+
await this._pipeline.unpause();
|
|
1043
1208
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1209
|
+
async waitUntilTimeframe(timeframe) {
|
|
1210
|
+
assert8(this._pipeline, "Pipeline is not initialized.");
|
|
1211
|
+
await this._pipeline.state.waitUntilTimeframe(timeframe);
|
|
1046
1212
|
}
|
|
1047
|
-
async
|
|
1048
|
-
|
|
1049
|
-
this.
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
(_a = this._onSessionAuth) == null ? void 0 : _a.call(this, this._teleport);
|
|
1062
|
-
},
|
|
1063
|
-
onAuthFailure: () => {
|
|
1064
|
-
log8.warn("Auth failed", {}, {
|
|
1065
|
-
file: "space-protocol.ts",
|
|
1066
|
-
line: 211,
|
|
1067
|
-
scope: this,
|
|
1068
|
-
callSite: (f, a) => f(...a)
|
|
1069
|
-
});
|
|
1070
|
-
this._authStatus = AuthStatus.FAILURE;
|
|
1071
|
-
}
|
|
1072
|
-
}));
|
|
1073
|
-
this._teleport.addExtension("dxos.mesh.teleport.replicator", this.replicator);
|
|
1213
|
+
async createEpoch() {
|
|
1214
|
+
assert8(this._pipeline);
|
|
1215
|
+
assert8(this.currentEpoch);
|
|
1216
|
+
await this._pipeline.pause();
|
|
1217
|
+
const snapshot = await this._createSnapshot();
|
|
1218
|
+
const snapshotCid = await this._params.snapshotManager.store(snapshot);
|
|
1219
|
+
const epoch = {
|
|
1220
|
+
previousId: this.currentEpoch.id,
|
|
1221
|
+
timeframe: this._pipeline.state.timeframe,
|
|
1222
|
+
number: this.currentEpoch.subject.assertion.number + 1,
|
|
1223
|
+
snapshotCid
|
|
1224
|
+
};
|
|
1225
|
+
await this._pipeline.unpause();
|
|
1226
|
+
return epoch;
|
|
1074
1227
|
}
|
|
1075
|
-
async
|
|
1076
|
-
await this.
|
|
1228
|
+
async ensureEpochInitialized() {
|
|
1229
|
+
await this.onNewEpoch.waitForCondition(() => !!this.currentEpoch);
|
|
1077
1230
|
}
|
|
1078
1231
|
};
|
|
1079
1232
|
__decorate5([
|
|
1080
|
-
|
|
1081
|
-
],
|
|
1233
|
+
synchronized3
|
|
1234
|
+
], DataPipeline.prototype, "open", null);
|
|
1082
1235
|
__decorate5([
|
|
1083
|
-
|
|
1084
|
-
],
|
|
1236
|
+
synchronized3
|
|
1237
|
+
], DataPipeline.prototype, "close", null);
|
|
1238
|
+
__decorate5([
|
|
1239
|
+
synchronized3
|
|
1240
|
+
], DataPipeline.prototype, "_processEpoch", null);
|
|
1241
|
+
__decorate5([
|
|
1242
|
+
synchronized3
|
|
1243
|
+
], DataPipeline.prototype, "createEpoch", null);
|
|
1244
|
+
DataPipeline = __decorate5([
|
|
1245
|
+
trackLeaks2("open", "close")
|
|
1246
|
+
], DataPipeline);
|
|
1085
1247
|
|
|
1086
|
-
// packages/core/echo/echo-pipeline/src/space/space
|
|
1087
|
-
import
|
|
1088
|
-
import {
|
|
1089
|
-
import {
|
|
1248
|
+
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
1249
|
+
import assert9 from "@dxos/node-std/assert";
|
|
1250
|
+
import { Event as Event4, synchronized as synchronized4, trackLeaks as trackLeaks3, Lock } from "@dxos/async";
|
|
1251
|
+
import { log as log10, logInfo } from "@dxos/log";
|
|
1252
|
+
import { AdmittedFeed as AdmittedFeed2 } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
1253
|
+
import { Callback as Callback2 } from "@dxos/util";
|
|
1254
|
+
|
|
1255
|
+
// packages/core/echo/echo-pipeline/src/space/control-pipeline.ts
|
|
1256
|
+
import { SpaceStateMachine } from "@dxos/credentials";
|
|
1257
|
+
import { PublicKey as PublicKey3 } from "@dxos/keys";
|
|
1090
1258
|
import { log as log9 } from "@dxos/log";
|
|
1091
|
-
import {
|
|
1092
|
-
import {
|
|
1093
|
-
var
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1259
|
+
import { AdmittedFeed } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
1260
|
+
import { Callback } from "@dxos/util";
|
|
1261
|
+
var ControlPipeline = class {
|
|
1262
|
+
constructor({ spaceKey, genesisFeed, feedProvider }) {
|
|
1263
|
+
this.onFeedAdmitted = new Callback();
|
|
1264
|
+
this._pipeline = new Pipeline();
|
|
1265
|
+
void this._pipeline.addFeed(genesisFeed);
|
|
1266
|
+
this._spaceStateMachine = new SpaceStateMachine(spaceKey);
|
|
1267
|
+
this._spaceStateMachine.onFeedAdmitted.set(async (info) => {
|
|
1268
|
+
log9("feed admitted", {
|
|
1269
|
+
key: info.key
|
|
1270
|
+
}, {
|
|
1271
|
+
file: "control-pipeline.ts",
|
|
1272
|
+
line: 39,
|
|
1273
|
+
scope: this,
|
|
1274
|
+
callSite: (f, a) => f(...a)
|
|
1275
|
+
});
|
|
1276
|
+
if (info.assertion.designation === AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
|
|
1277
|
+
try {
|
|
1278
|
+
const feed = await feedProvider(info.key);
|
|
1279
|
+
await this._pipeline.addFeed(feed);
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
log9.catch(err, {}, {
|
|
1282
|
+
file: "control-pipeline.ts",
|
|
1283
|
+
line: 47,
|
|
1284
|
+
scope: this,
|
|
1285
|
+
callSite: (f, a) => f(...a)
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
await this.onFeedAdmitted.callIfSet(info);
|
|
1290
|
+
});
|
|
1291
|
+
this.onMemberAdmitted = this._spaceStateMachine.onMemberAdmitted;
|
|
1292
|
+
this.onCredentialProcessed = this._spaceStateMachine.onCredentialProcessed;
|
|
1109
1293
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
return this._spaces;
|
|
1294
|
+
get spaceState() {
|
|
1295
|
+
return this._spaceStateMachine;
|
|
1113
1296
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1297
|
+
get pipeline() {
|
|
1298
|
+
return this._pipeline;
|
|
1299
|
+
}
|
|
1300
|
+
setWriteFeed(feed) {
|
|
1301
|
+
this._pipeline.setWriteFeed(feed);
|
|
1302
|
+
}
|
|
1303
|
+
async start() {
|
|
1304
|
+
log9("starting...", {}, {
|
|
1305
|
+
file: "control-pipeline.ts",
|
|
1306
|
+
line: 71,
|
|
1121
1307
|
scope: this,
|
|
1122
1308
|
callSite: (f, a) => f(...a)
|
|
1123
1309
|
});
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1310
|
+
setTimeout(async () => {
|
|
1311
|
+
for await (const msg of this._pipeline.consume()) {
|
|
1312
|
+
try {
|
|
1313
|
+
log9("processing", {
|
|
1314
|
+
key: msg.feedKey,
|
|
1315
|
+
seq: msg.seq
|
|
1316
|
+
}, {
|
|
1317
|
+
file: "control-pipeline.ts",
|
|
1318
|
+
line: 76,
|
|
1319
|
+
scope: this,
|
|
1320
|
+
callSite: (f, a) => f(...a)
|
|
1321
|
+
});
|
|
1322
|
+
if (msg.data.payload.credential) {
|
|
1323
|
+
const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, PublicKey3.from(msg.feedKey));
|
|
1324
|
+
if (!result) {
|
|
1325
|
+
log9.warn("processing failed", {
|
|
1326
|
+
msg
|
|
1327
|
+
}, {
|
|
1328
|
+
file: "control-pipeline.ts",
|
|
1329
|
+
line: 83,
|
|
1330
|
+
scope: this,
|
|
1331
|
+
callSite: (f, a) => f(...a)
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
} catch (err) {
|
|
1336
|
+
log9.catch(err, {}, {
|
|
1337
|
+
file: "control-pipeline.ts",
|
|
1338
|
+
line: 87,
|
|
1339
|
+
scope: this,
|
|
1340
|
+
callSite: (f, a) => f(...a)
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
await this._pipeline.start();
|
|
1346
|
+
log9("started", {}, {
|
|
1347
|
+
file: "control-pipeline.ts",
|
|
1348
|
+
line: 93,
|
|
1134
1349
|
scope: this,
|
|
1135
1350
|
callSite: (f, a) => f(...a)
|
|
1136
1351
|
});
|
|
1137
1352
|
}
|
|
1138
|
-
async
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
}, {
|
|
1143
|
-
file: "space-manager.ts",
|
|
1144
|
-
line: 76,
|
|
1353
|
+
async stop() {
|
|
1354
|
+
log9("stopping...", {}, {
|
|
1355
|
+
file: "control-pipeline.ts",
|
|
1356
|
+
line: 97,
|
|
1145
1357
|
scope: this,
|
|
1146
1358
|
callSite: (f, a) => f(...a)
|
|
1147
1359
|
});
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
onSessionAuth: onNetworkConnection
|
|
1155
|
-
});
|
|
1156
|
-
const space = new Space({
|
|
1157
|
-
spaceKey,
|
|
1158
|
-
protocol,
|
|
1159
|
-
genesisFeed,
|
|
1160
|
-
feedProvider: (feedKey) => this._feedStore.openFeed(feedKey)
|
|
1360
|
+
await this._pipeline.stop();
|
|
1361
|
+
log9("stopped", {}, {
|
|
1362
|
+
file: "control-pipeline.ts",
|
|
1363
|
+
line: 99,
|
|
1364
|
+
scope: this,
|
|
1365
|
+
callSite: (f, a) => f(...a)
|
|
1161
1366
|
});
|
|
1162
|
-
this._spaces.set(space.key, space);
|
|
1163
|
-
return space;
|
|
1164
1367
|
}
|
|
1165
1368
|
};
|
|
1166
|
-
__decorate6([
|
|
1167
|
-
synchronized4
|
|
1168
|
-
], SpaceManager.prototype, "open", null);
|
|
1169
|
-
__decorate6([
|
|
1170
|
-
synchronized4
|
|
1171
|
-
], SpaceManager.prototype, "close", null);
|
|
1172
|
-
SpaceManager = __decorate6([
|
|
1173
|
-
trackLeaks2("open", "close")
|
|
1174
|
-
], SpaceManager);
|
|
1175
1369
|
|
|
1176
|
-
// packages/core/echo/echo-pipeline/src/space/
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
assertion
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
await signingContext.credentialSigner.createCredential({
|
|
1215
|
-
subject: (_c = space.dataFeedKey) != null ? _c : failUndefined2(),
|
|
1216
|
-
assertion: {
|
|
1217
|
-
"@type": "dxos.halo.credentials.AdmittedFeed",
|
|
1218
|
-
spaceKey: space.key,
|
|
1219
|
-
identityKey: signingContext.identityKey,
|
|
1220
|
-
deviceKey: signingContext.deviceKey,
|
|
1221
|
-
designation: AdmittedFeed3.Designation.DATA
|
|
1370
|
+
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
1371
|
+
var __decorate6 = function(decorators, target, key, desc) {
|
|
1372
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1373
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1374
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1375
|
+
else
|
|
1376
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
1377
|
+
if (d = decorators[i])
|
|
1378
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1379
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1380
|
+
};
|
|
1381
|
+
var Space = class Space2 {
|
|
1382
|
+
constructor(params) {
|
|
1383
|
+
this._addFeedLock = new Lock();
|
|
1384
|
+
this.onCredentialProcessed = new Callback2();
|
|
1385
|
+
this.stateUpdate = new Event4();
|
|
1386
|
+
// Processes epoch credentials.
|
|
1387
|
+
this._dataPipelineCredentialConsumer = void 0;
|
|
1388
|
+
this._isOpen = false;
|
|
1389
|
+
assert9(params.spaceKey && params.feedProvider);
|
|
1390
|
+
this._key = params.spaceKey;
|
|
1391
|
+
this._genesisFeedKey = params.genesisFeed.key;
|
|
1392
|
+
this._feedProvider = params.feedProvider;
|
|
1393
|
+
this._snapshotManager = params.snapshotManager;
|
|
1394
|
+
this._controlPipeline = new ControlPipeline({
|
|
1395
|
+
spaceKey: params.spaceKey,
|
|
1396
|
+
genesisFeed: params.genesisFeed,
|
|
1397
|
+
feedProvider: params.feedProvider
|
|
1398
|
+
});
|
|
1399
|
+
this._controlPipeline.onFeedAdmitted.set(async (info) => {
|
|
1400
|
+
if (info.assertion.designation === AdmittedFeed2.Designation.DATA) {
|
|
1401
|
+
await this._addFeedLock.executeSynchronized(async () => {
|
|
1402
|
+
if (this._dataPipeline.pipeline) {
|
|
1403
|
+
if (!this._dataPipeline.pipeline.hasFeed(info.key)) {
|
|
1404
|
+
return this._dataPipeline.pipeline.addFeed(await this._feedProvider(info.key));
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1222
1408
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
for (const credential of credentials) {
|
|
1226
|
-
await space.controlPipeline.writer.write({
|
|
1227
|
-
credential: {
|
|
1228
|
-
credential
|
|
1409
|
+
if (!info.key.equals(params.genesisFeed.key)) {
|
|
1410
|
+
this.protocol.addFeed(await params.feedProvider(info.key));
|
|
1229
1411
|
}
|
|
1230
1412
|
});
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
import { ComplexMap as ComplexMap3 } from "@dxos/util";
|
|
1241
|
-
var DataServiceHost = class {
|
|
1242
|
-
constructor(_itemManager, _itemDemuxer, _writeStream) {
|
|
1243
|
-
this._itemManager = _itemManager;
|
|
1244
|
-
this._itemDemuxer = _itemDemuxer;
|
|
1245
|
-
this._writeStream = _writeStream;
|
|
1246
|
-
this._clientTagMap = new ComplexMap3(([feedKey, seq]) => `${feedKey.toHex()}:${seq}`);
|
|
1247
|
-
}
|
|
1248
|
-
/**
|
|
1249
|
-
* Real-time subscription to data objects in a space.
|
|
1250
|
-
*/
|
|
1251
|
-
subscribe() {
|
|
1252
|
-
return new Stream(({ next, ctx }) => {
|
|
1253
|
-
const objects = Array.from(this._itemManager.entities.values()).map((entity) => entity.createSnapshot());
|
|
1254
|
-
next({
|
|
1255
|
-
batch: {
|
|
1256
|
-
objects
|
|
1257
|
-
}
|
|
1258
|
-
});
|
|
1259
|
-
this._itemDemuxer.mutation.on(ctx, (message) => {
|
|
1260
|
-
var _a;
|
|
1261
|
-
const { batch, meta } = message;
|
|
1262
|
-
log10("message", {
|
|
1263
|
-
batch,
|
|
1264
|
-
meta
|
|
1265
|
-
}, {
|
|
1266
|
-
file: "data-service-host.ts",
|
|
1267
|
-
line: 49,
|
|
1268
|
-
scope: this,
|
|
1269
|
-
callSite: (f, a) => f(...a)
|
|
1270
|
-
});
|
|
1271
|
-
const clientTag = this._clientTagMap.get([
|
|
1272
|
-
message.meta.feedKey,
|
|
1273
|
-
message.meta.seq
|
|
1274
|
-
]);
|
|
1275
|
-
(_a = batch.objects) == null ? void 0 : _a.forEach((object) => {
|
|
1276
|
-
setMetadataOnObject(object, meta);
|
|
1277
|
-
});
|
|
1278
|
-
if (clientTag) {
|
|
1279
|
-
tagMutationsInBatch(batch, clientTag);
|
|
1280
|
-
}
|
|
1281
|
-
next({
|
|
1282
|
-
clientTag,
|
|
1283
|
-
feedKey: message.meta.feedKey,
|
|
1284
|
-
seq: message.meta.seq,
|
|
1285
|
-
batch
|
|
1286
|
-
});
|
|
1413
|
+
this._controlPipeline.onCredentialProcessed.set(async (credential) => {
|
|
1414
|
+
await this.onCredentialProcessed.callIfSet(credential);
|
|
1415
|
+
log10("onCredentialProcessed", {
|
|
1416
|
+
credential
|
|
1417
|
+
}, {
|
|
1418
|
+
file: "space.ts",
|
|
1419
|
+
line: 106,
|
|
1420
|
+
scope: this,
|
|
1421
|
+
callSite: (f, a) => f(...a)
|
|
1287
1422
|
});
|
|
1423
|
+
this.stateUpdate.emit();
|
|
1288
1424
|
});
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
const message = {
|
|
1303
|
-
batch: {
|
|
1304
|
-
objects: (_c = request.batch.objects) == null ? void 0 : _c.map((object) => {
|
|
1305
|
-
var _a2;
|
|
1306
|
-
return {
|
|
1307
|
-
...object,
|
|
1308
|
-
mutations: (_a2 = object.mutations) == null ? void 0 : _a2.map((mutation) => ({
|
|
1309
|
-
...mutation,
|
|
1310
|
-
meta: void 0
|
|
1311
|
-
})),
|
|
1312
|
-
meta: void 0
|
|
1313
|
-
};
|
|
1314
|
-
})
|
|
1315
|
-
}
|
|
1316
|
-
};
|
|
1317
|
-
const receipt = await this._writeStream.write(message, {
|
|
1318
|
-
afterWrite: async (receipt2) => {
|
|
1319
|
-
if (request.clientTag) {
|
|
1320
|
-
log10("tag", {
|
|
1321
|
-
clientTag: request.clientTag,
|
|
1322
|
-
feedKey: receipt2.feedKey,
|
|
1323
|
-
seq: receipt2.seq
|
|
1324
|
-
}, {
|
|
1325
|
-
file: "data-service-host.ts",
|
|
1326
|
-
line: 96,
|
|
1327
|
-
scope: this,
|
|
1328
|
-
callSite: (f, a) => f(...a)
|
|
1329
|
-
});
|
|
1330
|
-
this._clientTagMap.set([
|
|
1331
|
-
receipt2.feedKey,
|
|
1332
|
-
receipt2.seq
|
|
1333
|
-
], request.clientTag);
|
|
1425
|
+
this.protocol = params.protocol;
|
|
1426
|
+
this.protocol.addFeed(params.genesisFeed);
|
|
1427
|
+
this._dataPipeline = new DataPipeline({
|
|
1428
|
+
modelFactory: params.modelFactory,
|
|
1429
|
+
metadataStore: params.metadataStore,
|
|
1430
|
+
snapshotManager: params.snapshotManager,
|
|
1431
|
+
memberKey: params.memberKey,
|
|
1432
|
+
spaceKey: this._key,
|
|
1433
|
+
feedInfoProvider: (feedKey) => this._controlPipeline.spaceState.feeds.get(feedKey),
|
|
1434
|
+
snapshotId: params.snapshotId,
|
|
1435
|
+
onPipelineCreated: async (pipeline) => {
|
|
1436
|
+
if (this._dataFeed) {
|
|
1437
|
+
pipeline.setWriteFeed(this._dataFeed);
|
|
1334
1438
|
}
|
|
1439
|
+
await this._addFeedLock.executeSynchronized(async () => {
|
|
1440
|
+
for (const feed of this._controlPipeline.spaceState.feeds.values()) {
|
|
1441
|
+
if (feed.assertion.designation === AdmittedFeed2.Designation.DATA && !pipeline.hasFeed(feed.key)) {
|
|
1442
|
+
await pipeline.addFeed(await this._feedProvider(feed.key));
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1335
1446
|
}
|
|
1336
1447
|
});
|
|
1337
|
-
return receipt;
|
|
1338
1448
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
// packages/core/echo/echo-pipeline/src/dbhost/database-host.ts
|
|
1342
|
-
import { ItemDemuxer } from "@dxos/echo-db";
|
|
1343
|
-
var DatabaseHost = class {
|
|
1344
|
-
constructor(_outboundStream, _snapshot) {
|
|
1345
|
-
this._outboundStream = _outboundStream;
|
|
1346
|
-
this._snapshot = _snapshot;
|
|
1449
|
+
get key() {
|
|
1450
|
+
return this._key;
|
|
1347
1451
|
}
|
|
1348
|
-
get
|
|
1349
|
-
return
|
|
1452
|
+
get isOpen() {
|
|
1453
|
+
return this._isOpen;
|
|
1350
1454
|
}
|
|
1351
|
-
get
|
|
1352
|
-
return this.
|
|
1455
|
+
get genesisFeedKey() {
|
|
1456
|
+
return this._genesisFeedKey;
|
|
1353
1457
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
this.
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1458
|
+
get controlFeedKey() {
|
|
1459
|
+
var _a;
|
|
1460
|
+
return (_a = this._controlFeed) == null ? void 0 : _a.key;
|
|
1461
|
+
}
|
|
1462
|
+
get dataFeedKey() {
|
|
1463
|
+
var _a;
|
|
1464
|
+
return (_a = this._dataFeed) == null ? void 0 : _a.key;
|
|
1465
|
+
}
|
|
1466
|
+
get spaceState() {
|
|
1467
|
+
return this._controlPipeline.spaceState;
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* @test-only
|
|
1471
|
+
*/
|
|
1472
|
+
get controlPipeline() {
|
|
1473
|
+
return this._controlPipeline.pipeline;
|
|
1474
|
+
}
|
|
1475
|
+
get dataPipeline() {
|
|
1476
|
+
return this._dataPipeline;
|
|
1477
|
+
}
|
|
1478
|
+
get snapshotManager() {
|
|
1479
|
+
return this._snapshotManager;
|
|
1480
|
+
}
|
|
1481
|
+
setControlFeed(feed) {
|
|
1482
|
+
assert9(!this._controlFeed, "Control feed already set.");
|
|
1483
|
+
this._controlFeed = feed;
|
|
1484
|
+
this._controlPipeline.setWriteFeed(feed);
|
|
1485
|
+
return this;
|
|
1362
1486
|
}
|
|
1363
|
-
|
|
1487
|
+
setDataFeed(feed) {
|
|
1488
|
+
var _a;
|
|
1489
|
+
assert9(!this._dataFeed, "Data feed already set.");
|
|
1490
|
+
this._dataFeed = feed;
|
|
1491
|
+
(_a = this._dataPipeline.pipeline) == null ? void 0 : _a.setWriteFeed(feed);
|
|
1492
|
+
return this;
|
|
1364
1493
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1494
|
+
/**
|
|
1495
|
+
* Use for diagnostics.
|
|
1496
|
+
*/
|
|
1497
|
+
getControlFeeds() {
|
|
1498
|
+
return Array.from(this._controlPipeline.spaceState.feeds.values());
|
|
1367
1499
|
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1500
|
+
/**
|
|
1501
|
+
* Use for diagnostics.
|
|
1502
|
+
*/
|
|
1503
|
+
// getDataFeeds(): FeedInfo[] {
|
|
1504
|
+
// return this._dataPipeline?.getFeeds();
|
|
1505
|
+
// }
|
|
1506
|
+
async open() {
|
|
1507
|
+
log10("opening...", {}, {
|
|
1508
|
+
file: "space.ts",
|
|
1509
|
+
line: 208,
|
|
1510
|
+
scope: this,
|
|
1511
|
+
callSite: (f, a) => f(...a)
|
|
1512
|
+
});
|
|
1513
|
+
if (this._isOpen) {
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
await this._controlPipeline.start();
|
|
1517
|
+
await this.protocol.start();
|
|
1518
|
+
this._dataPipelineCredentialConsumer = this._controlPipeline.spaceState.registerProcessor(this._dataPipeline.createCredentialProcessor());
|
|
1519
|
+
this._isOpen = true;
|
|
1520
|
+
log10("opened", {}, {
|
|
1521
|
+
file: "space.ts",
|
|
1522
|
+
line: 222,
|
|
1523
|
+
scope: this,
|
|
1524
|
+
callSite: (f, a) => f(...a)
|
|
1525
|
+
});
|
|
1370
1526
|
}
|
|
1371
|
-
|
|
1527
|
+
async close() {
|
|
1372
1528
|
var _a;
|
|
1373
|
-
|
|
1529
|
+
log10("closing...", {
|
|
1530
|
+
key: this._key
|
|
1531
|
+
}, {
|
|
1532
|
+
file: "space.ts",
|
|
1533
|
+
line: 227,
|
|
1534
|
+
scope: this,
|
|
1535
|
+
callSite: (f, a) => f(...a)
|
|
1536
|
+
});
|
|
1537
|
+
if (!this._isOpen) {
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
await ((_a = this._dataPipelineCredentialConsumer) == null ? void 0 : _a.close());
|
|
1541
|
+
this._dataPipelineCredentialConsumer = void 0;
|
|
1542
|
+
await this._dataPipeline.close();
|
|
1543
|
+
await this.protocol.stop();
|
|
1544
|
+
await this._controlPipeline.stop();
|
|
1545
|
+
this._isOpen = false;
|
|
1546
|
+
log10("closed", {}, {
|
|
1547
|
+
file: "space.ts",
|
|
1548
|
+
line: 241,
|
|
1549
|
+
scope: this,
|
|
1550
|
+
callSite: (f, a) => f(...a)
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
async initializeDataPipeline() {
|
|
1554
|
+
log10.info("initializeDataPipeline", {}, {
|
|
1555
|
+
file: "space.ts",
|
|
1556
|
+
line: 245,
|
|
1557
|
+
scope: this,
|
|
1558
|
+
callSite: (f, a) => f(...a)
|
|
1559
|
+
});
|
|
1560
|
+
assert9(this._isOpen, "Space must be open to initialize data pipeline.");
|
|
1561
|
+
await this._dataPipeline.open();
|
|
1562
|
+
await this._dataPipelineCredentialConsumer.open();
|
|
1374
1563
|
}
|
|
1375
1564
|
};
|
|
1565
|
+
__decorate6([
|
|
1566
|
+
logInfo
|
|
1567
|
+
], Space.prototype, "key", null);
|
|
1568
|
+
__decorate6([
|
|
1569
|
+
synchronized4
|
|
1570
|
+
], Space.prototype, "open", null);
|
|
1571
|
+
__decorate6([
|
|
1572
|
+
synchronized4
|
|
1573
|
+
], Space.prototype, "close", null);
|
|
1574
|
+
Space = __decorate6([
|
|
1575
|
+
trackLeaks3("open", "close")
|
|
1576
|
+
], Space);
|
|
1376
1577
|
|
|
1377
|
-
// packages/core/echo/echo-pipeline/src/
|
|
1378
|
-
import {
|
|
1379
|
-
import {
|
|
1380
|
-
import {
|
|
1578
|
+
// packages/core/echo/echo-pipeline/src/space/space-protocol.ts
|
|
1579
|
+
import { discoveryKey, sha256 } from "@dxos/crypto";
|
|
1580
|
+
import { PublicKey as PublicKey4 } from "@dxos/keys";
|
|
1581
|
+
import { log as log11, logInfo as logInfo2 } from "@dxos/log";
|
|
1582
|
+
import { MMSTTopology } from "@dxos/network-manager";
|
|
1583
|
+
import { Teleport } from "@dxos/teleport";
|
|
1584
|
+
import { ReplicatorExtension } from "@dxos/teleport-extension-replicator";
|
|
1585
|
+
import { ComplexMap as ComplexMap4 } from "@dxos/util";
|
|
1381
1586
|
var __decorate7 = function(decorators, target, key, desc) {
|
|
1382
1587
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1383
1588
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
@@ -1388,154 +1593,180 @@ var __decorate7 = function(decorators, target, key, desc) {
|
|
|
1388
1593
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1389
1594
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1390
1595
|
};
|
|
1391
|
-
var
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
this.
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
return {
|
|
1402
|
-
id,
|
|
1403
|
-
payload: schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").encodeAsAny(snapshot)
|
|
1404
|
-
};
|
|
1405
|
-
},
|
|
1406
|
-
setObject: async (data) => {
|
|
1407
|
-
const snapshot = schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(data.payload);
|
|
1408
|
-
await this._snapshotStore.saveSnapshot(snapshot);
|
|
1409
|
-
}
|
|
1410
|
-
});
|
|
1411
|
-
}
|
|
1412
|
-
get objectSync() {
|
|
1413
|
-
return this._objectSync;
|
|
1414
|
-
}
|
|
1415
|
-
async open() {
|
|
1416
|
-
await this._objectSync.open();
|
|
1417
|
-
}
|
|
1418
|
-
async close() {
|
|
1419
|
-
await this._objectSync.close();
|
|
1596
|
+
var MOCK_AUTH_PROVIDER = async (nonce) => Buffer.from("mock");
|
|
1597
|
+
var MOCK_AUTH_VERIFIER = async (nonce, credential) => true;
|
|
1598
|
+
var SpaceProtocol = class {
|
|
1599
|
+
constructor({ topic, swarmIdentity, networkManager, onSessionAuth }) {
|
|
1600
|
+
this._feeds = /* @__PURE__ */ new Set();
|
|
1601
|
+
this._sessions = new ComplexMap4(PublicKey4.hash);
|
|
1602
|
+
this._networkManager = networkManager;
|
|
1603
|
+
this._swarmIdentity = swarmIdentity;
|
|
1604
|
+
this._onSessionAuth = onSessionAuth;
|
|
1605
|
+
this._topic = PublicKey4.from(discoveryKey(sha256(topic.toHex())));
|
|
1420
1606
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
if (local) {
|
|
1424
|
-
return local;
|
|
1425
|
-
}
|
|
1426
|
-
const remote = await this._objectSync.download(id);
|
|
1427
|
-
return schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(remote.payload);
|
|
1607
|
+
get sessions() {
|
|
1608
|
+
return this._sessions;
|
|
1428
1609
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
return id;
|
|
1610
|
+
get feeds() {
|
|
1611
|
+
return this._feeds;
|
|
1432
1612
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
trackLeaks3("open", "close")
|
|
1436
|
-
], SnapshotManager);
|
|
1437
|
-
|
|
1438
|
-
// packages/core/echo/echo-pipeline/src/dbhost/snapshot-store.ts
|
|
1439
|
-
import { subtleCrypto } from "@dxos/crypto";
|
|
1440
|
-
import { schema as schema5 } from "@dxos/protocols";
|
|
1441
|
-
var SnapshotStore = class {
|
|
1442
|
-
// prettier-ignore
|
|
1443
|
-
constructor(_directory) {
|
|
1444
|
-
this._directory = _directory;
|
|
1613
|
+
get _ownPeerKey() {
|
|
1614
|
+
return this._swarmIdentity.peerKey;
|
|
1445
1615
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1616
|
+
// TODO(burdon): Create abstraction for Space (e.g., add keys and have provider).
|
|
1617
|
+
addFeed(feed) {
|
|
1618
|
+
log11("addFeed", {
|
|
1619
|
+
key: feed.key
|
|
1620
|
+
}, {
|
|
1621
|
+
file: "space-protocol.ts",
|
|
1622
|
+
line: 84,
|
|
1623
|
+
scope: this,
|
|
1624
|
+
callSite: (f, a) => f(...a)
|
|
1625
|
+
});
|
|
1626
|
+
this._feeds.add(feed);
|
|
1627
|
+
for (const session of this._sessions.values()) {
|
|
1628
|
+
session.replicator.addFeed(feed);
|
|
1455
1629
|
}
|
|
1456
|
-
return keyString;
|
|
1457
1630
|
}
|
|
1458
|
-
async
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
const { size } = await file.stat();
|
|
1462
|
-
if (size === 0) {
|
|
1463
|
-
return void 0;
|
|
1464
|
-
}
|
|
1465
|
-
const buffer = await file.read(0, size);
|
|
1466
|
-
return schema5.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(buffer);
|
|
1467
|
-
} finally {
|
|
1468
|
-
await file.close();
|
|
1631
|
+
async start() {
|
|
1632
|
+
if (this._connection) {
|
|
1633
|
+
return;
|
|
1469
1634
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
var DataServiceSubscriptions = class {
|
|
1480
|
-
constructor() {
|
|
1481
|
-
this._spaces = new ComplexMap4(PublicKey5.hash);
|
|
1482
|
-
}
|
|
1483
|
-
clear() {
|
|
1484
|
-
this._spaces.clear();
|
|
1485
|
-
}
|
|
1486
|
-
registerSpace(spaceKey, host) {
|
|
1487
|
-
log11("Registering space", {
|
|
1488
|
-
spaceKey
|
|
1489
|
-
}, {
|
|
1490
|
-
file: "data-service.ts",
|
|
1491
|
-
line: 31,
|
|
1635
|
+
const credentials = await this._swarmIdentity.credentialProvider(Buffer.from(""));
|
|
1636
|
+
const topologyConfig = {
|
|
1637
|
+
originateConnections: 4,
|
|
1638
|
+
maxPeers: 10,
|
|
1639
|
+
sampleSize: 20
|
|
1640
|
+
};
|
|
1641
|
+
log11("starting...", {}, {
|
|
1642
|
+
file: "space-protocol.ts",
|
|
1643
|
+
line: 107,
|
|
1492
1644
|
scope: this,
|
|
1493
1645
|
callSite: (f, a) => f(...a)
|
|
1494
1646
|
});
|
|
1495
|
-
this.
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1647
|
+
this._connection = await this._networkManager.joinSwarm({
|
|
1648
|
+
protocolProvider: this._createProtocolProvider(credentials),
|
|
1649
|
+
peerId: this._swarmIdentity.peerKey,
|
|
1650
|
+
topic: this._topic,
|
|
1651
|
+
topology: new MMSTTopology(topologyConfig),
|
|
1652
|
+
label: `Protocol swarm: ${this._topic}`
|
|
1653
|
+
});
|
|
1654
|
+
log11("started", {}, {
|
|
1655
|
+
file: "space-protocol.ts",
|
|
1656
|
+
line: 116,
|
|
1503
1657
|
scope: this,
|
|
1504
1658
|
callSite: (f, a) => f(...a)
|
|
1505
1659
|
});
|
|
1506
|
-
this._spaces.delete(spaceKey);
|
|
1507
1660
|
}
|
|
1508
|
-
|
|
1509
|
-
|
|
1661
|
+
async stop() {
|
|
1662
|
+
if (this._connection) {
|
|
1663
|
+
log11("stopping...", {}, {
|
|
1664
|
+
file: "space-protocol.ts",
|
|
1665
|
+
line: 121,
|
|
1666
|
+
scope: this,
|
|
1667
|
+
callSite: (f, a) => f(...a)
|
|
1668
|
+
});
|
|
1669
|
+
await this._connection.close();
|
|
1670
|
+
log11("stopped", {}, {
|
|
1671
|
+
file: "space-protocol.ts",
|
|
1672
|
+
line: 123,
|
|
1673
|
+
scope: this,
|
|
1674
|
+
callSite: (f, a) => f(...a)
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
_createProtocolProvider(credentials) {
|
|
1679
|
+
return (wireParams) => {
|
|
1680
|
+
const session = new SpaceProtocolSession({
|
|
1681
|
+
wireParams,
|
|
1682
|
+
swarmIdentity: this._swarmIdentity,
|
|
1683
|
+
onSessionAuth: this._onSessionAuth
|
|
1684
|
+
});
|
|
1685
|
+
this._sessions.set(wireParams.remotePeerId, session);
|
|
1686
|
+
for (const feed of this._feeds) {
|
|
1687
|
+
session.replicator.addFeed(feed);
|
|
1688
|
+
}
|
|
1689
|
+
return session;
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
__decorate7([
|
|
1694
|
+
logInfo2
|
|
1695
|
+
], SpaceProtocol.prototype, "_topic", void 0);
|
|
1696
|
+
__decorate7([
|
|
1697
|
+
logInfo2
|
|
1698
|
+
], SpaceProtocol.prototype, "_ownPeerKey", null);
|
|
1699
|
+
var AuthStatus;
|
|
1700
|
+
(function(AuthStatus2) {
|
|
1701
|
+
AuthStatus2["INITIAL"] = "INITIAL";
|
|
1702
|
+
AuthStatus2["SUCCESS"] = "SUCCESS";
|
|
1703
|
+
AuthStatus2["FAILURE"] = "FAILURE";
|
|
1704
|
+
})(AuthStatus || (AuthStatus = {}));
|
|
1705
|
+
var SpaceProtocolSession = class {
|
|
1706
|
+
// TODO(dmaretskyi): Allow to pass in extra extensions.
|
|
1707
|
+
constructor({ wireParams, swarmIdentity, onSessionAuth }) {
|
|
1708
|
+
// TODO(dmaretskyi): Start with upload=false when switching it on the fly works.
|
|
1709
|
+
this.replicator = new ReplicatorExtension().setOptions({
|
|
1710
|
+
upload: true
|
|
1711
|
+
});
|
|
1712
|
+
this._authStatus = AuthStatus.INITIAL;
|
|
1713
|
+
this._wireParams = wireParams;
|
|
1714
|
+
this._swarmIdentity = swarmIdentity;
|
|
1715
|
+
this._onSessionAuth = onSessionAuth;
|
|
1716
|
+
this._teleport = new Teleport(wireParams);
|
|
1717
|
+
}
|
|
1718
|
+
get authStatus() {
|
|
1719
|
+
return this._authStatus;
|
|
1510
1720
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
constructor(_subscriptions) {
|
|
1514
|
-
this._subscriptions = _subscriptions;
|
|
1721
|
+
get stream() {
|
|
1722
|
+
return this._teleport.stream;
|
|
1515
1723
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1724
|
+
async initialize() {
|
|
1725
|
+
await this._teleport.open();
|
|
1726
|
+
this._teleport.addExtension("dxos.mesh.teleport.auth", new AuthExtension({
|
|
1727
|
+
provider: this._swarmIdentity.credentialProvider,
|
|
1728
|
+
verifier: this._swarmIdentity.credentialAuthenticator,
|
|
1729
|
+
onAuthSuccess: () => {
|
|
1730
|
+
var _a;
|
|
1731
|
+
this._authStatus = AuthStatus.SUCCESS;
|
|
1732
|
+
log11("Peer authenticated", {}, {
|
|
1733
|
+
file: "space-protocol.ts",
|
|
1734
|
+
line: 206,
|
|
1735
|
+
scope: this,
|
|
1736
|
+
callSite: (f, a) => f(...a)
|
|
1737
|
+
});
|
|
1738
|
+
(_a = this._onSessionAuth) == null ? void 0 : _a.call(this, this._teleport);
|
|
1739
|
+
},
|
|
1740
|
+
onAuthFailure: () => {
|
|
1741
|
+
log11.warn("Auth failed", {}, {
|
|
1742
|
+
file: "space-protocol.ts",
|
|
1743
|
+
line: 211,
|
|
1744
|
+
scope: this,
|
|
1745
|
+
callSite: (f, a) => f(...a)
|
|
1746
|
+
});
|
|
1747
|
+
this._authStatus = AuthStatus.FAILURE;
|
|
1748
|
+
}
|
|
1749
|
+
}));
|
|
1750
|
+
this._teleport.addExtension("dxos.mesh.teleport.replicator", this.replicator);
|
|
1521
1751
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
assert8(request.spaceKey);
|
|
1525
|
-
assert8(request.batch);
|
|
1526
|
-
const host = (_a = this._subscriptions.getDataService(request.spaceKey)) != null ? _a : raise(new Error(`space not found: ${request.spaceKey}`));
|
|
1527
|
-
return host.write(request);
|
|
1752
|
+
async destroy() {
|
|
1753
|
+
await this._teleport.close();
|
|
1528
1754
|
}
|
|
1529
1755
|
};
|
|
1756
|
+
__decorate7([
|
|
1757
|
+
logInfo2
|
|
1758
|
+
], SpaceProtocolSession.prototype, "_wireParams", void 0);
|
|
1759
|
+
__decorate7([
|
|
1760
|
+
logInfo2
|
|
1761
|
+
], SpaceProtocolSession.prototype, "authStatus", null);
|
|
1530
1762
|
|
|
1531
|
-
// packages/core/echo/echo-pipeline/src/space/
|
|
1532
|
-
import
|
|
1533
|
-
import {
|
|
1534
|
-
import {
|
|
1535
|
-
import { failUndefined as failUndefined3 } from "@dxos/debug";
|
|
1536
|
-
import { ItemManager } from "@dxos/echo-db";
|
|
1763
|
+
// packages/core/echo/echo-pipeline/src/space/space-manager.ts
|
|
1764
|
+
import { synchronized as synchronized5, trackLeaks as trackLeaks4 } from "@dxos/async";
|
|
1765
|
+
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
1766
|
+
import { PublicKey as PublicKey5 } from "@dxos/keys";
|
|
1537
1767
|
import { log as log12 } from "@dxos/log";
|
|
1538
|
-
import {
|
|
1768
|
+
import { trace } from "@dxos/protocols";
|
|
1769
|
+
import { ComplexMap as ComplexMap5 } from "@dxos/util";
|
|
1539
1770
|
var __decorate8 = function(decorators, target, key, desc) {
|
|
1540
1771
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1541
1772
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
@@ -1546,204 +1777,85 @@ var __decorate8 = function(decorators, target, key, desc) {
|
|
|
1546
1777
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1547
1778
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1548
1779
|
};
|
|
1549
|
-
var
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
this.
|
|
1556
|
-
this.
|
|
1557
|
-
this.
|
|
1558
|
-
this._isOpen = false;
|
|
1559
|
-
this._lastTimeframeSaveTime = 0;
|
|
1560
|
-
this._lastSnapshotSaveTime = 0;
|
|
1561
|
-
}
|
|
1562
|
-
get isOpen() {
|
|
1563
|
-
return this._isOpen;
|
|
1780
|
+
var SpaceManager = class SpaceManager2 {
|
|
1781
|
+
constructor({ feedStore, networkManager, modelFactory, metadataStore, snapshotStore }) {
|
|
1782
|
+
this._spaces = new ComplexMap5(PublicKey5.hash);
|
|
1783
|
+
this._instanceId = PublicKey5.random().toHex();
|
|
1784
|
+
this._feedStore = feedStore;
|
|
1785
|
+
this._networkManager = networkManager;
|
|
1786
|
+
this._modelFactory = modelFactory;
|
|
1787
|
+
this._metadataStore = metadataStore;
|
|
1788
|
+
this._snapshotStore = snapshotStore;
|
|
1564
1789
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
return
|
|
1790
|
+
// TODO(burdon): Remove.
|
|
1791
|
+
get spaces() {
|
|
1792
|
+
return this._spaces;
|
|
1568
1793
|
}
|
|
1569
|
-
|
|
1570
|
-
var _a;
|
|
1571
|
-
return (_a = this._snapshot) == null ? void 0 : _a.timeframe;
|
|
1794
|
+
async open() {
|
|
1572
1795
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1796
|
+
async close() {
|
|
1797
|
+
await Promise.all([
|
|
1798
|
+
...this._spaces.values()
|
|
1799
|
+
].map((space) => space.close()));
|
|
1576
1800
|
}
|
|
1577
|
-
|
|
1801
|
+
async constructSpace({ metadata, swarmIdentity, onNetworkConnection, memberKey }) {
|
|
1578
1802
|
var _a;
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
}
|
|
1587
|
-
this._spaceContext = spaceContext;
|
|
1588
|
-
if (this._params.snapshotId && !DISABLE_SNAPSHOT_CACHE) {
|
|
1589
|
-
this._snapshot = await this._params.snapshotManager.load(this._params.snapshotId);
|
|
1590
|
-
this._lastAutomaticSnapshotTimeframe = (_b = (_a = this._snapshot) == null ? void 0 : _a.timeframe) != null ? _b : new Timeframe3();
|
|
1591
|
-
}
|
|
1592
|
-
this._pipeline = await this._spaceContext.openPipeline(this.getStartTimeframe());
|
|
1593
|
-
if (this._targetTimeframe) {
|
|
1594
|
-
this._pipeline.state.setTargetTimeframe(this._targetTimeframe);
|
|
1595
|
-
}
|
|
1596
|
-
const feedWriter = createMappedFeedWriter((data) => ({
|
|
1597
|
-
data
|
|
1598
|
-
}), (_c = this._pipeline.writer) != null ? _c : failUndefined3());
|
|
1599
|
-
this.databaseBackend = new DatabaseHost(feedWriter, (_d = this._snapshot) == null ? void 0 : _d.database);
|
|
1600
|
-
this._itemManager = new ItemManager(this._params.modelFactory);
|
|
1601
|
-
await this.databaseBackend.open(this._itemManager, this._params.modelFactory);
|
|
1602
|
-
scheduleTask2(this._ctx, async () => {
|
|
1603
|
-
await this._consumePipeline();
|
|
1803
|
+
log12.trace("dxos.echo.space-manager.construct-space", trace.begin({
|
|
1804
|
+
id: this._instanceId
|
|
1805
|
+
}), {
|
|
1806
|
+
file: "space-manager.ts",
|
|
1807
|
+
line: 74,
|
|
1808
|
+
scope: this,
|
|
1809
|
+
callSite: (f, a) => f(...a)
|
|
1604
1810
|
});
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1612
|
-
log12("close", {}, {
|
|
1613
|
-
file: "data-pipeline.ts",
|
|
1614
|
-
line: 145,
|
|
1811
|
+
log12("constructing space...", {
|
|
1812
|
+
spaceKey: metadata.genesisFeedKey
|
|
1813
|
+
}, {
|
|
1814
|
+
file: "space-manager.ts",
|
|
1815
|
+
line: 75,
|
|
1615
1816
|
scope: this,
|
|
1616
1817
|
callSite: (f, a) => f(...a)
|
|
1617
1818
|
});
|
|
1618
|
-
this.
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
file: "data-pipeline.ts",
|
|
1648
|
-
line: 172,
|
|
1649
|
-
scope: this,
|
|
1650
|
-
callSite: (f, a) => f(...a)
|
|
1651
|
-
});
|
|
1652
|
-
try {
|
|
1653
|
-
if (data.payload.data) {
|
|
1654
|
-
const feedInfo = this._params.feedInfoProvider(feedKey);
|
|
1655
|
-
if (!feedInfo) {
|
|
1656
|
-
log12.error("Could not find feed.", {
|
|
1657
|
-
feedKey
|
|
1658
|
-
}, {
|
|
1659
|
-
file: "data-pipeline.ts",
|
|
1660
|
-
line: 178,
|
|
1661
|
-
scope: this,
|
|
1662
|
-
callSite: (f, a) => f(...a)
|
|
1663
|
-
});
|
|
1664
|
-
continue;
|
|
1665
|
-
}
|
|
1666
|
-
await this.databaseBackend.echoProcessor({
|
|
1667
|
-
batch: data.payload.data.batch,
|
|
1668
|
-
meta: {
|
|
1669
|
-
feedKey,
|
|
1670
|
-
seq,
|
|
1671
|
-
timeframe: data.timeframe,
|
|
1672
|
-
memberKey: feedInfo.assertion.identityKey
|
|
1673
|
-
}
|
|
1674
|
-
});
|
|
1675
|
-
await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
|
|
1676
|
-
}
|
|
1677
|
-
} catch (err) {
|
|
1678
|
-
log12.catch(err, {}, {
|
|
1679
|
-
file: "data-pipeline.ts",
|
|
1680
|
-
line: 196,
|
|
1681
|
-
scope: this,
|
|
1682
|
-
callSite: (f, a) => f(...a)
|
|
1683
|
-
});
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
_createSnapshot(timeframe) {
|
|
1688
|
-
assert9(this.databaseBackend, "Database backend is not initialized.");
|
|
1689
|
-
return {
|
|
1690
|
-
spaceKey: this._params.spaceKey.asUint8Array(),
|
|
1691
|
-
timeframe,
|
|
1692
|
-
database: this.databaseBackend.createSnapshot()
|
|
1693
|
-
};
|
|
1694
|
-
}
|
|
1695
|
-
async _saveSnapshot(timeframe) {
|
|
1696
|
-
const snapshot = await this._createSnapshot(timeframe);
|
|
1697
|
-
const snapshotKey = await this._params.snapshotManager.store(snapshot);
|
|
1698
|
-
await this._params.metadataStore.setSpaceSnapshot(this._params.spaceKey, snapshotKey);
|
|
1699
|
-
return snapshot;
|
|
1700
|
-
}
|
|
1701
|
-
async _saveTargetTimeframe(timeframe) {
|
|
1702
|
-
var _a;
|
|
1703
|
-
const newTimeframe = Timeframe3.merge((_a = this._targetTimeframe) != null ? _a : new Timeframe3(), timeframe);
|
|
1704
|
-
await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, newTimeframe);
|
|
1705
|
-
this._targetTimeframe = newTimeframe;
|
|
1706
|
-
}
|
|
1707
|
-
async _noteTargetStateIfNeeded(timeframe) {
|
|
1708
|
-
var _a;
|
|
1709
|
-
if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL) {
|
|
1710
|
-
this._lastTimeframeSaveTime = Date.now();
|
|
1711
|
-
await this._saveTargetTimeframe(timeframe);
|
|
1712
|
-
}
|
|
1713
|
-
if (!DISABLE_SNAPSHOT_CACHE && Date.now() - this._lastSnapshotSaveTime > AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL && timeframe.totalMessages() - this._lastAutomaticSnapshotTimeframe.totalMessages() > MESSAGES_PER_SNAPSHOT) {
|
|
1714
|
-
this._lastSnapshotSaveTime = Date.now();
|
|
1715
|
-
const snapshot = await this._saveSnapshot(timeframe);
|
|
1716
|
-
this._lastAutomaticSnapshotTimeframe = (_a = snapshot.timeframe) != null ? _a : failUndefined3();
|
|
1717
|
-
log12("save", {
|
|
1718
|
-
snapshot
|
|
1719
|
-
}, {
|
|
1720
|
-
file: "data-pipeline.ts",
|
|
1721
|
-
line: 239,
|
|
1722
|
-
scope: this,
|
|
1723
|
-
callSite: (f, a) => f(...a)
|
|
1724
|
-
});
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
async waitUntilTimeframe(timeframe) {
|
|
1728
|
-
assert9(this._pipeline, "Pipeline is not initialized.");
|
|
1729
|
-
await this._pipeline.state.waitUntilTimeframe(timeframe);
|
|
1819
|
+
const genesisFeed = await this._feedStore.openFeed((_a = metadata.genesisFeedKey) != null ? _a : failUndefined2());
|
|
1820
|
+
const spaceKey = metadata.key;
|
|
1821
|
+
const protocol = new SpaceProtocol({
|
|
1822
|
+
topic: spaceKey,
|
|
1823
|
+
swarmIdentity,
|
|
1824
|
+
networkManager: this._networkManager,
|
|
1825
|
+
onSessionAuth: onNetworkConnection
|
|
1826
|
+
});
|
|
1827
|
+
const snapshotManager = new SnapshotManager(this._snapshotStore);
|
|
1828
|
+
const space = new Space({
|
|
1829
|
+
spaceKey,
|
|
1830
|
+
protocol,
|
|
1831
|
+
genesisFeed,
|
|
1832
|
+
feedProvider: (feedKey) => this._feedStore.openFeed(feedKey),
|
|
1833
|
+
modelFactory: this._modelFactory,
|
|
1834
|
+
metadataStore: this._metadataStore,
|
|
1835
|
+
snapshotManager,
|
|
1836
|
+
memberKey
|
|
1837
|
+
});
|
|
1838
|
+
this._spaces.set(space.key, space);
|
|
1839
|
+
log12.trace("dxos.echo.space-manager.construct-space", trace.end({
|
|
1840
|
+
id: this._instanceId
|
|
1841
|
+
}), {
|
|
1842
|
+
file: "space-manager.ts",
|
|
1843
|
+
line: 100,
|
|
1844
|
+
scope: this,
|
|
1845
|
+
callSite: (f, a) => f(...a)
|
|
1846
|
+
});
|
|
1847
|
+
return space;
|
|
1730
1848
|
}
|
|
1731
1849
|
};
|
|
1732
1850
|
__decorate8([
|
|
1733
1851
|
synchronized5
|
|
1734
|
-
],
|
|
1852
|
+
], SpaceManager.prototype, "open", null);
|
|
1735
1853
|
__decorate8([
|
|
1736
1854
|
synchronized5
|
|
1737
|
-
],
|
|
1738
|
-
|
|
1855
|
+
], SpaceManager.prototype, "close", null);
|
|
1856
|
+
SpaceManager = __decorate8([
|
|
1739
1857
|
trackLeaks4("open", "close")
|
|
1740
|
-
],
|
|
1741
|
-
var snapshotTimeframeToStartingTimeframe = (snapshotTimeframe) => {
|
|
1742
|
-
return snapshotTimeframe.map(([key, seq]) => [
|
|
1743
|
-
key,
|
|
1744
|
-
seq + 1
|
|
1745
|
-
]);
|
|
1746
|
-
};
|
|
1858
|
+
], SpaceManager);
|
|
1747
1859
|
|
|
1748
1860
|
export {
|
|
1749
1861
|
STORAGE_VERSION,
|
|
@@ -1757,20 +1869,19 @@ export {
|
|
|
1757
1869
|
TimeframeClock,
|
|
1758
1870
|
Pipeline,
|
|
1759
1871
|
AuthExtension,
|
|
1760
|
-
Space,
|
|
1761
|
-
MOCK_AUTH_PROVIDER,
|
|
1762
|
-
MOCK_AUTH_VERIFIER,
|
|
1763
|
-
SpaceProtocol,
|
|
1764
|
-
AuthStatus,
|
|
1765
|
-
SpaceProtocolSession,
|
|
1766
|
-
SpaceManager,
|
|
1767
|
-
spaceGenesis,
|
|
1768
1872
|
DataServiceHost,
|
|
1769
1873
|
DatabaseHost,
|
|
1770
1874
|
SnapshotManager,
|
|
1771
1875
|
SnapshotStore,
|
|
1772
1876
|
DataServiceSubscriptions,
|
|
1773
1877
|
DataServiceImpl,
|
|
1774
|
-
DataPipeline
|
|
1878
|
+
DataPipeline,
|
|
1879
|
+
Space,
|
|
1880
|
+
MOCK_AUTH_PROVIDER,
|
|
1881
|
+
MOCK_AUTH_VERIFIER,
|
|
1882
|
+
SpaceProtocol,
|
|
1883
|
+
AuthStatus,
|
|
1884
|
+
SpaceProtocolSession,
|
|
1885
|
+
SpaceManager
|
|
1775
1886
|
};
|
|
1776
|
-
//# sourceMappingURL=chunk-
|
|
1887
|
+
//# sourceMappingURL=chunk-2NGLSBL4.mjs.map
|