@dxos/echo-pipeline 0.6.5 → 0.6.6-staging.582ce24
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-2MII6KJX.mjs → chunk-P6XSIJKM.mjs} +2184 -2132
- package/dist/lib/browser/chunk-P6XSIJKM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +8 -8
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-6MWU4MHX.cjs → chunk-IYTGTZ7D.cjs} +2177 -2125
- package/dist/lib/node/chunk-IYTGTZ7D.cjs.map +7 -0
- package/dist/lib/node/index.cjs +35 -35
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +18 -18
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/automerge/automerge-host.d.ts +1 -0
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts +2 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-replicator.d.ts +10 -1
- package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/network-protocol.d.ts +3 -28
- package/dist/types/src/automerge/network-protocol.d.ts.map +1 -1
- package/dist/types/src/space/space-manager.d.ts +3 -1
- package/dist/types/src/space/space-manager.d.ts.map +1 -1
- package/dist/types/src/space/space-protocol.d.ts +10 -3
- package/dist/types/src/space/space-protocol.d.ts.map +1 -1
- package/dist/types/src/space/space.d.ts.map +1 -1
- package/dist/types/src/testing/test-network-adapter.d.ts +2 -1
- package/dist/types/src/testing/test-network-adapter.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-host.ts +13 -1
- package/src/automerge/automerge-repo.test.ts +380 -366
- package/src/automerge/echo-network-adapter.test.ts +1 -0
- package/src/automerge/echo-network-adapter.ts +8 -0
- package/src/automerge/echo-replicator.ts +11 -1
- package/src/automerge/mesh-echo-replicator-connection.ts +18 -0
- package/src/automerge/mesh-echo-replicator.ts +10 -2
- package/src/automerge/network-protocol.ts +8 -34
- package/src/space/space-manager.ts +15 -2
- package/src/space/space-protocol.ts +42 -5
- package/src/space/space.ts +4 -4
- package/src/testing/test-network-adapter.ts +5 -3
- package/dist/lib/browser/chunk-2MII6KJX.mjs.map +0 -7
- package/dist/lib/node/chunk-6MWU4MHX.cjs.map +0 -7
|
@@ -434,138 +434,121 @@ var diffCollectionState = (local, remote) => {
|
|
|
434
434
|
};
|
|
435
435
|
};
|
|
436
436
|
|
|
437
|
-
// packages/core/echo/echo-pipeline/src/
|
|
438
|
-
import {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
} catch (err) {
|
|
457
|
-
if (isLevelDbNotFoundError(err)) {
|
|
458
|
-
return void 0;
|
|
459
|
-
}
|
|
460
|
-
throw err;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
async save(keyArray, binary) {
|
|
464
|
-
if (this._lifecycleState !== LifecycleState.OPEN) {
|
|
465
|
-
return void 0;
|
|
466
|
-
}
|
|
467
|
-
const startMs = Date.now();
|
|
468
|
-
const batch = this._params.db.batch();
|
|
469
|
-
await this._params.callbacks?.beforeSave?.({
|
|
470
|
-
path: keyArray,
|
|
471
|
-
batch
|
|
437
|
+
// packages/core/echo/echo-pipeline/src/space/auth.ts
|
|
438
|
+
import { runInContext, scheduleTask as scheduleTask2 } from "@dxos/async";
|
|
439
|
+
import { Context } from "@dxos/context";
|
|
440
|
+
import { randomBytes } from "@dxos/crypto";
|
|
441
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
442
|
+
import { log as log2 } from "@dxos/log";
|
|
443
|
+
import { schema as schema4 } from "@dxos/protocols";
|
|
444
|
+
import { RpcExtension } from "@dxos/teleport";
|
|
445
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/auth.ts";
|
|
446
|
+
var AuthExtension = class extends RpcExtension {
|
|
447
|
+
constructor(_authParams) {
|
|
448
|
+
super({
|
|
449
|
+
requested: {
|
|
450
|
+
AuthService: schema4.getService("dxos.mesh.teleport.auth.AuthService")
|
|
451
|
+
},
|
|
452
|
+
exposed: {
|
|
453
|
+
AuthService: schema4.getService("dxos.mesh.teleport.auth.AuthService")
|
|
454
|
+
},
|
|
455
|
+
timeout: 60 * 1e3
|
|
472
456
|
});
|
|
473
|
-
|
|
474
|
-
|
|
457
|
+
this._authParams = _authParams;
|
|
458
|
+
this._ctx = new Context({
|
|
459
|
+
onError: (err) => {
|
|
460
|
+
log2.catch(err, void 0, {
|
|
461
|
+
F: __dxlog_file3,
|
|
462
|
+
L: 28,
|
|
463
|
+
S: this,
|
|
464
|
+
C: (f, a) => f(...a)
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}, {
|
|
468
|
+
F: __dxlog_file3,
|
|
469
|
+
L: 26
|
|
475
470
|
});
|
|
476
|
-
await batch.write();
|
|
477
|
-
this._params.monitor?.recordBytesStored(binary.byteLength);
|
|
478
|
-
await this._params.callbacks?.afterSave?.(keyArray);
|
|
479
|
-
this._params.monitor?.recordStoreDuration(Date.now() - startMs);
|
|
480
471
|
}
|
|
481
|
-
async
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
472
|
+
async getHandlers() {
|
|
473
|
+
return {
|
|
474
|
+
AuthService: {
|
|
475
|
+
authenticate: async ({ challenge }) => {
|
|
476
|
+
try {
|
|
477
|
+
const credential = await this._authParams.provider(challenge);
|
|
478
|
+
if (!credential) {
|
|
479
|
+
throw new Error("auth rejected");
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
credential
|
|
483
|
+
};
|
|
484
|
+
} catch (err) {
|
|
485
|
+
log2.error("failed to generate auth credentials", err, {
|
|
486
|
+
F: __dxlog_file3,
|
|
487
|
+
L: 55,
|
|
488
|
+
S: this,
|
|
489
|
+
C: (f, a) => f(...a)
|
|
490
|
+
});
|
|
491
|
+
throw new Error("auth rejected");
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
async onOpen(context) {
|
|
498
|
+
await super.onOpen(context);
|
|
499
|
+
scheduleTask2(this._ctx, async () => {
|
|
500
|
+
try {
|
|
501
|
+
const challenge = randomBytes(32);
|
|
502
|
+
const { credential } = await this.rpc.AuthService.authenticate({
|
|
503
|
+
challenge
|
|
504
|
+
});
|
|
505
|
+
invariant3(credential?.length > 0, "invalid credential", {
|
|
506
|
+
F: __dxlog_file3,
|
|
507
|
+
L: 69,
|
|
508
|
+
S: this,
|
|
509
|
+
A: [
|
|
510
|
+
"credential?.length > 0",
|
|
511
|
+
"'invalid credential'"
|
|
512
|
+
]
|
|
513
|
+
});
|
|
514
|
+
const success = await this._authParams.verifier(challenge, credential);
|
|
515
|
+
invariant3(success, "credential not verified", {
|
|
516
|
+
F: __dxlog_file3,
|
|
517
|
+
L: 71,
|
|
518
|
+
S: this,
|
|
519
|
+
A: [
|
|
520
|
+
"success",
|
|
521
|
+
"'credential not verified'"
|
|
522
|
+
]
|
|
523
|
+
});
|
|
524
|
+
runInContext(this._ctx, () => this._authParams.onAuthSuccess());
|
|
525
|
+
} catch (err) {
|
|
526
|
+
log2("auth failed", err, {
|
|
527
|
+
F: __dxlog_file3,
|
|
528
|
+
L: 74,
|
|
529
|
+
S: this,
|
|
530
|
+
C: (f, a) => f(...a)
|
|
531
|
+
});
|
|
532
|
+
this.close();
|
|
533
|
+
this._authParams.onAuthFailure();
|
|
534
|
+
}
|
|
487
535
|
});
|
|
488
536
|
}
|
|
489
|
-
async
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
const startMs = Date.now();
|
|
494
|
-
const result = [];
|
|
495
|
-
for await (const [key, value] of this._params.db.iterator({
|
|
496
|
-
gte: keyPrefix,
|
|
497
|
-
lte: [
|
|
498
|
-
...keyPrefix,
|
|
499
|
-
"\uFFFF"
|
|
500
|
-
],
|
|
501
|
-
...encodingOptions
|
|
502
|
-
})) {
|
|
503
|
-
result.push({
|
|
504
|
-
key,
|
|
505
|
-
data: value
|
|
506
|
-
});
|
|
507
|
-
this._params.monitor?.recordBytesLoaded(value.byteLength);
|
|
508
|
-
}
|
|
509
|
-
this._params.monitor?.recordLoadDuration(Date.now() - startMs);
|
|
510
|
-
return result;
|
|
537
|
+
async onClose() {
|
|
538
|
+
await this._ctx.dispose();
|
|
539
|
+
await super.onClose();
|
|
511
540
|
}
|
|
512
|
-
async
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
const batch = this._params.db.batch();
|
|
517
|
-
for await (const [key] of this._params.db.iterator({
|
|
518
|
-
gte: keyPrefix,
|
|
519
|
-
lte: [
|
|
520
|
-
...keyPrefix,
|
|
521
|
-
"\uFFFF"
|
|
522
|
-
],
|
|
523
|
-
...encodingOptions
|
|
524
|
-
})) {
|
|
525
|
-
batch.del(key, {
|
|
526
|
-
...encodingOptions
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
await batch.write();
|
|
541
|
+
async onAbort() {
|
|
542
|
+
await this._ctx.dispose();
|
|
543
|
+
await super.onAbort();
|
|
530
544
|
}
|
|
531
545
|
};
|
|
532
|
-
var keyEncoder = {
|
|
533
|
-
encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
|
|
534
|
-
decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%")),
|
|
535
|
-
format: "buffer"
|
|
536
|
-
};
|
|
537
|
-
var encodingOptions = {
|
|
538
|
-
keyEncoding: keyEncoder,
|
|
539
|
-
valueEncoding: "buffer"
|
|
540
|
-
};
|
|
541
|
-
var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
|
|
542
546
|
|
|
543
|
-
// packages/core/echo/echo-pipeline/src/
|
|
544
|
-
import { Event as Event2
|
|
545
|
-
import {
|
|
546
|
-
import { Repo } from "@dxos/automerge/automerge-repo";
|
|
547
|
-
import { Context, Resource as Resource4, cancelWithContext as cancelWithContext2 } from "@dxos/context";
|
|
548
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
549
|
-
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
547
|
+
// packages/core/echo/echo-pipeline/src/pipeline/timeframe-clock.ts
|
|
548
|
+
import { Event as Event2 } from "@dxos/async";
|
|
549
|
+
import { timed } from "@dxos/debug";
|
|
550
550
|
import { log as log3 } from "@dxos/log";
|
|
551
|
-
import {
|
|
552
|
-
import { trace } from "@dxos/tracing";
|
|
553
|
-
|
|
554
|
-
// packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
|
|
555
|
-
import { synchronized, Trigger } from "@dxos/async";
|
|
556
|
-
import { NetworkAdapter } from "@dxos/automerge/automerge-repo";
|
|
557
|
-
import { LifecycleState as LifecycleState2 } from "@dxos/context";
|
|
558
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
559
|
-
import { log as log2 } from "@dxos/log";
|
|
560
|
-
import { nonNullable } from "@dxos/util";
|
|
561
|
-
|
|
562
|
-
// packages/core/echo/echo-pipeline/src/automerge/network-protocol.ts
|
|
563
|
-
var MESSAGE_TYPE_COLLECTION_QUERY = "collection-query";
|
|
564
|
-
var isCollectionQueryMessage = (message) => message.type === MESSAGE_TYPE_COLLECTION_QUERY;
|
|
565
|
-
var MESSAGE_TYPE_COLLECTION_STATE = "collection-state";
|
|
566
|
-
var isCollectionStateMessage = (message) => message.type === MESSAGE_TYPE_COLLECTION_STATE;
|
|
567
|
-
|
|
568
|
-
// packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
|
|
551
|
+
import { Timeframe } from "@dxos/timeframe";
|
|
569
552
|
function _ts_decorate(decorators, target, key, desc) {
|
|
570
553
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
571
554
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
@@ -576,360 +559,575 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
576
559
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
577
560
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
578
561
|
}
|
|
579
|
-
var
|
|
580
|
-
var
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
562
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/timeframe-clock.ts";
|
|
563
|
+
var mapTimeframeToFeedIndexes = (timeframe) => timeframe.frames().map(([feedKey, index]) => ({
|
|
564
|
+
feedKey,
|
|
565
|
+
index
|
|
566
|
+
}));
|
|
567
|
+
var mapFeedIndexesToTimeframe = (indexes) => new Timeframe(indexes.map(({ feedKey, index }) => [
|
|
568
|
+
feedKey,
|
|
569
|
+
index
|
|
570
|
+
]));
|
|
571
|
+
var startAfter = (timeframe) => timeframe.frames().map(([feedKey, index]) => ({
|
|
572
|
+
feedKey,
|
|
573
|
+
index: index + 1
|
|
574
|
+
}));
|
|
575
|
+
var TimeframeClock = class {
|
|
576
|
+
constructor(_timeframe = new Timeframe()) {
|
|
577
|
+
this._timeframe = _timeframe;
|
|
578
|
+
this.update = new Event2();
|
|
579
|
+
this._pendingTimeframe = _timeframe;
|
|
588
580
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
581
|
+
/**
|
|
582
|
+
* Timeframe that was processed by ECHO.
|
|
583
|
+
*/
|
|
584
|
+
get timeframe() {
|
|
585
|
+
return this._timeframe;
|
|
593
586
|
}
|
|
594
|
-
|
|
595
|
-
|
|
587
|
+
/**
|
|
588
|
+
* Timeframe that is currently being processed by ECHO.
|
|
589
|
+
* Will be equal to `timeframe` after the processing is complete.
|
|
590
|
+
*/
|
|
591
|
+
get pendingTimeframe() {
|
|
592
|
+
return this._pendingTimeframe;
|
|
596
593
|
}
|
|
597
|
-
|
|
594
|
+
setTimeframe(timeframe) {
|
|
595
|
+
this._timeframe = timeframe;
|
|
596
|
+
this._pendingTimeframe = timeframe;
|
|
597
|
+
this.update.emit(this._timeframe);
|
|
598
598
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
599
|
+
updatePendingTimeframe(key, seq) {
|
|
600
|
+
this._pendingTimeframe = Timeframe.merge(this._pendingTimeframe, new Timeframe([
|
|
601
|
+
[
|
|
602
|
+
key,
|
|
603
|
+
seq
|
|
604
|
+
]
|
|
605
|
+
]));
|
|
606
|
+
}
|
|
607
|
+
updateTimeframe() {
|
|
608
|
+
this._timeframe = this._pendingTimeframe;
|
|
609
|
+
this.update.emit(this._timeframe);
|
|
610
|
+
}
|
|
611
|
+
hasGaps(timeframe) {
|
|
612
|
+
const gaps = Timeframe.dependencies(timeframe, this._timeframe);
|
|
613
|
+
return !gaps.isEmpty();
|
|
614
|
+
}
|
|
615
|
+
async waitUntilReached(target) {
|
|
616
|
+
log3("waitUntilReached", {
|
|
617
|
+
target,
|
|
618
|
+
current: this._timeframe
|
|
619
|
+
}, {
|
|
620
|
+
F: __dxlog_file4,
|
|
621
|
+
L: 70,
|
|
607
622
|
S: this,
|
|
608
623
|
C: (f, a) => f(...a)
|
|
609
624
|
});
|
|
610
|
-
this.
|
|
611
|
-
|
|
625
|
+
await this.update.waitForCondition(() => {
|
|
626
|
+
log3("check if reached", {
|
|
627
|
+
target,
|
|
628
|
+
current: this._timeframe,
|
|
629
|
+
deps: Timeframe.dependencies(target, this._timeframe)
|
|
630
|
+
}, {
|
|
631
|
+
F: __dxlog_file4,
|
|
632
|
+
L: 72,
|
|
633
|
+
S: this,
|
|
634
|
+
C: (f, a) => f(...a)
|
|
635
|
+
});
|
|
636
|
+
return Timeframe.dependencies(target, this._timeframe).isEmpty();
|
|
612
637
|
});
|
|
613
638
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
639
|
+
};
|
|
640
|
+
_ts_decorate([
|
|
641
|
+
timed(5e3)
|
|
642
|
+
], TimeframeClock.prototype, "waitUntilReached", null);
|
|
643
|
+
|
|
644
|
+
// packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
|
|
645
|
+
import { Event as Event3, sleepWithContext, synchronized, Trigger } from "@dxos/async";
|
|
646
|
+
import { Context as Context2, rejectOnDispose } from "@dxos/context";
|
|
647
|
+
import { failUndefined } from "@dxos/debug";
|
|
648
|
+
import { FeedSetIterator } from "@dxos/feed-store";
|
|
649
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
650
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
651
|
+
import { log as log5 } from "@dxos/log";
|
|
652
|
+
import { Timeframe as Timeframe2 } from "@dxos/timeframe";
|
|
653
|
+
import { ComplexMap } from "@dxos/util";
|
|
654
|
+
|
|
655
|
+
// packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts
|
|
656
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
657
|
+
import { log as log4 } from "@dxos/log";
|
|
658
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts";
|
|
659
|
+
var createMessageSelector = (timeframeClock) => {
|
|
660
|
+
return (messages) => {
|
|
661
|
+
for (let i = 0; i < messages.length; i++) {
|
|
662
|
+
const { data: { timeframe } } = messages[i];
|
|
663
|
+
invariant4(timeframe, void 0, {
|
|
664
|
+
F: __dxlog_file5,
|
|
665
|
+
L: 25,
|
|
666
|
+
S: void 0,
|
|
667
|
+
A: [
|
|
668
|
+
"timeframe",
|
|
669
|
+
""
|
|
670
|
+
]
|
|
671
|
+
});
|
|
672
|
+
if (!timeframeClock.hasGaps(timeframe)) {
|
|
673
|
+
return i;
|
|
674
|
+
}
|
|
620
675
|
}
|
|
621
|
-
|
|
622
|
-
|
|
676
|
+
log4("Skipping...", void 0, {
|
|
677
|
+
F: __dxlog_file5,
|
|
678
|
+
L: 33,
|
|
679
|
+
S: void 0,
|
|
680
|
+
C: (f, a) => f(...a)
|
|
681
|
+
});
|
|
682
|
+
};
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
|
|
686
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
687
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
688
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
689
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
690
|
+
else
|
|
691
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
692
|
+
if (d = decorators[i])
|
|
693
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
694
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
695
|
+
}
|
|
696
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts";
|
|
697
|
+
var PipelineState = class {
|
|
698
|
+
constructor(_feeds, _timeframeClock) {
|
|
699
|
+
this._feeds = _feeds;
|
|
700
|
+
this._timeframeClock = _timeframeClock;
|
|
701
|
+
this._ctx = new Context2(void 0, {
|
|
702
|
+
F: __dxlog_file6,
|
|
703
|
+
L: 41
|
|
704
|
+
});
|
|
705
|
+
this.timeframeUpdate = this._timeframeClock.update;
|
|
706
|
+
this.stalled = new Event3();
|
|
707
|
+
this._startTimeframe = new Timeframe2();
|
|
708
|
+
this._reachedTarget = false;
|
|
623
709
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
710
|
+
/**
|
|
711
|
+
* Latest theoretical timeframe based on the last mutation in each feed.
|
|
712
|
+
* NOTE: This might never be reached if the mutation dependencies
|
|
713
|
+
*/
|
|
714
|
+
// TODO(dmaretskyi): Rename `totalTimeframe`? or `lastTimeframe`.
|
|
715
|
+
get endTimeframe() {
|
|
716
|
+
return mapFeedIndexesToTimeframe(Array.from(this._feeds.values()).filter((feed) => feed.length > 0).map((feed) => ({
|
|
717
|
+
feedKey: feed.key,
|
|
718
|
+
index: feed.length - 1
|
|
719
|
+
})));
|
|
720
|
+
}
|
|
721
|
+
get startTimeframe() {
|
|
722
|
+
return this._startTimeframe;
|
|
723
|
+
}
|
|
724
|
+
get timeframe() {
|
|
725
|
+
return this._timeframeClock.timeframe;
|
|
726
|
+
}
|
|
727
|
+
get pendingTimeframe() {
|
|
728
|
+
return this._timeframeClock.pendingTimeframe;
|
|
729
|
+
}
|
|
730
|
+
get targetTimeframe() {
|
|
731
|
+
return this._targetTimeframe ? this._targetTimeframe : new Timeframe2();
|
|
732
|
+
}
|
|
733
|
+
get reachedTarget() {
|
|
734
|
+
return this._reachedTarget;
|
|
735
|
+
}
|
|
736
|
+
get feeds() {
|
|
737
|
+
return Array.from(this._feeds.values());
|
|
738
|
+
}
|
|
739
|
+
async waitUntilTimeframe(target) {
|
|
740
|
+
await this._timeframeClock.waitUntilReached(target);
|
|
741
|
+
}
|
|
742
|
+
setTargetTimeframe(target) {
|
|
743
|
+
this._targetTimeframe = target;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Wait until the pipeline processes all messages in the feed and reaches the target timeframe if that is set.
|
|
747
|
+
*
|
|
748
|
+
* This function will resolve immediately if the pipeline is stalled.
|
|
749
|
+
*
|
|
750
|
+
* @param timeout Timeout in milliseconds to specify the maximum wait time.
|
|
751
|
+
*/
|
|
752
|
+
async waitUntilReachedTargetTimeframe({ ctx = new Context2(void 0, {
|
|
753
|
+
F: __dxlog_file6,
|
|
754
|
+
L: 129
|
|
755
|
+
}), timeout, breakOnStall = true } = {}) {
|
|
756
|
+
log5("waitUntilReachedTargetTimeframe", {
|
|
757
|
+
timeout,
|
|
758
|
+
current: this.timeframe,
|
|
759
|
+
target: this.targetTimeframe
|
|
760
|
+
}, {
|
|
761
|
+
F: __dxlog_file6,
|
|
762
|
+
L: 133,
|
|
763
|
+
S: this,
|
|
764
|
+
C: (f, a) => f(...a)
|
|
627
765
|
});
|
|
766
|
+
this._reachedTargetPromise ??= Promise.race([
|
|
767
|
+
this._timeframeClock.update.waitForCondition(() => {
|
|
768
|
+
return Timeframe2.dependencies(this.targetTimeframe, this.timeframe).isEmpty();
|
|
769
|
+
}),
|
|
770
|
+
...breakOnStall ? [
|
|
771
|
+
this.stalled.discardParameter().waitForCount(1)
|
|
772
|
+
] : []
|
|
773
|
+
]);
|
|
774
|
+
let done = false;
|
|
775
|
+
if (timeout) {
|
|
776
|
+
return Promise.race([
|
|
777
|
+
rejectOnDispose(ctx),
|
|
778
|
+
rejectOnDispose(this._ctx),
|
|
779
|
+
this._reachedTargetPromise.then(() => {
|
|
780
|
+
done = true;
|
|
781
|
+
this._reachedTarget = true;
|
|
782
|
+
}),
|
|
783
|
+
sleepWithContext(this._ctx, timeout).then(() => {
|
|
784
|
+
if (done) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
log5.warn("waitUntilReachedTargetTimeframe timed out", {
|
|
788
|
+
timeout,
|
|
789
|
+
current: this.timeframe,
|
|
790
|
+
target: this.targetTimeframe,
|
|
791
|
+
dependencies: Timeframe2.dependencies(this.targetTimeframe, this.timeframe)
|
|
792
|
+
}, {
|
|
793
|
+
F: __dxlog_file6,
|
|
794
|
+
L: 161,
|
|
795
|
+
S: this,
|
|
796
|
+
C: (f, a) => f(...a)
|
|
797
|
+
});
|
|
798
|
+
})
|
|
799
|
+
]);
|
|
800
|
+
} else {
|
|
801
|
+
return this._reachedTargetPromise;
|
|
802
|
+
}
|
|
628
803
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
804
|
+
};
|
|
805
|
+
var Pipeline = class {
|
|
806
|
+
constructor() {
|
|
807
|
+
this._timeframeClock = new TimeframeClock(new Timeframe2());
|
|
808
|
+
this._feeds = new ComplexMap(PublicKey2.hash);
|
|
809
|
+
// External state accessor.
|
|
810
|
+
this._state = new PipelineState(this._feeds, this._timeframeClock);
|
|
811
|
+
// Waits for the message consumer to process the message and yield control back to the pipeline.
|
|
812
|
+
this._processingTrigger = new Trigger().wake();
|
|
813
|
+
this._pauseTrigger = new Trigger().wake();
|
|
814
|
+
// Pending downloads.
|
|
815
|
+
this._downloads = new ComplexMap((value) => PublicKey2.hash(value.key));
|
|
816
|
+
this._isStopping = false;
|
|
817
|
+
this._isStarted = false;
|
|
818
|
+
this._isBeingConsumed = false;
|
|
819
|
+
this._isPaused = false;
|
|
820
|
+
}
|
|
821
|
+
get state() {
|
|
822
|
+
return this._state;
|
|
823
|
+
}
|
|
824
|
+
get writer() {
|
|
825
|
+
invariant5(this._writer, "Writer not set.", {
|
|
826
|
+
F: __dxlog_file6,
|
|
827
|
+
L: 243,
|
|
633
828
|
S: this,
|
|
634
829
|
A: [
|
|
635
|
-
"this.
|
|
636
|
-
""
|
|
830
|
+
"this._writer",
|
|
831
|
+
"'Writer not set.'"
|
|
637
832
|
]
|
|
638
833
|
});
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
834
|
+
return this._writer;
|
|
835
|
+
}
|
|
836
|
+
hasFeed(feedKey) {
|
|
837
|
+
return this._feeds.has(feedKey);
|
|
838
|
+
}
|
|
839
|
+
getFeeds() {
|
|
840
|
+
return this._feedSetIterator.feeds;
|
|
841
|
+
}
|
|
842
|
+
// NOTE: This cannot be synchronized with `stop` because stop waits for the mutation processing to complete,
|
|
843
|
+
// which might be opening feeds during the mutation processing, which w
|
|
844
|
+
async addFeed(feed) {
|
|
845
|
+
this._feeds.set(feed.key, feed);
|
|
846
|
+
if (this._feedSetIterator) {
|
|
847
|
+
await this._feedSetIterator.addFeed(feed);
|
|
848
|
+
}
|
|
849
|
+
if (this._isStarted && !this._isPaused) {
|
|
850
|
+
this._setFeedDownloadState(feed);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
setWriteFeed(feed) {
|
|
854
|
+
invariant5(!this._writer, "Writer already set.", {
|
|
855
|
+
F: __dxlog_file6,
|
|
856
|
+
L: 270,
|
|
642
857
|
S: this,
|
|
643
858
|
A: [
|
|
644
|
-
"this.
|
|
645
|
-
""
|
|
859
|
+
"!this._writer",
|
|
860
|
+
"'Writer already set.'"
|
|
646
861
|
]
|
|
647
862
|
});
|
|
648
|
-
|
|
649
|
-
F:
|
|
650
|
-
L:
|
|
863
|
+
invariant5(feed.properties.writable, "Feed must be writable.", {
|
|
864
|
+
F: __dxlog_file6,
|
|
865
|
+
L: 271,
|
|
651
866
|
S: this,
|
|
652
867
|
A: [
|
|
653
|
-
"
|
|
654
|
-
""
|
|
868
|
+
"feed.properties.writable",
|
|
869
|
+
"'Feed must be writable.'"
|
|
655
870
|
]
|
|
656
871
|
});
|
|
657
|
-
this.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
onConnectionClosed: this._onConnectionClosed.bind(this),
|
|
662
|
-
onConnectionAuthScopeChanged: this._onConnectionAuthScopeChanged.bind(this),
|
|
663
|
-
getContainingSpaceForDocument: this._params.getContainingSpaceForDocument
|
|
664
|
-
});
|
|
872
|
+
this._writer = createMappedFeedWriter((payload) => ({
|
|
873
|
+
timeframe: this._timeframeClock.timeframe,
|
|
874
|
+
payload
|
|
875
|
+
}), feed.createFeedWriter());
|
|
665
876
|
}
|
|
666
|
-
async
|
|
667
|
-
|
|
668
|
-
F:
|
|
669
|
-
L:
|
|
877
|
+
async start() {
|
|
878
|
+
invariant5(!this._isStarted, "Pipeline is already started.", {
|
|
879
|
+
F: __dxlog_file6,
|
|
880
|
+
L: 284,
|
|
670
881
|
S: this,
|
|
671
882
|
A: [
|
|
672
|
-
"this.
|
|
673
|
-
""
|
|
883
|
+
"!this._isStarted",
|
|
884
|
+
"'Pipeline is already started.'"
|
|
674
885
|
]
|
|
675
886
|
});
|
|
676
|
-
|
|
677
|
-
F:
|
|
678
|
-
L:
|
|
887
|
+
log5("starting...", void 0, {
|
|
888
|
+
F: __dxlog_file6,
|
|
889
|
+
L: 285,
|
|
679
890
|
S: this,
|
|
680
|
-
|
|
681
|
-
"this._replicators.has(replicator)",
|
|
682
|
-
""
|
|
683
|
-
]
|
|
891
|
+
C: (f, a) => f(...a)
|
|
684
892
|
});
|
|
685
|
-
await
|
|
686
|
-
this.
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
return false;
|
|
893
|
+
await this._initIterator();
|
|
894
|
+
await this._feedSetIterator.open();
|
|
895
|
+
this._isStarted = true;
|
|
896
|
+
log5("started", void 0, {
|
|
897
|
+
F: __dxlog_file6,
|
|
898
|
+
L: 289,
|
|
899
|
+
S: this,
|
|
900
|
+
C: (f, a) => f(...a)
|
|
901
|
+
});
|
|
902
|
+
if (!this._isPaused) {
|
|
903
|
+
for (const feed of this._feeds.values()) {
|
|
904
|
+
this._setFeedDownloadState(feed);
|
|
905
|
+
}
|
|
699
906
|
}
|
|
700
|
-
return connection.connection.shouldSyncCollection(params);
|
|
701
|
-
}
|
|
702
|
-
queryCollectionState(collectionId, targetId) {
|
|
703
|
-
const message = {
|
|
704
|
-
type: "collection-query",
|
|
705
|
-
senderId: this.peerId,
|
|
706
|
-
targetId,
|
|
707
|
-
collectionId
|
|
708
|
-
};
|
|
709
|
-
this._send(message);
|
|
710
|
-
}
|
|
711
|
-
sendCollectionState(collectionId, targetId, state) {
|
|
712
|
-
const message = {
|
|
713
|
-
type: "collection-state",
|
|
714
|
-
senderId: this.peerId,
|
|
715
|
-
targetId,
|
|
716
|
-
collectionId,
|
|
717
|
-
state
|
|
718
|
-
};
|
|
719
|
-
this._send(message);
|
|
720
907
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
908
|
+
async stop() {
|
|
909
|
+
log5("stopping...", void 0, {
|
|
910
|
+
F: __dxlog_file6,
|
|
911
|
+
L: 300,
|
|
912
|
+
S: this,
|
|
913
|
+
C: (f, a) => f(...a)
|
|
914
|
+
});
|
|
915
|
+
this._isStopping = true;
|
|
916
|
+
for (const [feed, handle] of this._downloads.entries()) {
|
|
917
|
+
feed.undownload(handle);
|
|
725
918
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
F: __dxlog_file3,
|
|
734
|
-
L: 181,
|
|
735
|
-
S: this,
|
|
736
|
-
C: (f, a) => f(...a)
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
this._params.monitor?.recordMessageSendingFailed(message);
|
|
919
|
+
this._downloads.clear();
|
|
920
|
+
await this._feedSetIterator?.close();
|
|
921
|
+
await this._processingTrigger.wait();
|
|
922
|
+
await this._state._ctx.dispose();
|
|
923
|
+
this._state._ctx = new Context2(void 0, {
|
|
924
|
+
F: __dxlog_file6,
|
|
925
|
+
L: 309
|
|
740
926
|
});
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}) ? connection.connection.peerId : null;
|
|
748
|
-
}).filter(nonNullable);
|
|
749
|
-
}
|
|
750
|
-
_onConnectionOpen(connection) {
|
|
751
|
-
log2("Connection opened", {
|
|
752
|
-
peerId: connection.peerId
|
|
753
|
-
}, {
|
|
754
|
-
F: __dxlog_file3,
|
|
755
|
-
L: 199,
|
|
927
|
+
this._state._reachedTargetPromise = void 0;
|
|
928
|
+
this._state._reachedTarget = false;
|
|
929
|
+
this._isStarted = false;
|
|
930
|
+
log5("stopped", void 0, {
|
|
931
|
+
F: __dxlog_file6,
|
|
932
|
+
L: 313,
|
|
756
933
|
S: this,
|
|
757
934
|
C: (f, a) => f(...a)
|
|
758
935
|
});
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* @param timeframe Timeframe of already processed messages.
|
|
939
|
+
* The pipeline will start processing messages AFTER this timeframe.
|
|
940
|
+
*/
|
|
941
|
+
async setCursor(timeframe) {
|
|
942
|
+
invariant5(!this._isStarted || this._isPaused, "Invalid state.", {
|
|
943
|
+
F: __dxlog_file6,
|
|
944
|
+
L: 322,
|
|
762
945
|
S: this,
|
|
763
946
|
A: [
|
|
764
|
-
"!this.
|
|
765
|
-
""
|
|
947
|
+
"!this._isStarted || this._isPaused",
|
|
948
|
+
"'Invalid state.'"
|
|
766
949
|
]
|
|
767
950
|
});
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
isOpen: true
|
|
775
|
-
};
|
|
776
|
-
this._connections.set(connection.peerId, connectionEntry);
|
|
777
|
-
queueMicrotask(async () => {
|
|
778
|
-
try {
|
|
779
|
-
while (true) {
|
|
780
|
-
const { done, value } = await reader.read();
|
|
781
|
-
if (done) {
|
|
782
|
-
break;
|
|
783
|
-
}
|
|
784
|
-
this._onMessage(value);
|
|
785
|
-
}
|
|
786
|
-
} catch (err) {
|
|
787
|
-
if (connectionEntry.isOpen) {
|
|
788
|
-
log2.catch(err, void 0, {
|
|
789
|
-
F: __dxlog_file3,
|
|
790
|
-
L: 219,
|
|
791
|
-
S: this,
|
|
792
|
-
C: (f, a) => f(...a)
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
log2("emit peer-candidate", {
|
|
798
|
-
peerId: connection.peerId
|
|
799
|
-
}, {
|
|
800
|
-
F: __dxlog_file3,
|
|
801
|
-
L: 224,
|
|
802
|
-
S: this,
|
|
803
|
-
C: (f, a) => f(...a)
|
|
804
|
-
});
|
|
805
|
-
this._emitPeerCandidate(connection);
|
|
806
|
-
this._params.monitor?.recordPeerConnected(connection.peerId);
|
|
807
|
-
}
|
|
808
|
-
_onMessage(message) {
|
|
809
|
-
if (isCollectionQueryMessage(message)) {
|
|
810
|
-
this._params.onCollectionStateQueried(message.collectionId, message.senderId);
|
|
811
|
-
} else if (isCollectionStateMessage(message)) {
|
|
812
|
-
this._params.onCollectionStateReceived(message.collectionId, message.senderId, message.state);
|
|
813
|
-
} else {
|
|
814
|
-
this.emit("message", message);
|
|
951
|
+
this._state._startTimeframe = timeframe;
|
|
952
|
+
this._timeframeClock.setTimeframe(timeframe);
|
|
953
|
+
if (this._feedSetIterator) {
|
|
954
|
+
await this._feedSetIterator.close();
|
|
955
|
+
await this._initIterator();
|
|
956
|
+
await this._feedSetIterator.open();
|
|
815
957
|
}
|
|
816
|
-
this._params.monitor?.recordMessageReceived(message);
|
|
817
958
|
}
|
|
818
959
|
/**
|
|
819
|
-
*
|
|
820
|
-
* TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
|
|
960
|
+
* Calling pause while processing will cause a deadlock.
|
|
821
961
|
*/
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
L: 247,
|
|
962
|
+
async pause() {
|
|
963
|
+
if (this._isPaused) {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
this._pauseTrigger.reset();
|
|
967
|
+
await this._processingTrigger.wait();
|
|
968
|
+
this._isPaused = true;
|
|
969
|
+
}
|
|
970
|
+
async unpause() {
|
|
971
|
+
invariant5(this._isPaused, "Pipeline is not paused.", {
|
|
972
|
+
F: __dxlog_file6,
|
|
973
|
+
L: 351,
|
|
835
974
|
S: this,
|
|
836
975
|
A: [
|
|
837
|
-
"
|
|
838
|
-
""
|
|
976
|
+
"this._isPaused",
|
|
977
|
+
"'Pipeline is not paused.'"
|
|
839
978
|
]
|
|
840
979
|
});
|
|
841
|
-
this.
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
980
|
+
this._pauseTrigger.wake();
|
|
981
|
+
this._isPaused = false;
|
|
982
|
+
for (const feed of this._feeds.values()) {
|
|
983
|
+
this._setFeedDownloadState(feed);
|
|
984
|
+
}
|
|
845
985
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
986
|
+
/**
|
|
987
|
+
* Starts to iterate over the ordered messages from the added feeds.
|
|
988
|
+
* Updates the timeframe clock after the message has bee processed.
|
|
989
|
+
*/
|
|
990
|
+
async *consume() {
|
|
991
|
+
invariant5(!this._isBeingConsumed, "Pipeline is already being consumed.", {
|
|
992
|
+
F: __dxlog_file6,
|
|
993
|
+
L: 366,
|
|
852
994
|
S: this,
|
|
853
|
-
|
|
995
|
+
A: [
|
|
996
|
+
"!this._isBeingConsumed",
|
|
997
|
+
"'Pipeline is already being consumed.'"
|
|
998
|
+
]
|
|
854
999
|
});
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
F:
|
|
858
|
-
L:
|
|
1000
|
+
this._isBeingConsumed = true;
|
|
1001
|
+
invariant5(this._feedSetIterator, "Iterator not initialized.", {
|
|
1002
|
+
F: __dxlog_file6,
|
|
1003
|
+
L: 369,
|
|
859
1004
|
S: this,
|
|
860
1005
|
A: [
|
|
861
|
-
"
|
|
862
|
-
""
|
|
1006
|
+
"this._feedSetIterator",
|
|
1007
|
+
"'Iterator not initialized.'"
|
|
863
1008
|
]
|
|
864
1009
|
});
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1010
|
+
let lastFeedSetIterator = this._feedSetIterator;
|
|
1011
|
+
let iterable = lastFeedSetIterator[Symbol.asyncIterator]();
|
|
1012
|
+
while (!this._isStopping) {
|
|
1013
|
+
await this._pauseTrigger.wait();
|
|
1014
|
+
if (lastFeedSetIterator !== this._feedSetIterator) {
|
|
1015
|
+
invariant5(this._feedSetIterator, "Iterator not initialized.", {
|
|
1016
|
+
F: __dxlog_file6,
|
|
1017
|
+
L: 378,
|
|
1018
|
+
S: this,
|
|
1019
|
+
A: [
|
|
1020
|
+
"this._feedSetIterator",
|
|
1021
|
+
"'Iterator not initialized.'"
|
|
1022
|
+
]
|
|
1023
|
+
});
|
|
1024
|
+
lastFeedSetIterator = this._feedSetIterator;
|
|
1025
|
+
iterable = lastFeedSetIterator[Symbol.asyncIterator]();
|
|
1026
|
+
}
|
|
1027
|
+
const { done, value } = await iterable.next();
|
|
1028
|
+
if (!done) {
|
|
1029
|
+
const block = value ?? failUndefined();
|
|
1030
|
+
this._processingTrigger.reset();
|
|
1031
|
+
this._timeframeClock.updatePendingTimeframe(PublicKey2.from(block.feedKey), block.seq);
|
|
1032
|
+
yield block;
|
|
1033
|
+
this._processingTrigger.wake();
|
|
1034
|
+
this._timeframeClock.updateTimeframe();
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
this._isBeingConsumed = false;
|
|
1038
|
+
}
|
|
1039
|
+
_setFeedDownloadState(feed) {
|
|
1040
|
+
let handle = this._downloads.get(feed);
|
|
1041
|
+
if (handle) {
|
|
1042
|
+
feed.undownload(handle);
|
|
1043
|
+
}
|
|
1044
|
+
const timeframe = this._state._startTimeframe;
|
|
1045
|
+
const seq = timeframe.get(feed.key) ?? -1;
|
|
1046
|
+
log5("download", {
|
|
1047
|
+
feed: feed.key.truncate(),
|
|
1048
|
+
seq,
|
|
1049
|
+
length: feed.length
|
|
1050
|
+
}, {
|
|
1051
|
+
F: __dxlog_file6,
|
|
1052
|
+
L: 407,
|
|
879
1053
|
S: this,
|
|
880
1054
|
C: (f, a) => f(...a)
|
|
881
|
-
})
|
|
882
|
-
|
|
1055
|
+
});
|
|
1056
|
+
handle = feed.download({
|
|
1057
|
+
start: seq + 1,
|
|
1058
|
+
linear: true
|
|
1059
|
+
}, (err, data) => {
|
|
1060
|
+
if (err) {
|
|
1061
|
+
} else {
|
|
1062
|
+
log5.info("downloaded", {
|
|
1063
|
+
data
|
|
1064
|
+
}, {
|
|
1065
|
+
F: __dxlog_file6,
|
|
1066
|
+
L: 412,
|
|
1067
|
+
S: this,
|
|
1068
|
+
C: (f, a) => f(...a)
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
this._downloads.set(feed, handle);
|
|
883
1073
|
}
|
|
884
|
-
|
|
885
|
-
this.
|
|
886
|
-
|
|
887
|
-
|
|
1074
|
+
async _initIterator() {
|
|
1075
|
+
this._feedSetIterator = new FeedSetIterator(createMessageSelector(this._timeframeClock), {
|
|
1076
|
+
start: startAfter(this._timeframeClock.timeframe),
|
|
1077
|
+
stallTimeout: 1e3
|
|
1078
|
+
});
|
|
1079
|
+
this._feedSetIterator.stalled.on((iterator) => {
|
|
1080
|
+
log5.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, void 0, {
|
|
1081
|
+
F: __dxlog_file6,
|
|
1082
|
+
L: 426,
|
|
1083
|
+
S: this,
|
|
1084
|
+
C: (f, a) => f(...a)
|
|
1085
|
+
});
|
|
1086
|
+
this._state.stalled.emit();
|
|
888
1087
|
});
|
|
1088
|
+
for (const feed of this._feeds.values()) {
|
|
1089
|
+
await this._feedSetIterator.addFeed(feed);
|
|
1090
|
+
}
|
|
889
1091
|
}
|
|
890
1092
|
};
|
|
891
|
-
|
|
1093
|
+
_ts_decorate2([
|
|
892
1094
|
synchronized
|
|
893
|
-
],
|
|
894
|
-
|
|
1095
|
+
], Pipeline.prototype, "start", null);
|
|
1096
|
+
_ts_decorate2([
|
|
895
1097
|
synchronized
|
|
896
|
-
],
|
|
897
|
-
|
|
1098
|
+
], Pipeline.prototype, "stop", null);
|
|
1099
|
+
_ts_decorate2([
|
|
898
1100
|
synchronized
|
|
899
|
-
],
|
|
900
|
-
|
|
1101
|
+
], Pipeline.prototype, "setCursor", null);
|
|
1102
|
+
_ts_decorate2([
|
|
901
1103
|
synchronized
|
|
902
|
-
],
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
});
|
|
907
|
-
var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetworkAdapter";
|
|
1104
|
+
], Pipeline.prototype, "pause", null);
|
|
1105
|
+
_ts_decorate2([
|
|
1106
|
+
synchronized
|
|
1107
|
+
], Pipeline.prototype, "unpause", null);
|
|
908
1108
|
|
|
909
|
-
// packages/core/echo/echo-pipeline/src/
|
|
910
|
-
import {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
valueEncoding: headsEncoding
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
// TODO(dmaretskyi): Make batched.
|
|
923
|
-
async getHeads(documentIds) {
|
|
924
|
-
return this._db.getMany(documentIds, {
|
|
925
|
-
keyEncoding: "utf8",
|
|
926
|
-
valueEncoding: headsEncoding
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
};
|
|
1109
|
+
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
1110
|
+
import { Event as Event4, scheduleMicroTask, synchronized as synchronized2, trackLeaks as trackLeaks2 } from "@dxos/async";
|
|
1111
|
+
import { LifecycleState, Resource as Resource3 } from "@dxos/context";
|
|
1112
|
+
import { subtleCrypto as subtleCrypto2 } from "@dxos/crypto";
|
|
1113
|
+
import { invariant as invariant6 } from "@dxos/invariant";
|
|
1114
|
+
import { PublicKey as PublicKey4, SpaceId } from "@dxos/keys";
|
|
1115
|
+
import { log as log7, logInfo } from "@dxos/log";
|
|
1116
|
+
import { AdmittedFeed as AdmittedFeed2 } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
1117
|
+
import { trace as trace2 } from "@dxos/tracing";
|
|
1118
|
+
import { Callback as Callback2, ComplexMap as ComplexMap2 } from "@dxos/util";
|
|
930
1119
|
|
|
931
|
-
// packages/core/echo/echo-pipeline/src/
|
|
932
|
-
|
|
1120
|
+
// packages/core/echo/echo-pipeline/src/space/control-pipeline.ts
|
|
1121
|
+
import { DeferredTask, sleepWithContext as sleepWithContext2, trackLeaks } from "@dxos/async";
|
|
1122
|
+
import { Context as Context3 } from "@dxos/context";
|
|
1123
|
+
import { SpaceStateMachine } from "@dxos/credentials";
|
|
1124
|
+
import { PublicKey as PublicKey3 } from "@dxos/keys";
|
|
1125
|
+
import { log as log6 } from "@dxos/log";
|
|
1126
|
+
import { AdmittedFeed } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
1127
|
+
import { Timeframe as Timeframe3 } from "@dxos/timeframe";
|
|
1128
|
+
import { TimeSeriesCounter, TimeUsageCounter, trace } from "@dxos/tracing";
|
|
1129
|
+
import { Callback, tracer } from "@dxos/util";
|
|
1130
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
933
1131
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
934
1132
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
935
1133
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -939,579 +1137,566 @@ function _ts_decorate2(decorators, target, key, desc) {
|
|
|
939
1137
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
940
1138
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
941
1139
|
}
|
|
942
|
-
var
|
|
943
|
-
var
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
this._db = db;
|
|
952
|
-
this._storage = new LevelDBStorageAdapter({
|
|
953
|
-
db: db.sublevel("automerge"),
|
|
954
|
-
callbacks: {
|
|
955
|
-
beforeSave: async (params) => this._beforeSave(params),
|
|
956
|
-
afterSave: async (key) => this._afterSave(key)
|
|
957
|
-
},
|
|
958
|
-
monitor: dataMonitor
|
|
959
|
-
});
|
|
960
|
-
this._echoNetworkAdapter = new EchoNetworkAdapter({
|
|
961
|
-
getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
|
|
962
|
-
onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
|
|
963
|
-
onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
|
|
964
|
-
monitor: dataMonitor
|
|
965
|
-
});
|
|
966
|
-
this._headsStore = new HeadsStore({
|
|
967
|
-
db: db.sublevel("heads")
|
|
1140
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/control-pipeline.ts";
|
|
1141
|
+
var TIMEFRAME_SAVE_DEBOUNCE_INTERVAL = 500;
|
|
1142
|
+
var CONTROL_PIPELINE_SNAPSHOT_DELAY = 1e4;
|
|
1143
|
+
var USE_SNAPSHOTS = true;
|
|
1144
|
+
var ControlPipeline = class {
|
|
1145
|
+
constructor({ spaceKey, genesisFeed, feedProvider, metadataStore }) {
|
|
1146
|
+
this._ctx = new Context3(void 0, {
|
|
1147
|
+
F: __dxlog_file7,
|
|
1148
|
+
L: 47
|
|
968
1149
|
});
|
|
969
|
-
this.
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
this.
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
sharePolicy: this._sharePolicy.bind(this),
|
|
977
|
-
storage: this._storage,
|
|
978
|
-
network: [
|
|
979
|
-
// Upstream swarm.
|
|
980
|
-
this._echoNetworkAdapter
|
|
981
|
-
]
|
|
1150
|
+
this._lastTimeframeSaveTime = Date.now();
|
|
1151
|
+
this.onFeedAdmitted = new Callback();
|
|
1152
|
+
this._usage = new TimeUsageCounter();
|
|
1153
|
+
this._mutations = new TimeSeriesCounter();
|
|
1154
|
+
this._snapshotTask = new DeferredTask(this._ctx, async () => {
|
|
1155
|
+
await sleepWithContext2(this._ctx, CONTROL_PIPELINE_SNAPSHOT_DELAY);
|
|
1156
|
+
await this._saveSnapshot();
|
|
982
1157
|
});
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
this.
|
|
986
|
-
|
|
1158
|
+
this._spaceKey = spaceKey;
|
|
1159
|
+
this._metadata = metadataStore;
|
|
1160
|
+
this._pipeline = new Pipeline();
|
|
1161
|
+
void this._pipeline.addFeed(genesisFeed);
|
|
1162
|
+
this._spaceStateMachine = new SpaceStateMachine(spaceKey);
|
|
1163
|
+
this._spaceStateMachine.onFeedAdmitted.set(async (info) => {
|
|
1164
|
+
log6("feed admitted", {
|
|
1165
|
+
key: info.key
|
|
1166
|
+
}, {
|
|
1167
|
+
F: __dxlog_file7,
|
|
1168
|
+
L: 82,
|
|
1169
|
+
S: this,
|
|
1170
|
+
C: (f, a) => f(...a)
|
|
1171
|
+
});
|
|
1172
|
+
if (info.assertion.designation === AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
|
|
1173
|
+
queueMicrotask(async () => {
|
|
1174
|
+
try {
|
|
1175
|
+
const feed = await feedProvider(info.key);
|
|
1176
|
+
if (!this._pipeline.hasFeed(feed.key)) {
|
|
1177
|
+
await this._pipeline.addFeed(feed);
|
|
1178
|
+
}
|
|
1179
|
+
} catch (err) {
|
|
1180
|
+
log6.catch(err, void 0, {
|
|
1181
|
+
F: __dxlog_file7,
|
|
1182
|
+
L: 93,
|
|
1183
|
+
S: this,
|
|
1184
|
+
C: (f, a) => f(...a)
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
await this.onFeedAdmitted.callIfSet(info);
|
|
987
1190
|
});
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
}
|
|
993
|
-
async _close() {
|
|
994
|
-
await this._collectionSynchronizer.close();
|
|
995
|
-
await this._storage.close?.();
|
|
996
|
-
await this._echoNetworkAdapter.close();
|
|
997
|
-
await this._ctx.dispose();
|
|
998
|
-
}
|
|
999
|
-
/**
|
|
1000
|
-
* @deprecated To be abstracted away.
|
|
1001
|
-
*/
|
|
1002
|
-
get repo() {
|
|
1003
|
-
return this._repo;
|
|
1191
|
+
this.onMemberRoleChanged = this._spaceStateMachine.onMemberRoleChanged;
|
|
1192
|
+
this.onCredentialProcessed = this._spaceStateMachine.onCredentialProcessed;
|
|
1193
|
+
this.onDelegatedInvitation = this._spaceStateMachine.onDelegatedInvitation;
|
|
1194
|
+
this.onDelegatedInvitationRemoved = this._spaceStateMachine.onDelegatedInvitationRemoved;
|
|
1004
1195
|
}
|
|
1005
|
-
get
|
|
1006
|
-
return this.
|
|
1196
|
+
get spaceState() {
|
|
1197
|
+
return this._spaceStateMachine;
|
|
1007
1198
|
}
|
|
1008
|
-
get
|
|
1009
|
-
return
|
|
1199
|
+
get pipeline() {
|
|
1200
|
+
return this._pipeline;
|
|
1010
1201
|
}
|
|
1011
|
-
async
|
|
1012
|
-
await this.
|
|
1202
|
+
async setWriteFeed(feed) {
|
|
1203
|
+
await this._pipeline.addFeed(feed);
|
|
1204
|
+
this._pipeline.setWriteFeed(feed);
|
|
1013
1205
|
}
|
|
1014
|
-
async
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
if (!handle.isReady()) {
|
|
1029
|
-
if (!opts?.timeout) {
|
|
1030
|
-
await cancelWithContext2(ctx, handle.whenReady());
|
|
1031
|
-
} else {
|
|
1032
|
-
await cancelWithContext2(ctx, asyncTimeout(handle.whenReady(), opts.timeout));
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
return handle;
|
|
1036
|
-
}
|
|
1037
|
-
/**
|
|
1038
|
-
* Create new persisted document.
|
|
1039
|
-
*/
|
|
1040
|
-
createDoc(initialValue, opts) {
|
|
1041
|
-
if (opts?.preserveHistory) {
|
|
1042
|
-
if (!isAutomerge(initialValue)) {
|
|
1043
|
-
throw new TypeError("Initial value must be an Automerge document");
|
|
1044
|
-
}
|
|
1045
|
-
return this._repo.import(save(initialValue));
|
|
1046
|
-
} else {
|
|
1047
|
-
return this._repo.create(initialValue);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
async waitUntilHeadsReplicated(heads) {
|
|
1051
|
-
const entries = heads.entries;
|
|
1052
|
-
if (!entries?.length) {
|
|
1053
|
-
return;
|
|
1206
|
+
async start() {
|
|
1207
|
+
const snapshot = this._metadata.getSpaceControlPipelineSnapshot(this._spaceKey);
|
|
1208
|
+
log6("load snapshot", {
|
|
1209
|
+
key: this._spaceKey,
|
|
1210
|
+
present: !!snapshot,
|
|
1211
|
+
tf: snapshot?.timeframe
|
|
1212
|
+
}, {
|
|
1213
|
+
F: __dxlog_file7,
|
|
1214
|
+
L: 123,
|
|
1215
|
+
S: this,
|
|
1216
|
+
C: (f, a) => f(...a)
|
|
1217
|
+
});
|
|
1218
|
+
if (USE_SNAPSHOTS && snapshot) {
|
|
1219
|
+
await this._processSnapshot(snapshot);
|
|
1054
1220
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
return false;
|
|
1061
|
-
}
|
|
1062
|
-
const currentHeads = documentHeads[index];
|
|
1063
|
-
return !(currentHeads !== null && headsEquals(currentHeads, targetHeads));
|
|
1221
|
+
log6("starting...", void 0, {
|
|
1222
|
+
F: __dxlog_file7,
|
|
1223
|
+
L: 128,
|
|
1224
|
+
S: this,
|
|
1225
|
+
C: (f, a) => f(...a)
|
|
1064
1226
|
});
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
L: 226
|
|
1070
|
-
}), entry.documentId);
|
|
1071
|
-
await waitForHeads(handle, entry.heads);
|
|
1227
|
+
setTimeout(async () => {
|
|
1228
|
+
void this._consumePipeline(new Context3(void 0, {
|
|
1229
|
+
F: __dxlog_file7,
|
|
1230
|
+
L: 130
|
|
1072
1231
|
}));
|
|
1073
|
-
}
|
|
1074
|
-
await this.
|
|
1232
|
+
});
|
|
1233
|
+
await this._pipeline.start();
|
|
1234
|
+
log6("started", void 0, {
|
|
1235
|
+
F: __dxlog_file7,
|
|
1236
|
+
L: 134,
|
|
1237
|
+
S: this,
|
|
1238
|
+
C: (f, a) => f(...a)
|
|
1239
|
+
});
|
|
1075
1240
|
}
|
|
1076
|
-
async
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
L: 238,
|
|
1083
|
-
S: this,
|
|
1084
|
-
C: (f, a) => f(...a)
|
|
1241
|
+
async _processSnapshot(snapshot) {
|
|
1242
|
+
await this._pipeline.setCursor(snapshot.timeframe);
|
|
1243
|
+
for (const message of snapshot.messages ?? []) {
|
|
1244
|
+
const result = await this._spaceStateMachine.process(message.credential, {
|
|
1245
|
+
sourceFeed: message.feedKey,
|
|
1246
|
+
skipVerification: true
|
|
1085
1247
|
});
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
"requesting"
|
|
1090
|
-
]);
|
|
1091
|
-
if (handle.inState([
|
|
1092
|
-
"requesting"
|
|
1093
|
-
])) {
|
|
1094
|
-
log3.warn("document is not available locally, skipping", {
|
|
1095
|
-
documentId
|
|
1248
|
+
if (!result) {
|
|
1249
|
+
log6.warn("credential processing failed from snapshot", {
|
|
1250
|
+
message
|
|
1096
1251
|
}, {
|
|
1097
|
-
F:
|
|
1098
|
-
L:
|
|
1252
|
+
F: __dxlog_file7,
|
|
1253
|
+
L: 147,
|
|
1099
1254
|
S: this,
|
|
1100
1255
|
C: (f, a) => f(...a)
|
|
1101
1256
|
});
|
|
1102
|
-
continue;
|
|
1103
1257
|
}
|
|
1104
|
-
const doc = handle.docSync();
|
|
1105
|
-
invariant4(doc, void 0, {
|
|
1106
|
-
F: __dxlog_file4,
|
|
1107
|
-
L: 247,
|
|
1108
|
-
S: this,
|
|
1109
|
-
A: [
|
|
1110
|
-
"doc",
|
|
1111
|
-
""
|
|
1112
|
-
]
|
|
1113
|
-
});
|
|
1114
|
-
const heads = getHeads(doc);
|
|
1115
|
-
const batch = this._db.batch();
|
|
1116
|
-
this._headsStore.setHeads(documentId, heads, batch);
|
|
1117
|
-
await batch.write();
|
|
1118
1258
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1259
|
+
}
|
|
1260
|
+
async _saveSnapshot() {
|
|
1261
|
+
await this._pipeline.pause();
|
|
1262
|
+
const snapshot = {
|
|
1263
|
+
timeframe: this._pipeline.state.timeframe,
|
|
1264
|
+
messages: this._spaceStateMachine.credentialEntries.map((entry) => ({
|
|
1265
|
+
feedKey: entry.sourceFeed,
|
|
1266
|
+
credential: entry.credential
|
|
1267
|
+
}))
|
|
1268
|
+
};
|
|
1269
|
+
await this._pipeline.unpause();
|
|
1270
|
+
log6("save snapshot", {
|
|
1271
|
+
key: this._spaceKey,
|
|
1272
|
+
snapshot
|
|
1273
|
+
}, {
|
|
1274
|
+
F: __dxlog_file7,
|
|
1275
|
+
L: 163,
|
|
1122
1276
|
S: this,
|
|
1123
1277
|
C: (f, a) => f(...a)
|
|
1124
1278
|
});
|
|
1279
|
+
await this._metadata.setSpaceControlPipelineSnapshot(this._spaceKey, snapshot);
|
|
1125
1280
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1281
|
+
async _consumePipeline(ctx) {
|
|
1282
|
+
for await (const msg of this._pipeline.consume()) {
|
|
1283
|
+
const span = this._usage.beginRecording();
|
|
1284
|
+
this._mutations.inc();
|
|
1285
|
+
try {
|
|
1286
|
+
await this._processMessage(ctx, msg);
|
|
1287
|
+
} catch (err) {
|
|
1288
|
+
log6.catch(err, void 0, {
|
|
1289
|
+
F: __dxlog_file7,
|
|
1290
|
+
L: 176,
|
|
1291
|
+
S: this,
|
|
1292
|
+
C: (f, a) => f(...a)
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
span.end();
|
|
1136
1296
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1297
|
+
}
|
|
1298
|
+
async _processMessage(ctx, msg) {
|
|
1299
|
+
log6("processing", {
|
|
1300
|
+
key: msg.feedKey,
|
|
1301
|
+
seq: msg.seq
|
|
1302
|
+
}, {
|
|
1303
|
+
F: __dxlog_file7,
|
|
1304
|
+
L: 186,
|
|
1305
|
+
S: this,
|
|
1306
|
+
C: (f, a) => f(...a)
|
|
1307
|
+
});
|
|
1308
|
+
if (msg.data.payload.credential) {
|
|
1309
|
+
const timer = tracer.mark("dxos.echo.pipeline.control");
|
|
1310
|
+
const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, {
|
|
1311
|
+
sourceFeed: PublicKey3.from(msg.feedKey)
|
|
1141
1312
|
});
|
|
1313
|
+
timer.end();
|
|
1314
|
+
if (!result) {
|
|
1315
|
+
log6.warn("processing failed", {
|
|
1316
|
+
msg
|
|
1317
|
+
}, {
|
|
1318
|
+
F: __dxlog_file7,
|
|
1319
|
+
L: 195,
|
|
1320
|
+
S: this,
|
|
1321
|
+
C: (f, a) => f(...a)
|
|
1322
|
+
});
|
|
1323
|
+
} else {
|
|
1324
|
+
await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
|
|
1325
|
+
}
|
|
1326
|
+
this._snapshotTask.schedule();
|
|
1142
1327
|
}
|
|
1143
|
-
return false;
|
|
1144
1328
|
}
|
|
1145
|
-
async
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
const doc = handle.docSync();
|
|
1151
|
-
if (!doc) {
|
|
1152
|
-
return;
|
|
1329
|
+
async _noteTargetStateIfNeeded(timeframe) {
|
|
1330
|
+
if (Date.now() - this._lastTimeframeSaveTime > TIMEFRAME_SAVE_DEBOUNCE_INTERVAL) {
|
|
1331
|
+
this._lastTimeframeSaveTime = Date.now();
|
|
1332
|
+
await this._saveTargetTimeframe(timeframe);
|
|
1153
1333
|
}
|
|
1154
|
-
const heads = getHeads(doc);
|
|
1155
|
-
this._headsStore.setHeads(handle.documentId, heads, batch);
|
|
1156
|
-
const spaceKey = getSpaceKeyFromDoc(doc) ?? void 0;
|
|
1157
|
-
const objectIds = Object.keys(doc.objects ?? {});
|
|
1158
|
-
const encodedIds = objectIds.map((objectId) => objectPointerCodec.encode({
|
|
1159
|
-
documentId: handle.documentId,
|
|
1160
|
-
objectId,
|
|
1161
|
-
spaceKey
|
|
1162
|
-
}));
|
|
1163
|
-
const idToLastHash = new Map(encodedIds.map((id) => [
|
|
1164
|
-
id,
|
|
1165
|
-
heads
|
|
1166
|
-
]));
|
|
1167
|
-
this._indexMetadataStore.markDirty(idToLastHash, batch);
|
|
1168
1334
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1335
|
+
async stop() {
|
|
1336
|
+
log6("stopping...", void 0, {
|
|
1337
|
+
F: __dxlog_file7,
|
|
1338
|
+
L: 215,
|
|
1339
|
+
S: this,
|
|
1340
|
+
C: (f, a) => f(...a)
|
|
1341
|
+
});
|
|
1342
|
+
await this._ctx.dispose();
|
|
1343
|
+
await this._pipeline.stop();
|
|
1344
|
+
await this._saveTargetTimeframe(this._pipeline.state.timeframe);
|
|
1345
|
+
log6("stopped", void 0, {
|
|
1346
|
+
F: __dxlog_file7,
|
|
1347
|
+
L: 219,
|
|
1348
|
+
S: this,
|
|
1349
|
+
C: (f, a) => f(...a)
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
async _saveTargetTimeframe(timeframe) {
|
|
1353
|
+
try {
|
|
1354
|
+
const newTimeframe = Timeframe3.merge(this._targetTimeframe ?? new Timeframe3(), timeframe);
|
|
1355
|
+
await this._metadata.setSpaceControlLatestTimeframe(this._spaceKey, newTimeframe);
|
|
1356
|
+
this._targetTimeframe = newTimeframe;
|
|
1357
|
+
} catch (err) {
|
|
1358
|
+
log6(err, void 0, {
|
|
1359
|
+
F: __dxlog_file7,
|
|
1360
|
+
L: 228,
|
|
1361
|
+
S: this,
|
|
1362
|
+
C: (f, a) => f(...a)
|
|
1174
1363
|
});
|
|
1175
1364
|
}
|
|
1176
|
-
return false;
|
|
1177
1365
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1366
|
+
};
|
|
1367
|
+
_ts_decorate3([
|
|
1368
|
+
trace.metricsCounter()
|
|
1369
|
+
], ControlPipeline.prototype, "_usage", void 0);
|
|
1370
|
+
_ts_decorate3([
|
|
1371
|
+
trace.metricsCounter()
|
|
1372
|
+
], ControlPipeline.prototype, "_mutations", void 0);
|
|
1373
|
+
_ts_decorate3([
|
|
1374
|
+
trace.span({
|
|
1375
|
+
showInBrowserTimeline: true
|
|
1376
|
+
})
|
|
1377
|
+
], ControlPipeline.prototype, "start", null);
|
|
1378
|
+
_ts_decorate3([
|
|
1379
|
+
trace.span()
|
|
1380
|
+
], ControlPipeline.prototype, "_consumePipeline", null);
|
|
1381
|
+
_ts_decorate3([
|
|
1382
|
+
trace.span()
|
|
1383
|
+
], ControlPipeline.prototype, "_processMessage", null);
|
|
1384
|
+
ControlPipeline = _ts_decorate3([
|
|
1385
|
+
trace.resource(),
|
|
1386
|
+
trackLeaks("start", "stop")
|
|
1387
|
+
], ControlPipeline);
|
|
1388
|
+
|
|
1389
|
+
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
1390
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
1391
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1392
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1393
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1394
|
+
else
|
|
1395
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
1396
|
+
if (d = decorators[i])
|
|
1397
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1398
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1399
|
+
}
|
|
1400
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space.ts";
|
|
1401
|
+
var Space = class extends Resource3 {
|
|
1402
|
+
constructor(params) {
|
|
1403
|
+
super();
|
|
1404
|
+
this.onCredentialProcessed = new Callback2();
|
|
1405
|
+
this.stateUpdate = new Event4();
|
|
1406
|
+
invariant6(params.spaceKey && params.feedProvider, void 0, {
|
|
1407
|
+
F: __dxlog_file8,
|
|
1408
|
+
L: 76,
|
|
1409
|
+
S: this,
|
|
1410
|
+
A: [
|
|
1411
|
+
"params.spaceKey && params.feedProvider",
|
|
1412
|
+
""
|
|
1413
|
+
]
|
|
1414
|
+
});
|
|
1415
|
+
this._id = params.id;
|
|
1416
|
+
this._key = params.spaceKey;
|
|
1417
|
+
this._genesisFeedKey = params.genesisFeed.key;
|
|
1418
|
+
this._feedProvider = params.feedProvider;
|
|
1419
|
+
this._snapshotManager = params.snapshotManager;
|
|
1420
|
+
this._controlPipeline = new ControlPipeline({
|
|
1421
|
+
spaceKey: params.spaceKey,
|
|
1422
|
+
genesisFeed: params.genesisFeed,
|
|
1423
|
+
feedProvider: params.feedProvider,
|
|
1424
|
+
metadataStore: params.metadataStore
|
|
1425
|
+
});
|
|
1426
|
+
this._controlPipeline.onFeedAdmitted.set(async (info) => {
|
|
1427
|
+
const sparse = info.assertion.designation === AdmittedFeed2.Designation.DATA;
|
|
1428
|
+
if (!info.key.equals(params.genesisFeed.key)) {
|
|
1429
|
+
scheduleMicroTask(this._ctx, async () => {
|
|
1430
|
+
await this.protocol.addFeed(await params.feedProvider(info.key, {
|
|
1431
|
+
sparse
|
|
1432
|
+
}));
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
this._controlPipeline.onCredentialProcessed.set(async (credential) => {
|
|
1437
|
+
await this.onCredentialProcessed.callIfSet(credential);
|
|
1438
|
+
log7("onCredentialProcessed", {
|
|
1439
|
+
credential
|
|
1440
|
+
}, {
|
|
1441
|
+
F: __dxlog_file8,
|
|
1442
|
+
L: 104,
|
|
1443
|
+
S: this,
|
|
1444
|
+
C: (f, a) => f(...a)
|
|
1445
|
+
});
|
|
1446
|
+
this.stateUpdate.emit();
|
|
1447
|
+
});
|
|
1448
|
+
this._controlPipeline.onDelegatedInvitation.set(async (invitation) => {
|
|
1449
|
+
log7("onDelegatedInvitation", {
|
|
1450
|
+
invitation
|
|
1451
|
+
}, {
|
|
1452
|
+
F: __dxlog_file8,
|
|
1453
|
+
L: 108,
|
|
1454
|
+
S: this,
|
|
1455
|
+
C: (f, a) => f(...a)
|
|
1456
|
+
});
|
|
1457
|
+
await params.onDelegatedInvitationStatusChange(invitation, true);
|
|
1458
|
+
});
|
|
1459
|
+
this._controlPipeline.onDelegatedInvitationRemoved.set(async (invitation) => {
|
|
1460
|
+
log7("onDelegatedInvitationRemoved", {
|
|
1461
|
+
invitation
|
|
1462
|
+
}, {
|
|
1463
|
+
F: __dxlog_file8,
|
|
1464
|
+
L: 112,
|
|
1465
|
+
S: this,
|
|
1466
|
+
C: (f, a) => f(...a)
|
|
1467
|
+
});
|
|
1468
|
+
await params.onDelegatedInvitationStatusChange(invitation, false);
|
|
1469
|
+
});
|
|
1470
|
+
this._controlPipeline.onMemberRoleChanged.set(async (changedMembers) => {
|
|
1471
|
+
log7("onMemberRoleChanged", () => ({
|
|
1472
|
+
changedMembers: changedMembers.map((m) => [
|
|
1473
|
+
m.key,
|
|
1474
|
+
m.role
|
|
1475
|
+
])
|
|
1476
|
+
}), {
|
|
1477
|
+
F: __dxlog_file8,
|
|
1478
|
+
L: 116,
|
|
1479
|
+
S: this,
|
|
1480
|
+
C: (f, a) => f(...a)
|
|
1481
|
+
});
|
|
1482
|
+
await params.onMemberRolesChanged(changedMembers);
|
|
1483
|
+
});
|
|
1484
|
+
this.protocol = params.protocol;
|
|
1192
1485
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
if (!doc) {
|
|
1196
|
-
return null;
|
|
1197
|
-
}
|
|
1198
|
-
const spaceKeyHex = getSpaceKeyFromDoc(doc);
|
|
1199
|
-
if (!spaceKeyHex) {
|
|
1200
|
-
return null;
|
|
1201
|
-
}
|
|
1202
|
-
return PublicKey2.from(spaceKeyHex);
|
|
1486
|
+
get id() {
|
|
1487
|
+
return this._id;
|
|
1203
1488
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
*/
|
|
1207
|
-
async flush({ documentIds } = {}) {
|
|
1208
|
-
await this._repo.flush(documentIds);
|
|
1489
|
+
get key() {
|
|
1490
|
+
return this._key;
|
|
1209
1491
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
const storeRequestIds = [];
|
|
1213
|
-
const storeResultIndices = [];
|
|
1214
|
-
for (const documentId of documentIds) {
|
|
1215
|
-
const doc = this._repo.handles[documentId]?.docSync();
|
|
1216
|
-
if (doc) {
|
|
1217
|
-
result.push(getHeads(doc));
|
|
1218
|
-
} else {
|
|
1219
|
-
storeRequestIds.push(documentId);
|
|
1220
|
-
storeResultIndices.push(result.length);
|
|
1221
|
-
result.push(void 0);
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
if (storeRequestIds.length > 0) {
|
|
1225
|
-
const storedHeads = await this._headsStore.getHeads(storeRequestIds);
|
|
1226
|
-
for (let i = 0; i < storedHeads.length; i++) {
|
|
1227
|
-
result[storeResultIndices[i]] = storedHeads[i];
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
return result;
|
|
1492
|
+
get isOpen() {
|
|
1493
|
+
return this._lifecycleState === LifecycleState.OPEN;
|
|
1231
1494
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
//
|
|
1235
|
-
getLocalCollectionState(collectionId) {
|
|
1236
|
-
return this._collectionSynchronizer.getLocalCollectionState(collectionId);
|
|
1495
|
+
get genesisFeedKey() {
|
|
1496
|
+
return this._genesisFeedKey;
|
|
1237
1497
|
}
|
|
1238
|
-
|
|
1239
|
-
return this.
|
|
1498
|
+
get controlFeedKey() {
|
|
1499
|
+
return this._controlFeed?.key;
|
|
1240
1500
|
}
|
|
1241
|
-
|
|
1242
|
-
this.
|
|
1501
|
+
get dataFeedKey() {
|
|
1502
|
+
return this._dataFeed?.key;
|
|
1243
1503
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
peers: []
|
|
1247
|
-
};
|
|
1248
|
-
const localState = this.getLocalCollectionState(collectionId);
|
|
1249
|
-
const remoteState = this.getRemoteCollectionStates(collectionId);
|
|
1250
|
-
if (!localState) {
|
|
1251
|
-
return result;
|
|
1252
|
-
}
|
|
1253
|
-
for (const [peerId, state] of remoteState) {
|
|
1254
|
-
const diff = diffCollectionState(localState, state);
|
|
1255
|
-
result.peers.push({
|
|
1256
|
-
peerId,
|
|
1257
|
-
differentDocuments: diff.different.length
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
return result;
|
|
1504
|
+
get spaceState() {
|
|
1505
|
+
return this._controlPipeline.spaceState;
|
|
1261
1506
|
}
|
|
1262
1507
|
/**
|
|
1263
|
-
*
|
|
1508
|
+
* @test-only
|
|
1264
1509
|
*/
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
const documents = Object.fromEntries(heads.map((heads2, index) => [
|
|
1268
|
-
documentIds[index],
|
|
1269
|
-
heads2 ?? []
|
|
1270
|
-
]));
|
|
1271
|
-
this._collectionSynchronizer.setLocalCollectionState(collectionId, {
|
|
1272
|
-
documents
|
|
1273
|
-
});
|
|
1274
|
-
}
|
|
1275
|
-
_onCollectionStateQueried(collectionId, peerId) {
|
|
1276
|
-
this._collectionSynchronizer.onCollectionStateQueried(collectionId, peerId);
|
|
1277
|
-
}
|
|
1278
|
-
_onCollectionStateReceived(collectionId, peerId, state) {
|
|
1279
|
-
this._collectionSynchronizer.onRemoteStateReceived(collectionId, peerId, decodeCollectionState(state));
|
|
1510
|
+
get controlPipeline() {
|
|
1511
|
+
return this._controlPipeline.pipeline;
|
|
1280
1512
|
}
|
|
1281
|
-
|
|
1282
|
-
this.
|
|
1513
|
+
get snapshotManager() {
|
|
1514
|
+
return this._snapshotManager;
|
|
1283
1515
|
}
|
|
1284
|
-
|
|
1285
|
-
this.
|
|
1516
|
+
async setControlFeed(feed) {
|
|
1517
|
+
invariant6(!this._controlFeed, "Control feed already set.", {
|
|
1518
|
+
F: __dxlog_file8,
|
|
1519
|
+
L: 168,
|
|
1520
|
+
S: this,
|
|
1521
|
+
A: [
|
|
1522
|
+
"!this._controlFeed",
|
|
1523
|
+
"'Control feed already set.'"
|
|
1524
|
+
]
|
|
1525
|
+
});
|
|
1526
|
+
this._controlFeed = feed;
|
|
1527
|
+
await this._controlPipeline.setWriteFeed(feed);
|
|
1528
|
+
return this;
|
|
1286
1529
|
}
|
|
1287
|
-
|
|
1288
|
-
this.
|
|
1530
|
+
async setDataFeed(feed) {
|
|
1531
|
+
invariant6(!this._dataFeed, "Data feed already set.", {
|
|
1532
|
+
F: __dxlog_file8,
|
|
1533
|
+
L: 175,
|
|
1534
|
+
S: this,
|
|
1535
|
+
A: [
|
|
1536
|
+
"!this._dataFeed",
|
|
1537
|
+
"'Data feed already set.'"
|
|
1538
|
+
]
|
|
1539
|
+
});
|
|
1540
|
+
this._dataFeed = feed;
|
|
1541
|
+
return this;
|
|
1289
1542
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1543
|
+
/**
|
|
1544
|
+
* Use for diagnostics.
|
|
1545
|
+
*/
|
|
1546
|
+
getControlFeeds() {
|
|
1547
|
+
return Array.from(this._controlPipeline.spaceState.feeds.values());
|
|
1292
1548
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
F: __dxlog_file4,
|
|
1307
|
-
L: 463,
|
|
1549
|
+
async _open(ctx) {
|
|
1550
|
+
log7("opening...", void 0, {
|
|
1551
|
+
F: __dxlog_file8,
|
|
1552
|
+
L: 189,
|
|
1553
|
+
S: this,
|
|
1554
|
+
C: (f, a) => f(...a)
|
|
1555
|
+
});
|
|
1556
|
+
await this._controlPipeline.start();
|
|
1557
|
+
await this.protocol.start();
|
|
1558
|
+
await this.protocol.addFeed(await this._feedProvider(this._genesisFeedKey));
|
|
1559
|
+
log7("opened", void 0, {
|
|
1560
|
+
F: __dxlog_file8,
|
|
1561
|
+
L: 196,
|
|
1308
1562
|
S: this,
|
|
1309
1563
|
C: (f, a) => f(...a)
|
|
1310
1564
|
});
|
|
1311
|
-
for (const documentId of different) {
|
|
1312
|
-
this._repo.find(documentId);
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
_onHeadsChanged(documentId, heads) {
|
|
1316
|
-
for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
|
|
1317
|
-
const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
|
|
1318
|
-
if (state?.documents[documentId]) {
|
|
1319
|
-
const newState = structuredClone(state);
|
|
1320
|
-
newState.documents[documentId] = heads;
|
|
1321
|
-
this._collectionSynchronizer.setLocalCollectionState(collectionId, newState);
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
1565
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
var getSpaceKeyFromDoc = (doc) => {
|
|
1343
|
-
const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
|
|
1344
|
-
if (rawSpaceKey == null) {
|
|
1345
|
-
return null;
|
|
1566
|
+
async _close() {
|
|
1567
|
+
log7("closing...", {
|
|
1568
|
+
key: this._key
|
|
1569
|
+
}, {
|
|
1570
|
+
F: __dxlog_file8,
|
|
1571
|
+
L: 201,
|
|
1572
|
+
S: this,
|
|
1573
|
+
C: (f, a) => f(...a)
|
|
1574
|
+
});
|
|
1575
|
+
await this.protocol.stop();
|
|
1576
|
+
await this._controlPipeline.stop();
|
|
1577
|
+
log7("closed", void 0, {
|
|
1578
|
+
F: __dxlog_file8,
|
|
1579
|
+
L: 207,
|
|
1580
|
+
S: this,
|
|
1581
|
+
C: (f, a) => f(...a)
|
|
1582
|
+
});
|
|
1346
1583
|
}
|
|
1347
|
-
return String(rawSpaceKey);
|
|
1348
|
-
};
|
|
1349
|
-
var waitForHeads = async (handle, heads) => {
|
|
1350
|
-
const unavailableHeads = new Set(heads);
|
|
1351
|
-
await handle.whenReady();
|
|
1352
|
-
await Event2.wrap(handle, "change").waitForCondition(() => {
|
|
1353
|
-
for (const changeHash of unavailableHeads.values()) {
|
|
1354
|
-
if (changeIsPresentInDoc(handle.docSync(), changeHash)) {
|
|
1355
|
-
unavailableHeads.delete(changeHash);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
return unavailableHeads.size === 0;
|
|
1359
|
-
});
|
|
1360
|
-
};
|
|
1361
|
-
var changeIsPresentInDoc = (doc, changeHash) => {
|
|
1362
|
-
return !!getBackend(doc).getChangeByHash(changeHash);
|
|
1363
|
-
};
|
|
1364
|
-
var decodeCollectionState = (state) => {
|
|
1365
|
-
invariant4(typeof state === "object" && state !== null, "Invalid state", {
|
|
1366
|
-
F: __dxlog_file4,
|
|
1367
|
-
L: 516,
|
|
1368
|
-
S: void 0,
|
|
1369
|
-
A: [
|
|
1370
|
-
"typeof state === 'object' && state !== null",
|
|
1371
|
-
"'Invalid state'"
|
|
1372
|
-
]
|
|
1373
|
-
});
|
|
1374
|
-
return state;
|
|
1375
|
-
};
|
|
1376
|
-
var encodeCollectionState = (state) => {
|
|
1377
|
-
return state;
|
|
1378
1584
|
};
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1585
|
+
_ts_decorate4([
|
|
1586
|
+
trace2.info()
|
|
1587
|
+
], Space.prototype, "protocol", void 0);
|
|
1588
|
+
_ts_decorate4([
|
|
1589
|
+
trace2.info()
|
|
1590
|
+
], Space.prototype, "_controlPipeline", void 0);
|
|
1591
|
+
_ts_decorate4([
|
|
1592
|
+
logInfo,
|
|
1593
|
+
trace2.info()
|
|
1594
|
+
], Space.prototype, "id", null);
|
|
1595
|
+
_ts_decorate4([
|
|
1596
|
+
logInfo,
|
|
1597
|
+
trace2.info()
|
|
1598
|
+
], Space.prototype, "key", null);
|
|
1599
|
+
_ts_decorate4([
|
|
1600
|
+
trace2.span()
|
|
1601
|
+
], Space.prototype, "_open", null);
|
|
1602
|
+
_ts_decorate4([
|
|
1603
|
+
synchronized2
|
|
1604
|
+
], Space.prototype, "_close", null);
|
|
1605
|
+
Space = _ts_decorate4([
|
|
1606
|
+
trackLeaks2("open", "close"),
|
|
1607
|
+
trace2.resource()
|
|
1608
|
+
], Space);
|
|
1609
|
+
var SPACE_IDS_CACHE = new ComplexMap2(PublicKey4.hash);
|
|
1610
|
+
var createIdFromSpaceKey = async (spaceKey) => {
|
|
1611
|
+
const cachedValue = SPACE_IDS_CACHE.get(spaceKey);
|
|
1612
|
+
if (cachedValue !== void 0) {
|
|
1613
|
+
return cachedValue;
|
|
1614
|
+
}
|
|
1615
|
+
const digest = await subtleCrypto2.digest("SHA-256", spaceKey.asUint8Array());
|
|
1616
|
+
const bytes = new Uint8Array(digest).slice(0, SpaceId.byteLength);
|
|
1617
|
+
const spaceId = SpaceId.encode(bytes);
|
|
1618
|
+
SPACE_IDS_CACHE.set(spaceKey, spaceId);
|
|
1396
1619
|
return spaceId;
|
|
1397
1620
|
};
|
|
1398
1621
|
|
|
1399
|
-
// packages/core/echo/echo-pipeline/src/space/
|
|
1400
|
-
import {
|
|
1401
|
-
import { Context as
|
|
1402
|
-
import {
|
|
1403
|
-
import {
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/auth.ts";
|
|
1408
|
-
var AuthExtension = class extends RpcExtension {
|
|
1409
|
-
constructor(_authParams) {
|
|
1622
|
+
// packages/core/echo/echo-pipeline/src/space/admission-discovery-extension.ts
|
|
1623
|
+
import { scheduleTask as scheduleTask3 } from "@dxos/async";
|
|
1624
|
+
import { Context as Context4 } from "@dxos/context";
|
|
1625
|
+
import { ProtocolError, schema as schema5 } from "@dxos/protocols";
|
|
1626
|
+
import { RpcExtension as RpcExtension2 } from "@dxos/teleport";
|
|
1627
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/admission-discovery-extension.ts";
|
|
1628
|
+
var CredentialRetrieverExtension = class extends RpcExtension2 {
|
|
1629
|
+
constructor(_request, _onResult) {
|
|
1410
1630
|
super({
|
|
1411
1631
|
requested: {
|
|
1412
|
-
|
|
1413
|
-
},
|
|
1414
|
-
exposed: {
|
|
1415
|
-
AuthService: schema4.getService("dxos.mesh.teleport.auth.AuthService")
|
|
1416
|
-
},
|
|
1417
|
-
timeout: 60 * 1e3
|
|
1418
|
-
});
|
|
1419
|
-
this._authParams = _authParams;
|
|
1420
|
-
this._ctx = new Context2({
|
|
1421
|
-
onError: (err) => {
|
|
1422
|
-
log4.catch(err, void 0, {
|
|
1423
|
-
F: __dxlog_file6,
|
|
1424
|
-
L: 28,
|
|
1425
|
-
S: this,
|
|
1426
|
-
C: (f, a) => f(...a)
|
|
1427
|
-
});
|
|
1632
|
+
AdmissionDiscoveryService: schema5.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
|
|
1428
1633
|
}
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1634
|
+
});
|
|
1635
|
+
this._request = _request;
|
|
1636
|
+
this._onResult = _onResult;
|
|
1637
|
+
this._ctx = new Context4(void 0, {
|
|
1638
|
+
F: __dxlog_file9,
|
|
1639
|
+
L: 25
|
|
1432
1640
|
});
|
|
1433
1641
|
}
|
|
1434
1642
|
async getHandlers() {
|
|
1435
|
-
return {
|
|
1436
|
-
AuthService: {
|
|
1437
|
-
authenticate: async ({ challenge }) => {
|
|
1438
|
-
try {
|
|
1439
|
-
const credential = await this._authParams.provider(challenge);
|
|
1440
|
-
if (!credential) {
|
|
1441
|
-
throw new Error("auth rejected");
|
|
1442
|
-
}
|
|
1443
|
-
return {
|
|
1444
|
-
credential
|
|
1445
|
-
};
|
|
1446
|
-
} catch (err) {
|
|
1447
|
-
log4.error("failed to generate auth credentials", err, {
|
|
1448
|
-
F: __dxlog_file6,
|
|
1449
|
-
L: 55,
|
|
1450
|
-
S: this,
|
|
1451
|
-
C: (f, a) => f(...a)
|
|
1452
|
-
});
|
|
1453
|
-
throw new Error("auth rejected");
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
};
|
|
1643
|
+
return {};
|
|
1458
1644
|
}
|
|
1459
1645
|
async onOpen(context) {
|
|
1460
1646
|
await super.onOpen(context);
|
|
1461
|
-
|
|
1647
|
+
scheduleTask3(this._ctx, async () => {
|
|
1462
1648
|
try {
|
|
1463
|
-
const
|
|
1464
|
-
|
|
1465
|
-
challenge
|
|
1466
|
-
});
|
|
1467
|
-
invariant6(credential?.length > 0, "invalid credential", {
|
|
1468
|
-
F: __dxlog_file6,
|
|
1469
|
-
L: 69,
|
|
1470
|
-
S: this,
|
|
1471
|
-
A: [
|
|
1472
|
-
"credential?.length > 0",
|
|
1473
|
-
"'invalid credential'"
|
|
1474
|
-
]
|
|
1475
|
-
});
|
|
1476
|
-
const success = await this._authParams.verifier(challenge, credential);
|
|
1477
|
-
invariant6(success, "credential not verified", {
|
|
1478
|
-
F: __dxlog_file6,
|
|
1479
|
-
L: 71,
|
|
1480
|
-
S: this,
|
|
1481
|
-
A: [
|
|
1482
|
-
"success",
|
|
1483
|
-
"'credential not verified'"
|
|
1484
|
-
]
|
|
1485
|
-
});
|
|
1486
|
-
runInContext(this._ctx, () => this._authParams.onAuthSuccess());
|
|
1649
|
+
const result = await this.rpc.AdmissionDiscoveryService.getAdmissionCredential(this._request);
|
|
1650
|
+
this._onResult.wake(result.admissionCredential);
|
|
1487
1651
|
} catch (err) {
|
|
1488
|
-
|
|
1489
|
-
F: __dxlog_file6,
|
|
1490
|
-
L: 74,
|
|
1491
|
-
S: this,
|
|
1492
|
-
C: (f, a) => f(...a)
|
|
1493
|
-
});
|
|
1494
|
-
this.close();
|
|
1495
|
-
this._authParams.onAuthFailure();
|
|
1652
|
+
context.close(err);
|
|
1496
1653
|
}
|
|
1497
1654
|
});
|
|
1498
1655
|
}
|
|
1499
1656
|
async onClose() {
|
|
1500
1657
|
await this._ctx.dispose();
|
|
1501
|
-
await super.onClose();
|
|
1502
1658
|
}
|
|
1503
1659
|
async onAbort() {
|
|
1504
1660
|
await this._ctx.dispose();
|
|
1505
|
-
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1663
|
+
var CredentialServerExtension = class extends RpcExtension2 {
|
|
1664
|
+
constructor(_space) {
|
|
1665
|
+
super({
|
|
1666
|
+
exposed: {
|
|
1667
|
+
AdmissionDiscoveryService: schema5.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
this._space = _space;
|
|
1671
|
+
}
|
|
1672
|
+
async getHandlers() {
|
|
1673
|
+
return {
|
|
1674
|
+
AdmissionDiscoveryService: {
|
|
1675
|
+
getAdmissionCredential: async (request) => {
|
|
1676
|
+
const memberInfo = this._space.spaceState.members.get(request.memberKey);
|
|
1677
|
+
if (!memberInfo?.credential) {
|
|
1678
|
+
throw new ProtocolError("Space member not found.", request);
|
|
1679
|
+
}
|
|
1680
|
+
return {
|
|
1681
|
+
admissionCredential: memberInfo.credential
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1506
1686
|
}
|
|
1507
1687
|
};
|
|
1508
1688
|
|
|
1509
|
-
// packages/core/echo/echo-pipeline/src/
|
|
1510
|
-
import {
|
|
1511
|
-
import {
|
|
1512
|
-
import { log as
|
|
1513
|
-
import {
|
|
1514
|
-
|
|
1689
|
+
// packages/core/echo/echo-pipeline/src/space/space-protocol.ts
|
|
1690
|
+
import { discoveryKey, subtleCrypto as subtleCrypto3 } from "@dxos/crypto";
|
|
1691
|
+
import { PublicKey as PublicKey5 } from "@dxos/keys";
|
|
1692
|
+
import { log as log8, logInfo as logInfo2 } from "@dxos/log";
|
|
1693
|
+
import { MMSTTopology } from "@dxos/network-manager";
|
|
1694
|
+
import { Teleport } from "@dxos/teleport";
|
|
1695
|
+
import { BlobSync } from "@dxos/teleport-extension-object-sync";
|
|
1696
|
+
import { ReplicatorExtension } from "@dxos/teleport-extension-replicator";
|
|
1697
|
+
import { trace as trace3 } from "@dxos/tracing";
|
|
1698
|
+
import { CallbackCollection, ComplexMap as ComplexMap3 } from "@dxos/util";
|
|
1699
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
1515
1700
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1516
1701
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1517
1702
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1521,575 +1706,726 @@ function _ts_decorate3(decorators, target, key, desc) {
|
|
|
1521
1706
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1522
1707
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1523
1708
|
}
|
|
1524
|
-
var
|
|
1525
|
-
var
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
})
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
})
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
this.
|
|
1540
|
-
this.
|
|
1541
|
-
this.
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
}
|
|
1549
|
-
/**
|
|
1550
|
-
* Timeframe that is currently being processed by ECHO.
|
|
1551
|
-
* Will be equal to `timeframe` after the processing is complete.
|
|
1552
|
-
*/
|
|
1553
|
-
get pendingTimeframe() {
|
|
1554
|
-
return this._pendingTimeframe;
|
|
1555
|
-
}
|
|
1556
|
-
setTimeframe(timeframe) {
|
|
1557
|
-
this._timeframe = timeframe;
|
|
1558
|
-
this._pendingTimeframe = timeframe;
|
|
1559
|
-
this.update.emit(this._timeframe);
|
|
1709
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space-protocol.ts";
|
|
1710
|
+
var MOCK_AUTH_PROVIDER = async (nonce) => Buffer.from("mock");
|
|
1711
|
+
var MOCK_AUTH_VERIFIER = async (nonce, credential) => true;
|
|
1712
|
+
var SpaceProtocol = class {
|
|
1713
|
+
constructor({ topic, swarmIdentity, networkManager, onSessionAuth, onAuthFailure, blobStore, disableP2pReplication }) {
|
|
1714
|
+
this._feeds = /* @__PURE__ */ new Set();
|
|
1715
|
+
this._sessions = new ComplexMap3(PublicKey5.hash);
|
|
1716
|
+
// TODO(burdon): Move to config (with sensible defaults).
|
|
1717
|
+
this._topology = new MMSTTopology({
|
|
1718
|
+
originateConnections: 4,
|
|
1719
|
+
maxPeers: 10,
|
|
1720
|
+
sampleSize: 20
|
|
1721
|
+
});
|
|
1722
|
+
this.feedAdded = new CallbackCollection();
|
|
1723
|
+
this._spaceKey = topic;
|
|
1724
|
+
this._networkManager = networkManager;
|
|
1725
|
+
this._swarmIdentity = swarmIdentity;
|
|
1726
|
+
this._onSessionAuth = onSessionAuth;
|
|
1727
|
+
this._onAuthFailure = onAuthFailure;
|
|
1728
|
+
this.blobSync = new BlobSync({
|
|
1729
|
+
blobStore
|
|
1730
|
+
});
|
|
1731
|
+
this._topic = subtleCrypto3.digest("SHA-256", topic.asBuffer()).then(discoveryKey).then(PublicKey5.from);
|
|
1732
|
+
this._disableP2pReplication = disableP2pReplication ?? false;
|
|
1560
1733
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
[
|
|
1564
|
-
key,
|
|
1565
|
-
seq
|
|
1566
|
-
]
|
|
1567
|
-
]));
|
|
1734
|
+
get sessions() {
|
|
1735
|
+
return this._sessions;
|
|
1568
1736
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
this.update.emit(this._timeframe);
|
|
1737
|
+
get feeds() {
|
|
1738
|
+
return this._feeds;
|
|
1572
1739
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return !gaps.isEmpty();
|
|
1740
|
+
get _ownPeerKey() {
|
|
1741
|
+
return this._swarmIdentity.peerKey;
|
|
1576
1742
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1743
|
+
// TODO(burdon): Create abstraction for Space (e.g., add keys and have provider).
|
|
1744
|
+
async addFeed(feed) {
|
|
1745
|
+
log8("addFeed", {
|
|
1746
|
+
key: feed.key
|
|
1581
1747
|
}, {
|
|
1582
|
-
F:
|
|
1583
|
-
L:
|
|
1748
|
+
F: __dxlog_file10,
|
|
1749
|
+
L: 127,
|
|
1584
1750
|
S: this,
|
|
1585
1751
|
C: (f, a) => f(...a)
|
|
1586
1752
|
});
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
}, {
|
|
1593
|
-
F: __dxlog_file7,
|
|
1594
|
-
L: 72,
|
|
1595
|
-
S: this,
|
|
1596
|
-
C: (f, a) => f(...a)
|
|
1597
|
-
});
|
|
1598
|
-
return Timeframe.dependencies(target, this._timeframe).isEmpty();
|
|
1599
|
-
});
|
|
1753
|
+
this._feeds.add(feed);
|
|
1754
|
+
for (const session of this._sessions.values()) {
|
|
1755
|
+
session.replicator.addFeed(feed);
|
|
1756
|
+
}
|
|
1757
|
+
await this.feedAdded.callSerial(feed);
|
|
1600
1758
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
// packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
|
|
1607
|
-
import { Event as Event4, sleepWithContext, synchronized as synchronized2, Trigger as Trigger2 } from "@dxos/async";
|
|
1608
|
-
import { Context as Context3, rejectOnDispose } from "@dxos/context";
|
|
1609
|
-
import { failUndefined } from "@dxos/debug";
|
|
1610
|
-
import { FeedSetIterator } from "@dxos/feed-store";
|
|
1611
|
-
import { invariant as invariant8 } from "@dxos/invariant";
|
|
1612
|
-
import { PublicKey as PublicKey3 } from "@dxos/keys";
|
|
1613
|
-
import { log as log7 } from "@dxos/log";
|
|
1614
|
-
import { Timeframe as Timeframe2 } from "@dxos/timeframe";
|
|
1615
|
-
import { ComplexMap } from "@dxos/util";
|
|
1616
|
-
|
|
1617
|
-
// packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts
|
|
1618
|
-
import { invariant as invariant7 } from "@dxos/invariant";
|
|
1619
|
-
import { log as log6 } from "@dxos/log";
|
|
1620
|
-
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts";
|
|
1621
|
-
var createMessageSelector = (timeframeClock) => {
|
|
1622
|
-
return (messages) => {
|
|
1623
|
-
for (let i = 0; i < messages.length; i++) {
|
|
1624
|
-
const { data: { timeframe } } = messages[i];
|
|
1625
|
-
invariant7(timeframe, void 0, {
|
|
1626
|
-
F: __dxlog_file8,
|
|
1627
|
-
L: 25,
|
|
1628
|
-
S: void 0,
|
|
1629
|
-
A: [
|
|
1630
|
-
"timeframe",
|
|
1631
|
-
""
|
|
1632
|
-
]
|
|
1633
|
-
});
|
|
1634
|
-
if (!timeframeClock.hasGaps(timeframe)) {
|
|
1635
|
-
return i;
|
|
1636
|
-
}
|
|
1759
|
+
// TODO(burdon): Rename open? Common open/close interfaces for all services?
|
|
1760
|
+
async start() {
|
|
1761
|
+
if (this._connection) {
|
|
1762
|
+
return;
|
|
1637
1763
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1764
|
+
const credentials = await this._swarmIdentity.credentialProvider(Buffer.from(""));
|
|
1765
|
+
await this.blobSync.open();
|
|
1766
|
+
log8("starting...", void 0, {
|
|
1767
|
+
F: __dxlog_file10,
|
|
1768
|
+
L: 148,
|
|
1769
|
+
S: this,
|
|
1642
1770
|
C: (f, a) => f(...a)
|
|
1643
1771
|
});
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
}
|
|
1658
|
-
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts";
|
|
1659
|
-
var PipelineState = class {
|
|
1660
|
-
constructor(_feeds, _timeframeClock) {
|
|
1661
|
-
this._feeds = _feeds;
|
|
1662
|
-
this._timeframeClock = _timeframeClock;
|
|
1663
|
-
this._ctx = new Context3(void 0, {
|
|
1664
|
-
F: __dxlog_file9,
|
|
1665
|
-
L: 41
|
|
1772
|
+
const topic = await this._topic;
|
|
1773
|
+
this._connection = await this._networkManager.joinSwarm({
|
|
1774
|
+
protocolProvider: this._createProtocolProvider(credentials),
|
|
1775
|
+
peerId: this._swarmIdentity.peerKey,
|
|
1776
|
+
topic,
|
|
1777
|
+
topology: this._topology,
|
|
1778
|
+
label: `swarm ${topic.truncate()} for space ${this._spaceKey.truncate()}`
|
|
1779
|
+
});
|
|
1780
|
+
log8("started", void 0, {
|
|
1781
|
+
F: __dxlog_file10,
|
|
1782
|
+
L: 158,
|
|
1783
|
+
S: this,
|
|
1784
|
+
C: (f, a) => f(...a)
|
|
1666
1785
|
});
|
|
1667
|
-
this.timeframeUpdate = this._timeframeClock.update;
|
|
1668
|
-
this.stalled = new Event4();
|
|
1669
|
-
this._startTimeframe = new Timeframe2();
|
|
1670
|
-
this._reachedTarget = false;
|
|
1671
1786
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
* NOTE: This might never be reached if the mutation dependencies
|
|
1675
|
-
*/
|
|
1676
|
-
// TODO(dmaretskyi): Rename `totalTimeframe`? or `lastTimeframe`.
|
|
1677
|
-
get endTimeframe() {
|
|
1678
|
-
return mapFeedIndexesToTimeframe(Array.from(this._feeds.values()).filter((feed) => feed.length > 0).map((feed) => ({
|
|
1679
|
-
feedKey: feed.key,
|
|
1680
|
-
index: feed.length - 1
|
|
1681
|
-
})));
|
|
1787
|
+
updateTopology() {
|
|
1788
|
+
this._topology.forceUpdate();
|
|
1682
1789
|
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1790
|
+
async stop() {
|
|
1791
|
+
await this.blobSync.close();
|
|
1792
|
+
if (this._connection) {
|
|
1793
|
+
log8("stopping...", void 0, {
|
|
1794
|
+
F: __dxlog_file10,
|
|
1795
|
+
L: 169,
|
|
1796
|
+
S: this,
|
|
1797
|
+
C: (f, a) => f(...a)
|
|
1798
|
+
});
|
|
1799
|
+
await this._connection.close();
|
|
1800
|
+
log8("stopped", void 0, {
|
|
1801
|
+
F: __dxlog_file10,
|
|
1802
|
+
L: 171,
|
|
1803
|
+
S: this,
|
|
1804
|
+
C: (f, a) => f(...a)
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1685
1807
|
}
|
|
1686
|
-
|
|
1687
|
-
return
|
|
1808
|
+
_createProtocolProvider(credentials) {
|
|
1809
|
+
return (wireParams) => {
|
|
1810
|
+
const session = new SpaceProtocolSession({
|
|
1811
|
+
wireParams,
|
|
1812
|
+
swarmIdentity: this._swarmIdentity,
|
|
1813
|
+
onSessionAuth: this._onSessionAuth,
|
|
1814
|
+
onAuthFailure: this._onAuthFailure,
|
|
1815
|
+
blobSync: this.blobSync,
|
|
1816
|
+
disableP2pReplication: this._disableP2pReplication
|
|
1817
|
+
});
|
|
1818
|
+
this._sessions.set(wireParams.remotePeerId, session);
|
|
1819
|
+
for (const feed of this._feeds) {
|
|
1820
|
+
session.replicator.addFeed(feed);
|
|
1821
|
+
}
|
|
1822
|
+
return session;
|
|
1823
|
+
};
|
|
1688
1824
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1825
|
+
};
|
|
1826
|
+
_ts_decorate5([
|
|
1827
|
+
logInfo2,
|
|
1828
|
+
trace3.info()
|
|
1829
|
+
], SpaceProtocol.prototype, "_topic", void 0);
|
|
1830
|
+
_ts_decorate5([
|
|
1831
|
+
trace3.info()
|
|
1832
|
+
], SpaceProtocol.prototype, "_spaceKey", void 0);
|
|
1833
|
+
_ts_decorate5([
|
|
1834
|
+
logInfo2
|
|
1835
|
+
], SpaceProtocol.prototype, "_ownPeerKey", null);
|
|
1836
|
+
SpaceProtocol = _ts_decorate5([
|
|
1837
|
+
trace3.resource()
|
|
1838
|
+
], SpaceProtocol);
|
|
1839
|
+
var AuthStatus;
|
|
1840
|
+
(function(AuthStatus2) {
|
|
1841
|
+
AuthStatus2["INITIAL"] = "INITIAL";
|
|
1842
|
+
AuthStatus2["SUCCESS"] = "SUCCESS";
|
|
1843
|
+
AuthStatus2["FAILURE"] = "FAILURE";
|
|
1844
|
+
})(AuthStatus || (AuthStatus = {}));
|
|
1845
|
+
var SpaceProtocolSession = class {
|
|
1846
|
+
// TODO(dmaretskyi): Allow to pass in extra extensions.
|
|
1847
|
+
constructor({ wireParams, swarmIdentity, onSessionAuth, onAuthFailure, blobSync, disableP2pReplication }) {
|
|
1848
|
+
// TODO(dmaretskyi): Start with upload=false when switching it on the fly works.
|
|
1849
|
+
this.replicator = new ReplicatorExtension().setOptions({
|
|
1850
|
+
upload: true
|
|
1851
|
+
});
|
|
1852
|
+
this._authStatus = "INITIAL";
|
|
1853
|
+
this._wireParams = wireParams;
|
|
1854
|
+
this._swarmIdentity = swarmIdentity;
|
|
1855
|
+
this._onSessionAuth = onSessionAuth;
|
|
1856
|
+
this._onAuthFailure = onAuthFailure;
|
|
1857
|
+
this._blobSync = blobSync;
|
|
1858
|
+
this._teleport = new Teleport(wireParams);
|
|
1859
|
+
this._disableP2pReplication = disableP2pReplication ?? false;
|
|
1691
1860
|
}
|
|
1692
|
-
get
|
|
1693
|
-
return this.
|
|
1861
|
+
get authStatus() {
|
|
1862
|
+
return this._authStatus;
|
|
1694
1863
|
}
|
|
1695
|
-
get
|
|
1696
|
-
return this.
|
|
1864
|
+
get stats() {
|
|
1865
|
+
return this._teleport.stats;
|
|
1697
1866
|
}
|
|
1698
|
-
get
|
|
1699
|
-
return
|
|
1700
|
-
}
|
|
1701
|
-
async waitUntilTimeframe(target) {
|
|
1702
|
-
await this._timeframeClock.waitUntilReached(target);
|
|
1867
|
+
get stream() {
|
|
1868
|
+
return this._teleport.stream;
|
|
1703
1869
|
}
|
|
1704
|
-
|
|
1705
|
-
this.
|
|
1870
|
+
async open(sessionId) {
|
|
1871
|
+
await this._teleport.open(sessionId);
|
|
1872
|
+
this._teleport.addExtension("dxos.mesh.teleport.auth", new AuthExtension({
|
|
1873
|
+
provider: this._swarmIdentity.credentialProvider,
|
|
1874
|
+
verifier: this._swarmIdentity.credentialAuthenticator,
|
|
1875
|
+
onAuthSuccess: () => {
|
|
1876
|
+
log8("Peer authenticated", void 0, {
|
|
1877
|
+
F: __dxlog_file10,
|
|
1878
|
+
L: 282,
|
|
1879
|
+
S: this,
|
|
1880
|
+
C: (f, a) => f(...a)
|
|
1881
|
+
});
|
|
1882
|
+
this._authStatus = "SUCCESS";
|
|
1883
|
+
this._onSessionAuth?.(this._teleport);
|
|
1884
|
+
},
|
|
1885
|
+
onAuthFailure: () => {
|
|
1886
|
+
this._authStatus = "FAILURE";
|
|
1887
|
+
this._onAuthFailure?.(this._teleport);
|
|
1888
|
+
}
|
|
1889
|
+
}));
|
|
1890
|
+
if (!this._disableP2pReplication) {
|
|
1891
|
+
this._teleport.addExtension("dxos.mesh.teleport.replicator", this.replicator);
|
|
1892
|
+
}
|
|
1893
|
+
this._teleport.addExtension("dxos.mesh.teleport.blobsync", this._blobSync.createExtension());
|
|
1706
1894
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
*
|
|
1712
|
-
* @param timeout Timeout in milliseconds to specify the maximum wait time.
|
|
1713
|
-
*/
|
|
1714
|
-
async waitUntilReachedTargetTimeframe({ ctx = new Context3(void 0, {
|
|
1715
|
-
F: __dxlog_file9,
|
|
1716
|
-
L: 129
|
|
1717
|
-
}), timeout, breakOnStall = true } = {}) {
|
|
1718
|
-
log7("waitUntilReachedTargetTimeframe", {
|
|
1719
|
-
timeout,
|
|
1720
|
-
current: this.timeframe,
|
|
1721
|
-
target: this.targetTimeframe
|
|
1722
|
-
}, {
|
|
1723
|
-
F: __dxlog_file9,
|
|
1724
|
-
L: 133,
|
|
1895
|
+
async close() {
|
|
1896
|
+
log8("close", void 0, {
|
|
1897
|
+
F: __dxlog_file10,
|
|
1898
|
+
L: 301,
|
|
1725
1899
|
S: this,
|
|
1726
1900
|
C: (f, a) => f(...a)
|
|
1727
1901
|
});
|
|
1728
|
-
this.
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
...breakOnStall ? [
|
|
1733
|
-
this.stalled.discardParameter().waitForCount(1)
|
|
1734
|
-
] : []
|
|
1735
|
-
]);
|
|
1736
|
-
let done = false;
|
|
1737
|
-
if (timeout) {
|
|
1738
|
-
return Promise.race([
|
|
1739
|
-
rejectOnDispose(ctx),
|
|
1740
|
-
rejectOnDispose(this._ctx),
|
|
1741
|
-
this._reachedTargetPromise.then(() => {
|
|
1742
|
-
done = true;
|
|
1743
|
-
this._reachedTarget = true;
|
|
1744
|
-
}),
|
|
1745
|
-
sleepWithContext(this._ctx, timeout).then(() => {
|
|
1746
|
-
if (done) {
|
|
1747
|
-
return;
|
|
1748
|
-
}
|
|
1749
|
-
log7.warn("waitUntilReachedTargetTimeframe timed out", {
|
|
1750
|
-
timeout,
|
|
1751
|
-
current: this.timeframe,
|
|
1752
|
-
target: this.targetTimeframe,
|
|
1753
|
-
dependencies: Timeframe2.dependencies(this.targetTimeframe, this.timeframe)
|
|
1754
|
-
}, {
|
|
1755
|
-
F: __dxlog_file9,
|
|
1756
|
-
L: 161,
|
|
1757
|
-
S: this,
|
|
1758
|
-
C: (f, a) => f(...a)
|
|
1759
|
-
});
|
|
1760
|
-
})
|
|
1761
|
-
]);
|
|
1762
|
-
} else {
|
|
1763
|
-
return this._reachedTargetPromise;
|
|
1764
|
-
}
|
|
1902
|
+
await this._teleport.close();
|
|
1903
|
+
}
|
|
1904
|
+
async abort() {
|
|
1905
|
+
await this._teleport.abort();
|
|
1765
1906
|
}
|
|
1766
1907
|
};
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1908
|
+
_ts_decorate5([
|
|
1909
|
+
logInfo2
|
|
1910
|
+
], SpaceProtocolSession.prototype, "_wireParams", void 0);
|
|
1911
|
+
_ts_decorate5([
|
|
1912
|
+
logInfo2
|
|
1913
|
+
], SpaceProtocolSession.prototype, "authStatus", null);
|
|
1914
|
+
|
|
1915
|
+
// packages/core/echo/echo-pipeline/src/space/space-manager.ts
|
|
1916
|
+
import { synchronized as synchronized4, trackLeaks as trackLeaks3, Trigger as Trigger3 } from "@dxos/async";
|
|
1917
|
+
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
1918
|
+
import { PublicKey as PublicKey8 } from "@dxos/keys";
|
|
1919
|
+
import { log as log14 } from "@dxos/log";
|
|
1920
|
+
import { trace as trace6 } from "@dxos/protocols";
|
|
1921
|
+
import { ComplexMap as ComplexMap4 } from "@dxos/util";
|
|
1922
|
+
|
|
1923
|
+
// packages/core/echo/echo-pipeline/src/db-host/data-service.ts
|
|
1924
|
+
import { Stream } from "@dxos/codec-protobuf";
|
|
1925
|
+
import { invariant as invariant12 } from "@dxos/invariant";
|
|
1926
|
+
import { SpaceId as SpaceId3 } from "@dxos/keys";
|
|
1927
|
+
import { log as log13 } from "@dxos/log";
|
|
1928
|
+
|
|
1929
|
+
// packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
|
|
1930
|
+
import { Event as Event5, asyncTimeout } from "@dxos/async";
|
|
1931
|
+
import { getBackend, getHeads, isAutomerge, equals as headsEquals, save } from "@dxos/automerge/automerge";
|
|
1932
|
+
import { Repo } from "@dxos/automerge/automerge-repo";
|
|
1933
|
+
import { Context as Context5, Resource as Resource5, cancelWithContext as cancelWithContext2 } from "@dxos/context";
|
|
1934
|
+
import { invariant as invariant8 } from "@dxos/invariant";
|
|
1935
|
+
import { PublicKey as PublicKey6 } from "@dxos/keys";
|
|
1936
|
+
import { log as log10 } from "@dxos/log";
|
|
1937
|
+
import { objectPointerCodec } from "@dxos/protocols";
|
|
1938
|
+
import { trace as trace4 } from "@dxos/tracing";
|
|
1939
|
+
|
|
1940
|
+
// packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
|
|
1941
|
+
import { synchronized as synchronized3, Trigger as Trigger2 } from "@dxos/async";
|
|
1942
|
+
import { NetworkAdapter } from "@dxos/automerge/automerge-repo";
|
|
1943
|
+
import { LifecycleState as LifecycleState2 } from "@dxos/context";
|
|
1944
|
+
import { invariant as invariant7 } from "@dxos/invariant";
|
|
1945
|
+
import { log as log9 } from "@dxos/log";
|
|
1946
|
+
import { nonNullable } from "@dxos/util";
|
|
1947
|
+
|
|
1948
|
+
// packages/core/echo/echo-pipeline/src/automerge/network-protocol.ts
|
|
1949
|
+
import { MESSAGE_TYPE_COLLECTION_QUERY, MESSAGE_TYPE_COLLECTION_STATE } from "@dxos/protocols";
|
|
1950
|
+
var isCollectionQueryMessage = (message) => message.type === MESSAGE_TYPE_COLLECTION_QUERY;
|
|
1951
|
+
var isCollectionStateMessage = (message) => message.type === MESSAGE_TYPE_COLLECTION_STATE;
|
|
1952
|
+
|
|
1953
|
+
// packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
|
|
1954
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1955
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1956
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1957
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1958
|
+
else
|
|
1959
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
1960
|
+
if (d = decorators[i])
|
|
1961
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1962
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1963
|
+
}
|
|
1964
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
|
|
1965
|
+
var EchoNetworkAdapter = class extends NetworkAdapter {
|
|
1966
|
+
constructor(_params) {
|
|
1967
|
+
super();
|
|
1968
|
+
this._params = _params;
|
|
1969
|
+
this._replicators = /* @__PURE__ */ new Set();
|
|
1970
|
+
this._connections = /* @__PURE__ */ new Map();
|
|
1971
|
+
this._lifecycleState = LifecycleState2.CLOSED;
|
|
1972
|
+
this._connected = new Trigger2();
|
|
1782
1973
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1974
|
+
connect(peerId, peerMetadata) {
|
|
1975
|
+
this.peerId = peerId;
|
|
1976
|
+
this.peerMetadata = peerMetadata;
|
|
1977
|
+
this._connected.wake();
|
|
1785
1978
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
F: __dxlog_file9,
|
|
1789
|
-
L: 243,
|
|
1790
|
-
S: this,
|
|
1791
|
-
A: [
|
|
1792
|
-
"this._writer",
|
|
1793
|
-
"'Writer not set.'"
|
|
1794
|
-
]
|
|
1795
|
-
});
|
|
1796
|
-
return this._writer;
|
|
1979
|
+
send(message) {
|
|
1980
|
+
this._send(message);
|
|
1797
1981
|
}
|
|
1798
|
-
|
|
1799
|
-
return this._feeds.has(feedKey);
|
|
1982
|
+
disconnect() {
|
|
1800
1983
|
}
|
|
1801
|
-
|
|
1802
|
-
|
|
1984
|
+
async open() {
|
|
1985
|
+
if (this._lifecycleState === LifecycleState2.OPEN) {
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
this._lifecycleState = LifecycleState2.OPEN;
|
|
1989
|
+
log9("emit ready", void 0, {
|
|
1990
|
+
F: __dxlog_file11,
|
|
1991
|
+
L: 81,
|
|
1992
|
+
S: this,
|
|
1993
|
+
C: (f, a) => f(...a)
|
|
1994
|
+
});
|
|
1995
|
+
this.emit("ready", {
|
|
1996
|
+
network: this
|
|
1997
|
+
});
|
|
1803
1998
|
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
this._feeds.set(feed.key, feed);
|
|
1808
|
-
if (this._feedSetIterator) {
|
|
1809
|
-
await this._feedSetIterator.addFeed(feed);
|
|
1999
|
+
async close() {
|
|
2000
|
+
if (this._lifecycleState === LifecycleState2.CLOSED) {
|
|
2001
|
+
return this;
|
|
1810
2002
|
}
|
|
1811
|
-
|
|
1812
|
-
|
|
2003
|
+
for (const replicator of this._replicators) {
|
|
2004
|
+
await replicator.disconnect();
|
|
1813
2005
|
}
|
|
2006
|
+
this._replicators.clear();
|
|
2007
|
+
this._lifecycleState = LifecycleState2.CLOSED;
|
|
1814
2008
|
}
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
2009
|
+
async whenConnected() {
|
|
2010
|
+
await this._connected.wait({
|
|
2011
|
+
timeout: 1e4
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
async addReplicator(replicator) {
|
|
2015
|
+
invariant7(this._lifecycleState === LifecycleState2.OPEN, void 0, {
|
|
2016
|
+
F: __dxlog_file11,
|
|
2017
|
+
L: 107,
|
|
1819
2018
|
S: this,
|
|
1820
2019
|
A: [
|
|
1821
|
-
"
|
|
1822
|
-
"
|
|
2020
|
+
"this._lifecycleState === LifecycleState.OPEN",
|
|
2021
|
+
""
|
|
1823
2022
|
]
|
|
1824
2023
|
});
|
|
1825
|
-
|
|
1826
|
-
F:
|
|
1827
|
-
L:
|
|
2024
|
+
invariant7(this.peerId, void 0, {
|
|
2025
|
+
F: __dxlog_file11,
|
|
2026
|
+
L: 108,
|
|
1828
2027
|
S: this,
|
|
1829
2028
|
A: [
|
|
1830
|
-
"
|
|
1831
|
-
"
|
|
2029
|
+
"this.peerId",
|
|
2030
|
+
""
|
|
1832
2031
|
]
|
|
1833
2032
|
});
|
|
1834
|
-
this.
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
}), feed.createFeedWriter());
|
|
1838
|
-
}
|
|
1839
|
-
async start() {
|
|
1840
|
-
invariant8(!this._isStarted, "Pipeline is already started.", {
|
|
1841
|
-
F: __dxlog_file9,
|
|
1842
|
-
L: 284,
|
|
2033
|
+
invariant7(!this._replicators.has(replicator), void 0, {
|
|
2034
|
+
F: __dxlog_file11,
|
|
2035
|
+
L: 109,
|
|
1843
2036
|
S: this,
|
|
1844
2037
|
A: [
|
|
1845
|
-
"!this.
|
|
1846
|
-
"
|
|
2038
|
+
"!this._replicators.has(replicator)",
|
|
2039
|
+
""
|
|
1847
2040
|
]
|
|
1848
2041
|
});
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
2042
|
+
this._replicators.add(replicator);
|
|
2043
|
+
await replicator.connect({
|
|
2044
|
+
peerId: this.peerId,
|
|
2045
|
+
onConnectionOpen: this._onConnectionOpen.bind(this),
|
|
2046
|
+
onConnectionClosed: this._onConnectionClosed.bind(this),
|
|
2047
|
+
onConnectionAuthScopeChanged: this._onConnectionAuthScopeChanged.bind(this),
|
|
2048
|
+
isDocumentInRemoteCollection: this._params.isDocumentInRemoteCollection,
|
|
2049
|
+
getContainingSpaceForDocument: this._params.getContainingSpaceForDocument,
|
|
2050
|
+
getContainingSpaceIdForDocument: async (documentId) => {
|
|
2051
|
+
const key = await this._params.getContainingSpaceForDocument(documentId);
|
|
2052
|
+
return key ? createIdFromSpaceKey(key) : null;
|
|
2053
|
+
}
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
async removeReplicator(replicator) {
|
|
2057
|
+
invariant7(this._lifecycleState === LifecycleState2.OPEN, void 0, {
|
|
2058
|
+
F: __dxlog_file11,
|
|
2059
|
+
L: 128,
|
|
1852
2060
|
S: this,
|
|
1853
|
-
|
|
2061
|
+
A: [
|
|
2062
|
+
"this._lifecycleState === LifecycleState.OPEN",
|
|
2063
|
+
""
|
|
2064
|
+
]
|
|
1854
2065
|
});
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
log7("started", void 0, {
|
|
1859
|
-
F: __dxlog_file9,
|
|
1860
|
-
L: 289,
|
|
2066
|
+
invariant7(this._replicators.has(replicator), void 0, {
|
|
2067
|
+
F: __dxlog_file11,
|
|
2068
|
+
L: 129,
|
|
1861
2069
|
S: this,
|
|
1862
|
-
|
|
2070
|
+
A: [
|
|
2071
|
+
"this._replicators.has(replicator)",
|
|
2072
|
+
""
|
|
2073
|
+
]
|
|
1863
2074
|
});
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
2075
|
+
await replicator.disconnect();
|
|
2076
|
+
this._replicators.delete(replicator);
|
|
2077
|
+
}
|
|
2078
|
+
async shouldAdvertise(peerId, params) {
|
|
2079
|
+
const connection = this._connections.get(peerId);
|
|
2080
|
+
if (!connection) {
|
|
2081
|
+
return false;
|
|
1868
2082
|
}
|
|
2083
|
+
return connection.connection.shouldAdvertise(params);
|
|
1869
2084
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
S: this,
|
|
1875
|
-
C: (f, a) => f(...a)
|
|
1876
|
-
});
|
|
1877
|
-
this._isStopping = true;
|
|
1878
|
-
for (const [feed, handle] of this._downloads.entries()) {
|
|
1879
|
-
feed.undownload(handle);
|
|
2085
|
+
shouldSyncCollection(peerId, params) {
|
|
2086
|
+
const connection = this._connections.get(peerId);
|
|
2087
|
+
if (!connection) {
|
|
2088
|
+
return false;
|
|
1880
2089
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
2090
|
+
return connection.connection.shouldSyncCollection(params);
|
|
2091
|
+
}
|
|
2092
|
+
queryCollectionState(collectionId, targetId) {
|
|
2093
|
+
const message = {
|
|
2094
|
+
type: "collection-query",
|
|
2095
|
+
senderId: this.peerId,
|
|
2096
|
+
targetId,
|
|
2097
|
+
collectionId
|
|
2098
|
+
};
|
|
2099
|
+
this._send(message);
|
|
2100
|
+
}
|
|
2101
|
+
sendCollectionState(collectionId, targetId, state) {
|
|
2102
|
+
const message = {
|
|
2103
|
+
type: "collection-state",
|
|
2104
|
+
senderId: this.peerId,
|
|
2105
|
+
targetId,
|
|
2106
|
+
collectionId,
|
|
2107
|
+
state
|
|
2108
|
+
};
|
|
2109
|
+
this._send(message);
|
|
2110
|
+
}
|
|
2111
|
+
_send(message) {
|
|
2112
|
+
const connectionEntry = this._connections.get(message.targetId);
|
|
2113
|
+
if (!connectionEntry) {
|
|
2114
|
+
throw new Error("Connection not found.");
|
|
2115
|
+
}
|
|
2116
|
+
const writeStart = Date.now();
|
|
2117
|
+
connectionEntry.writer.write(message).then(() => {
|
|
2118
|
+
const durationMs = Date.now() - writeStart;
|
|
2119
|
+
this._params.monitor?.recordMessageSent(message, durationMs);
|
|
2120
|
+
}).catch((err) => {
|
|
2121
|
+
if (connectionEntry.isOpen) {
|
|
2122
|
+
log9.catch(err, void 0, {
|
|
2123
|
+
F: __dxlog_file11,
|
|
2124
|
+
L: 189,
|
|
2125
|
+
S: this,
|
|
2126
|
+
C: (f, a) => f(...a)
|
|
2127
|
+
});
|
|
2128
|
+
}
|
|
2129
|
+
this._params.monitor?.recordMessageSendingFailed(message);
|
|
1888
2130
|
});
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2131
|
+
}
|
|
2132
|
+
// TODO(dmaretskyi): Remove.
|
|
2133
|
+
getPeersInterestedInCollection(collectionId) {
|
|
2134
|
+
return Array.from(this._connections.values()).map((connection) => {
|
|
2135
|
+
return connection.connection.shouldSyncCollection({
|
|
2136
|
+
collectionId
|
|
2137
|
+
}) ? connection.connection.peerId : null;
|
|
2138
|
+
}).filter(nonNullable);
|
|
2139
|
+
}
|
|
2140
|
+
_onConnectionOpen(connection) {
|
|
2141
|
+
log9("Connection opened", {
|
|
2142
|
+
peerId: connection.peerId
|
|
2143
|
+
}, {
|
|
2144
|
+
F: __dxlog_file11,
|
|
2145
|
+
L: 207,
|
|
1895
2146
|
S: this,
|
|
1896
2147
|
C: (f, a) => f(...a)
|
|
1897
2148
|
});
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
* The pipeline will start processing messages AFTER this timeframe.
|
|
1902
|
-
*/
|
|
1903
|
-
async setCursor(timeframe) {
|
|
1904
|
-
invariant8(!this._isStarted || this._isPaused, "Invalid state.", {
|
|
1905
|
-
F: __dxlog_file9,
|
|
1906
|
-
L: 322,
|
|
2149
|
+
invariant7(!this._connections.has(connection.peerId), void 0, {
|
|
2150
|
+
F: __dxlog_file11,
|
|
2151
|
+
L: 208,
|
|
1907
2152
|
S: this,
|
|
1908
2153
|
A: [
|
|
1909
|
-
"!this.
|
|
1910
|
-
"
|
|
2154
|
+
"!this._connections.has(connection.peerId as PeerId)",
|
|
2155
|
+
""
|
|
1911
2156
|
]
|
|
1912
2157
|
});
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
2158
|
+
const reader = connection.readable.getReader();
|
|
2159
|
+
const writer = connection.writable.getWriter();
|
|
2160
|
+
const connectionEntry = {
|
|
2161
|
+
connection,
|
|
2162
|
+
reader,
|
|
2163
|
+
writer,
|
|
2164
|
+
isOpen: true
|
|
2165
|
+
};
|
|
2166
|
+
this._connections.set(connection.peerId, connectionEntry);
|
|
2167
|
+
queueMicrotask(async () => {
|
|
2168
|
+
try {
|
|
2169
|
+
while (true) {
|
|
2170
|
+
const { done, value } = await reader.read();
|
|
2171
|
+
if (done) {
|
|
2172
|
+
break;
|
|
2173
|
+
}
|
|
2174
|
+
this._onMessage(value);
|
|
2175
|
+
}
|
|
2176
|
+
} catch (err) {
|
|
2177
|
+
if (connectionEntry.isOpen) {
|
|
2178
|
+
log9.catch(err, void 0, {
|
|
2179
|
+
F: __dxlog_file11,
|
|
2180
|
+
L: 227,
|
|
2181
|
+
S: this,
|
|
2182
|
+
C: (f, a) => f(...a)
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
});
|
|
2187
|
+
log9("emit peer-candidate", {
|
|
2188
|
+
peerId: connection.peerId
|
|
2189
|
+
}, {
|
|
2190
|
+
F: __dxlog_file11,
|
|
2191
|
+
L: 232,
|
|
1936
2192
|
S: this,
|
|
1937
|
-
|
|
1938
|
-
"this._isPaused",
|
|
1939
|
-
"'Pipeline is not paused.'"
|
|
1940
|
-
]
|
|
2193
|
+
C: (f, a) => f(...a)
|
|
1941
2194
|
});
|
|
1942
|
-
this.
|
|
1943
|
-
this.
|
|
1944
|
-
|
|
1945
|
-
|
|
2195
|
+
this._emitPeerCandidate(connection);
|
|
2196
|
+
this._params.monitor?.recordPeerConnected(connection.peerId);
|
|
2197
|
+
}
|
|
2198
|
+
_onMessage(message) {
|
|
2199
|
+
if (isCollectionQueryMessage(message)) {
|
|
2200
|
+
this._params.onCollectionStateQueried(message.collectionId, message.senderId);
|
|
2201
|
+
} else if (isCollectionStateMessage(message)) {
|
|
2202
|
+
this._params.onCollectionStateReceived(message.collectionId, message.senderId, message.state);
|
|
2203
|
+
} else {
|
|
2204
|
+
this.emit("message", message);
|
|
1946
2205
|
}
|
|
2206
|
+
this._params.monitor?.recordMessageReceived(message);
|
|
1947
2207
|
}
|
|
1948
2208
|
/**
|
|
1949
|
-
*
|
|
1950
|
-
*
|
|
2209
|
+
* Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.
|
|
2210
|
+
* TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
|
|
1951
2211
|
*/
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2212
|
+
_onConnectionAuthScopeChanged(connection) {
|
|
2213
|
+
log9("Connection auth scope changed", {
|
|
2214
|
+
peerId: connection.peerId
|
|
2215
|
+
}, {
|
|
2216
|
+
F: __dxlog_file11,
|
|
2217
|
+
L: 253,
|
|
1956
2218
|
S: this,
|
|
1957
|
-
|
|
1958
|
-
"!this._isBeingConsumed",
|
|
1959
|
-
"'Pipeline is already being consumed.'"
|
|
1960
|
-
]
|
|
2219
|
+
C: (f, a) => f(...a)
|
|
1961
2220
|
});
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
F:
|
|
1965
|
-
L:
|
|
2221
|
+
const entry = this._connections.get(connection.peerId);
|
|
2222
|
+
invariant7(entry, void 0, {
|
|
2223
|
+
F: __dxlog_file11,
|
|
2224
|
+
L: 255,
|
|
1966
2225
|
S: this,
|
|
1967
2226
|
A: [
|
|
1968
|
-
"
|
|
1969
|
-
"
|
|
2227
|
+
"entry",
|
|
2228
|
+
""
|
|
1970
2229
|
]
|
|
1971
2230
|
});
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
if (lastFeedSetIterator !== this._feedSetIterator) {
|
|
1977
|
-
invariant8(this._feedSetIterator, "Iterator not initialized.", {
|
|
1978
|
-
F: __dxlog_file9,
|
|
1979
|
-
L: 378,
|
|
1980
|
-
S: this,
|
|
1981
|
-
A: [
|
|
1982
|
-
"this._feedSetIterator",
|
|
1983
|
-
"'Iterator not initialized.'"
|
|
1984
|
-
]
|
|
1985
|
-
});
|
|
1986
|
-
lastFeedSetIterator = this._feedSetIterator;
|
|
1987
|
-
iterable = lastFeedSetIterator[Symbol.asyncIterator]();
|
|
1988
|
-
}
|
|
1989
|
-
const { done, value } = await iterable.next();
|
|
1990
|
-
if (!done) {
|
|
1991
|
-
const block = value ?? failUndefined();
|
|
1992
|
-
this._processingTrigger.reset();
|
|
1993
|
-
this._timeframeClock.updatePendingTimeframe(PublicKey3.from(block.feedKey), block.seq);
|
|
1994
|
-
yield block;
|
|
1995
|
-
this._processingTrigger.wake();
|
|
1996
|
-
this._timeframeClock.updateTimeframe();
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
this._isBeingConsumed = false;
|
|
2231
|
+
this.emit("peer-disconnected", {
|
|
2232
|
+
peerId: connection.peerId
|
|
2233
|
+
});
|
|
2234
|
+
this._emitPeerCandidate(connection);
|
|
2000
2235
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
feed.undownload(handle);
|
|
2005
|
-
}
|
|
2006
|
-
const timeframe = this._state._startTimeframe;
|
|
2007
|
-
const seq = timeframe.get(feed.key) ?? -1;
|
|
2008
|
-
log7("download", {
|
|
2009
|
-
feed: feed.key.truncate(),
|
|
2010
|
-
seq,
|
|
2011
|
-
length: feed.length
|
|
2236
|
+
_onConnectionClosed(connection) {
|
|
2237
|
+
log9("Connection closed", {
|
|
2238
|
+
peerId: connection.peerId
|
|
2012
2239
|
}, {
|
|
2013
|
-
F:
|
|
2014
|
-
L:
|
|
2240
|
+
F: __dxlog_file11,
|
|
2241
|
+
L: 261,
|
|
2015
2242
|
S: this,
|
|
2016
2243
|
C: (f, a) => f(...a)
|
|
2017
2244
|
});
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
F: __dxlog_file9,
|
|
2028
|
-
L: 412,
|
|
2029
|
-
S: this,
|
|
2030
|
-
C: (f, a) => f(...a)
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2245
|
+
const entry = this._connections.get(connection.peerId);
|
|
2246
|
+
invariant7(entry, void 0, {
|
|
2247
|
+
F: __dxlog_file11,
|
|
2248
|
+
L: 263,
|
|
2249
|
+
S: this,
|
|
2250
|
+
A: [
|
|
2251
|
+
"entry",
|
|
2252
|
+
""
|
|
2253
|
+
]
|
|
2033
2254
|
});
|
|
2034
|
-
|
|
2255
|
+
entry.isOpen = false;
|
|
2256
|
+
this.emit("peer-disconnected", {
|
|
2257
|
+
peerId: connection.peerId
|
|
2258
|
+
});
|
|
2259
|
+
this._params.monitor?.recordPeerDisconnected(connection.peerId);
|
|
2260
|
+
void entry.reader.cancel().catch((err) => log9.catch(err, void 0, {
|
|
2261
|
+
F: __dxlog_file11,
|
|
2262
|
+
L: 269,
|
|
2263
|
+
S: this,
|
|
2264
|
+
C: (f, a) => f(...a)
|
|
2265
|
+
}));
|
|
2266
|
+
void entry.writer.abort().catch((err) => log9.catch(err, void 0, {
|
|
2267
|
+
F: __dxlog_file11,
|
|
2268
|
+
L: 270,
|
|
2269
|
+
S: this,
|
|
2270
|
+
C: (f, a) => f(...a)
|
|
2271
|
+
}));
|
|
2272
|
+
this._connections.delete(connection.peerId);
|
|
2035
2273
|
}
|
|
2036
|
-
|
|
2037
|
-
this.
|
|
2038
|
-
|
|
2039
|
-
|
|
2274
|
+
_emitPeerCandidate(connection) {
|
|
2275
|
+
this.emit("peer-candidate", {
|
|
2276
|
+
peerId: connection.peerId,
|
|
2277
|
+
peerMetadata: createEchoPeerMetadata()
|
|
2040
2278
|
});
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2279
|
+
}
|
|
2280
|
+
};
|
|
2281
|
+
_ts_decorate6([
|
|
2282
|
+
synchronized3
|
|
2283
|
+
], EchoNetworkAdapter.prototype, "open", null);
|
|
2284
|
+
_ts_decorate6([
|
|
2285
|
+
synchronized3
|
|
2286
|
+
], EchoNetworkAdapter.prototype, "close", null);
|
|
2287
|
+
_ts_decorate6([
|
|
2288
|
+
synchronized3
|
|
2289
|
+
], EchoNetworkAdapter.prototype, "addReplicator", null);
|
|
2290
|
+
_ts_decorate6([
|
|
2291
|
+
synchronized3
|
|
2292
|
+
], EchoNetworkAdapter.prototype, "removeReplicator", null);
|
|
2293
|
+
var createEchoPeerMetadata = () => ({
|
|
2294
|
+
// TODO(dmaretskyi): Refactor this.
|
|
2295
|
+
dxos_peerSource: "EchoNetworkAdapter"
|
|
2296
|
+
});
|
|
2297
|
+
var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetworkAdapter";
|
|
2298
|
+
|
|
2299
|
+
// packages/core/echo/echo-pipeline/src/automerge/heads-store.ts
|
|
2300
|
+
import { headsEncoding } from "@dxos/indexing";
|
|
2301
|
+
var HeadsStore = class {
|
|
2302
|
+
constructor({ db }) {
|
|
2303
|
+
this._db = db;
|
|
2304
|
+
}
|
|
2305
|
+
setHeads(documentId, heads, batch) {
|
|
2306
|
+
batch.put(documentId, heads, {
|
|
2307
|
+
sublevel: this._db,
|
|
2308
|
+
keyEncoding: "utf8",
|
|
2309
|
+
valueEncoding: headsEncoding
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
// TODO(dmaretskyi): Make batched.
|
|
2313
|
+
async getHeads(documentIds) {
|
|
2314
|
+
return this._db.getMany(documentIds, {
|
|
2315
|
+
keyEncoding: "utf8",
|
|
2316
|
+
valueEncoding: headsEncoding
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
|
|
2321
|
+
// packages/core/echo/echo-pipeline/src/automerge/leveldb-storage-adapter.ts
|
|
2322
|
+
import { LifecycleState as LifecycleState3, Resource as Resource4 } from "@dxos/context";
|
|
2323
|
+
var LevelDBStorageAdapter = class extends Resource4 {
|
|
2324
|
+
constructor(_params) {
|
|
2325
|
+
super();
|
|
2326
|
+
this._params = _params;
|
|
2327
|
+
}
|
|
2328
|
+
async load(keyArray) {
|
|
2329
|
+
try {
|
|
2330
|
+
if (this._lifecycleState !== LifecycleState3.OPEN) {
|
|
2331
|
+
return void 0;
|
|
2332
|
+
}
|
|
2333
|
+
const startMs = Date.now();
|
|
2334
|
+
const chunk = await this._params.db.get(keyArray, {
|
|
2335
|
+
...encodingOptions
|
|
2047
2336
|
});
|
|
2048
|
-
this.
|
|
2337
|
+
this._params.monitor?.recordBytesLoaded(chunk.byteLength);
|
|
2338
|
+
this._params.monitor?.recordLoadDuration(Date.now() - startMs);
|
|
2339
|
+
return chunk;
|
|
2340
|
+
} catch (err) {
|
|
2341
|
+
if (isLevelDbNotFoundError(err)) {
|
|
2342
|
+
return void 0;
|
|
2343
|
+
}
|
|
2344
|
+
throw err;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
async save(keyArray, binary) {
|
|
2348
|
+
if (this._lifecycleState !== LifecycleState3.OPEN) {
|
|
2349
|
+
return void 0;
|
|
2350
|
+
}
|
|
2351
|
+
const startMs = Date.now();
|
|
2352
|
+
const batch = this._params.db.batch();
|
|
2353
|
+
await this._params.callbacks?.beforeSave?.({
|
|
2354
|
+
path: keyArray,
|
|
2355
|
+
batch
|
|
2049
2356
|
});
|
|
2050
|
-
|
|
2051
|
-
|
|
2357
|
+
batch.put(keyArray, Buffer.from(binary), {
|
|
2358
|
+
...encodingOptions
|
|
2359
|
+
});
|
|
2360
|
+
await batch.write();
|
|
2361
|
+
this._params.monitor?.recordBytesStored(binary.byteLength);
|
|
2362
|
+
await this._params.callbacks?.afterSave?.(keyArray);
|
|
2363
|
+
this._params.monitor?.recordStoreDuration(Date.now() - startMs);
|
|
2364
|
+
}
|
|
2365
|
+
async remove(keyArray) {
|
|
2366
|
+
if (this._lifecycleState !== LifecycleState3.OPEN) {
|
|
2367
|
+
return void 0;
|
|
2368
|
+
}
|
|
2369
|
+
await this._params.db.del(keyArray, {
|
|
2370
|
+
...encodingOptions
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2373
|
+
async loadRange(keyPrefix) {
|
|
2374
|
+
if (this._lifecycleState !== LifecycleState3.OPEN) {
|
|
2375
|
+
return [];
|
|
2376
|
+
}
|
|
2377
|
+
const startMs = Date.now();
|
|
2378
|
+
const result = [];
|
|
2379
|
+
for await (const [key, value] of this._params.db.iterator({
|
|
2380
|
+
gte: keyPrefix,
|
|
2381
|
+
lte: [
|
|
2382
|
+
...keyPrefix,
|
|
2383
|
+
"\uFFFF"
|
|
2384
|
+
],
|
|
2385
|
+
...encodingOptions
|
|
2386
|
+
})) {
|
|
2387
|
+
result.push({
|
|
2388
|
+
key,
|
|
2389
|
+
data: value
|
|
2390
|
+
});
|
|
2391
|
+
this._params.monitor?.recordBytesLoaded(value.byteLength);
|
|
2392
|
+
}
|
|
2393
|
+
this._params.monitor?.recordLoadDuration(Date.now() - startMs);
|
|
2394
|
+
return result;
|
|
2395
|
+
}
|
|
2396
|
+
async removeRange(keyPrefix) {
|
|
2397
|
+
if (this._lifecycleState !== LifecycleState3.OPEN) {
|
|
2398
|
+
return void 0;
|
|
2399
|
+
}
|
|
2400
|
+
const batch = this._params.db.batch();
|
|
2401
|
+
for await (const [key] of this._params.db.iterator({
|
|
2402
|
+
gte: keyPrefix,
|
|
2403
|
+
lte: [
|
|
2404
|
+
...keyPrefix,
|
|
2405
|
+
"\uFFFF"
|
|
2406
|
+
],
|
|
2407
|
+
...encodingOptions
|
|
2408
|
+
})) {
|
|
2409
|
+
batch.del(key, {
|
|
2410
|
+
...encodingOptions
|
|
2411
|
+
});
|
|
2052
2412
|
}
|
|
2413
|
+
await batch.write();
|
|
2053
2414
|
}
|
|
2054
2415
|
};
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
synchronized2
|
|
2066
|
-
], Pipeline.prototype, "pause", null);
|
|
2067
|
-
_ts_decorate4([
|
|
2068
|
-
synchronized2
|
|
2069
|
-
], Pipeline.prototype, "unpause", null);
|
|
2070
|
-
|
|
2071
|
-
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
2072
|
-
import { Event as Event5, synchronized as synchronized3, trackLeaks as trackLeaks2 } from "@dxos/async";
|
|
2073
|
-
import { LifecycleState as LifecycleState3, Resource as Resource5 } from "@dxos/context";
|
|
2074
|
-
import { subtleCrypto as subtleCrypto2 } from "@dxos/crypto";
|
|
2075
|
-
import { invariant as invariant9 } from "@dxos/invariant";
|
|
2076
|
-
import { PublicKey as PublicKey5, SpaceId as SpaceId2 } from "@dxos/keys";
|
|
2077
|
-
import { log as log9, logInfo } from "@dxos/log";
|
|
2078
|
-
import { AdmittedFeed as AdmittedFeed2 } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
2079
|
-
import { trace as trace3 } from "@dxos/tracing";
|
|
2080
|
-
import { Callback as Callback2, ComplexMap as ComplexMap2 } from "@dxos/util";
|
|
2416
|
+
var keyEncoder = {
|
|
2417
|
+
encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
|
|
2418
|
+
decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%")),
|
|
2419
|
+
format: "buffer"
|
|
2420
|
+
};
|
|
2421
|
+
var encodingOptions = {
|
|
2422
|
+
keyEncoding: keyEncoder,
|
|
2423
|
+
valueEncoding: "buffer"
|
|
2424
|
+
};
|
|
2425
|
+
var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
|
|
2081
2426
|
|
|
2082
|
-
// packages/core/echo/echo-pipeline/src/
|
|
2083
|
-
|
|
2084
|
-
import { Context as Context4 } from "@dxos/context";
|
|
2085
|
-
import { SpaceStateMachine } from "@dxos/credentials";
|
|
2086
|
-
import { PublicKey as PublicKey4 } from "@dxos/keys";
|
|
2087
|
-
import { log as log8 } from "@dxos/log";
|
|
2088
|
-
import { AdmittedFeed } from "@dxos/protocols/proto/dxos/halo/credentials";
|
|
2089
|
-
import { Timeframe as Timeframe3 } from "@dxos/timeframe";
|
|
2090
|
-
import { TimeSeriesCounter, TimeUsageCounter, trace as trace2 } from "@dxos/tracing";
|
|
2091
|
-
import { Callback, tracer } from "@dxos/util";
|
|
2092
|
-
function _ts_decorate5(decorators, target, key, desc) {
|
|
2427
|
+
// packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
|
|
2428
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
2093
2429
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2094
2430
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
2095
2431
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2099,787 +2435,454 @@ function _ts_decorate5(decorators, target, key, desc) {
|
|
|
2099
2435
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2100
2436
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2101
2437
|
}
|
|
2102
|
-
var
|
|
2103
|
-
var
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
L: 47
|
|
2438
|
+
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
|
|
2439
|
+
var AutomergeHost = class extends Resource5 {
|
|
2440
|
+
constructor({ db, indexMetadataStore, dataMonitor }) {
|
|
2441
|
+
super();
|
|
2442
|
+
this._collectionSynchronizer = new CollectionSynchronizer({
|
|
2443
|
+
queryCollectionState: this._queryCollectionState.bind(this),
|
|
2444
|
+
sendCollectionState: this._sendCollectionState.bind(this),
|
|
2445
|
+
shouldSyncCollection: this._shouldSyncCollection.bind(this)
|
|
2111
2446
|
});
|
|
2112
|
-
this.
|
|
2113
|
-
this.
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2447
|
+
this._db = db;
|
|
2448
|
+
this._storage = new LevelDBStorageAdapter({
|
|
2449
|
+
db: db.sublevel("automerge"),
|
|
2450
|
+
callbacks: {
|
|
2451
|
+
beforeSave: async (params) => this._beforeSave(params),
|
|
2452
|
+
afterSave: async (key) => this._afterSave(key)
|
|
2453
|
+
},
|
|
2454
|
+
monitor: dataMonitor
|
|
2119
2455
|
});
|
|
2120
|
-
this.
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
log8("feed admitted", {
|
|
2127
|
-
key: info.key
|
|
2128
|
-
}, {
|
|
2129
|
-
F: __dxlog_file10,
|
|
2130
|
-
L: 82,
|
|
2131
|
-
S: this,
|
|
2132
|
-
C: (f, a) => f(...a)
|
|
2133
|
-
});
|
|
2134
|
-
if (info.assertion.designation === AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
|
|
2135
|
-
queueMicrotask(async () => {
|
|
2136
|
-
try {
|
|
2137
|
-
const feed = await feedProvider(info.key);
|
|
2138
|
-
if (!this._pipeline.hasFeed(feed.key)) {
|
|
2139
|
-
await this._pipeline.addFeed(feed);
|
|
2140
|
-
}
|
|
2141
|
-
} catch (err) {
|
|
2142
|
-
log8.catch(err, void 0, {
|
|
2143
|
-
F: __dxlog_file10,
|
|
2144
|
-
L: 93,
|
|
2145
|
-
S: this,
|
|
2146
|
-
C: (f, a) => f(...a)
|
|
2147
|
-
});
|
|
2148
|
-
}
|
|
2149
|
-
});
|
|
2150
|
-
}
|
|
2151
|
-
await this.onFeedAdmitted.callIfSet(info);
|
|
2456
|
+
this._echoNetworkAdapter = new EchoNetworkAdapter({
|
|
2457
|
+
getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
|
|
2458
|
+
isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
|
|
2459
|
+
onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
|
|
2460
|
+
onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
|
|
2461
|
+
monitor: dataMonitor
|
|
2152
2462
|
});
|
|
2153
|
-
this.
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
this.
|
|
2463
|
+
this._headsStore = new HeadsStore({
|
|
2464
|
+
db: db.sublevel("heads")
|
|
2465
|
+
});
|
|
2466
|
+
this._indexMetadataStore = indexMetadataStore;
|
|
2157
2467
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2468
|
+
async _open() {
|
|
2469
|
+
this._peerId = `host-${PublicKey6.random().toHex()}`;
|
|
2470
|
+
await this._storage.open?.();
|
|
2471
|
+
this._repo = new Repo({
|
|
2472
|
+
peerId: this._peerId,
|
|
2473
|
+
sharePolicy: this._sharePolicy.bind(this),
|
|
2474
|
+
storage: this._storage,
|
|
2475
|
+
network: [
|
|
2476
|
+
// Upstream swarm.
|
|
2477
|
+
this._echoNetworkAdapter
|
|
2478
|
+
]
|
|
2479
|
+
});
|
|
2480
|
+
Event5.wrap(this._echoNetworkAdapter, "peer-candidate").on(this._ctx, (e) => this._onPeerConnected(e.peerId));
|
|
2481
|
+
Event5.wrap(this._echoNetworkAdapter, "peer-disconnected").on(this._ctx, (e) => this._onPeerDisconnected(e.peerId));
|
|
2482
|
+
this._collectionSynchronizer.remoteStateUpdated.on(this._ctx, ({ collectionId, peerId }) => {
|
|
2483
|
+
this._onRemoteCollectionStateUpdated(collectionId, peerId);
|
|
2484
|
+
});
|
|
2485
|
+
await this._echoNetworkAdapter.open();
|
|
2486
|
+
await this._collectionSynchronizer.open();
|
|
2487
|
+
await this._echoNetworkAdapter.open();
|
|
2488
|
+
await this._echoNetworkAdapter.whenConnected();
|
|
2160
2489
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2490
|
+
async _close() {
|
|
2491
|
+
await this._collectionSynchronizer.close();
|
|
2492
|
+
await this._storage.close?.();
|
|
2493
|
+
await this._echoNetworkAdapter.close();
|
|
2494
|
+
await this._ctx.dispose();
|
|
2163
2495
|
}
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2496
|
+
/**
|
|
2497
|
+
* @deprecated To be abstracted away.
|
|
2498
|
+
*/
|
|
2499
|
+
get repo() {
|
|
2500
|
+
return this._repo;
|
|
2167
2501
|
}
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2502
|
+
get peerId() {
|
|
2503
|
+
return this._peerId;
|
|
2504
|
+
}
|
|
2505
|
+
get loadedDocsCount() {
|
|
2506
|
+
return Object.keys(this._repo.handles).length;
|
|
2507
|
+
}
|
|
2508
|
+
async addReplicator(replicator) {
|
|
2509
|
+
await this._echoNetworkAdapter.addReplicator(replicator);
|
|
2510
|
+
}
|
|
2511
|
+
async removeReplicator(replicator) {
|
|
2512
|
+
await this._echoNetworkAdapter.removeReplicator(replicator);
|
|
2513
|
+
}
|
|
2514
|
+
/**
|
|
2515
|
+
* Loads the document handle from the repo and waits for it to be ready.
|
|
2516
|
+
*/
|
|
2517
|
+
async loadDoc(ctx, documentId, opts) {
|
|
2518
|
+
let handle;
|
|
2519
|
+
if (typeof documentId === "string") {
|
|
2520
|
+
handle = this._repo.handles[documentId];
|
|
2182
2521
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2522
|
+
if (!handle) {
|
|
2523
|
+
handle = this._repo.find(documentId);
|
|
2524
|
+
}
|
|
2525
|
+
if (!handle.isReady()) {
|
|
2526
|
+
if (!opts?.timeout) {
|
|
2527
|
+
await cancelWithContext2(ctx, handle.whenReady());
|
|
2528
|
+
} else {
|
|
2529
|
+
await cancelWithContext2(ctx, asyncTimeout(handle.whenReady(), opts.timeout));
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
return handle;
|
|
2533
|
+
}
|
|
2534
|
+
/**
|
|
2535
|
+
* Create new persisted document.
|
|
2536
|
+
*/
|
|
2537
|
+
createDoc(initialValue, opts) {
|
|
2538
|
+
if (opts?.preserveHistory) {
|
|
2539
|
+
if (!isAutomerge(initialValue)) {
|
|
2540
|
+
throw new TypeError("Initial value must be an Automerge document");
|
|
2541
|
+
}
|
|
2542
|
+
return this._repo.import(save(initialValue));
|
|
2543
|
+
} else {
|
|
2544
|
+
return this._repo.create(initialValue);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
async waitUntilHeadsReplicated(heads) {
|
|
2548
|
+
const entries = heads.entries;
|
|
2549
|
+
if (!entries?.length) {
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
const documentIds = entries.map((entry) => entry.documentId);
|
|
2553
|
+
const documentHeads = await this.getHeads(documentIds);
|
|
2554
|
+
const headsToWait = entries.filter((entry, index) => {
|
|
2555
|
+
const targetHeads = entry.heads;
|
|
2556
|
+
if (!targetHeads || targetHeads.length === 0) {
|
|
2557
|
+
return false;
|
|
2558
|
+
}
|
|
2559
|
+
const currentHeads = documentHeads[index];
|
|
2560
|
+
return !(currentHeads !== null && headsEquals(currentHeads, targetHeads));
|
|
2188
2561
|
});
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2562
|
+
if (headsToWait.length > 0) {
|
|
2563
|
+
await Promise.all(headsToWait.map(async (entry, index) => {
|
|
2564
|
+
const handle = await this.loadDoc(Context5.default(void 0, {
|
|
2565
|
+
F: __dxlog_file12,
|
|
2566
|
+
L: 227
|
|
2567
|
+
}), entry.documentId);
|
|
2568
|
+
await waitForHeads(handle, entry.heads);
|
|
2193
2569
|
}));
|
|
2194
|
-
}
|
|
2195
|
-
await this.
|
|
2196
|
-
log8("started", void 0, {
|
|
2197
|
-
F: __dxlog_file10,
|
|
2198
|
-
L: 134,
|
|
2199
|
-
S: this,
|
|
2200
|
-
C: (f, a) => f(...a)
|
|
2201
|
-
});
|
|
2570
|
+
}
|
|
2571
|
+
await this._repo.flush(documentIds.filter((documentId) => !!this._repo.handles[documentId]));
|
|
2202
2572
|
}
|
|
2203
|
-
async
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2573
|
+
async reIndexHeads(documentIds) {
|
|
2574
|
+
for (const documentId of documentIds) {
|
|
2575
|
+
log10.info("re-indexing heads for document", {
|
|
2576
|
+
documentId
|
|
2577
|
+
}, {
|
|
2578
|
+
F: __dxlog_file12,
|
|
2579
|
+
L: 239,
|
|
2580
|
+
S: this,
|
|
2581
|
+
C: (f, a) => f(...a)
|
|
2209
2582
|
});
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2583
|
+
const handle = this._repo.find(documentId);
|
|
2584
|
+
await handle.whenReady([
|
|
2585
|
+
"ready",
|
|
2586
|
+
"requesting"
|
|
2587
|
+
]);
|
|
2588
|
+
if (handle.inState([
|
|
2589
|
+
"requesting"
|
|
2590
|
+
])) {
|
|
2591
|
+
log10.warn("document is not available locally, skipping", {
|
|
2592
|
+
documentId
|
|
2213
2593
|
}, {
|
|
2214
|
-
F:
|
|
2215
|
-
L:
|
|
2594
|
+
F: __dxlog_file12,
|
|
2595
|
+
L: 243,
|
|
2216
2596
|
S: this,
|
|
2217
2597
|
C: (f, a) => f(...a)
|
|
2218
2598
|
});
|
|
2599
|
+
continue;
|
|
2219
2600
|
}
|
|
2601
|
+
const doc = handle.docSync();
|
|
2602
|
+
invariant8(doc, void 0, {
|
|
2603
|
+
F: __dxlog_file12,
|
|
2604
|
+
L: 248,
|
|
2605
|
+
S: this,
|
|
2606
|
+
A: [
|
|
2607
|
+
"doc",
|
|
2608
|
+
""
|
|
2609
|
+
]
|
|
2610
|
+
});
|
|
2611
|
+
const heads = getHeads(doc);
|
|
2612
|
+
const batch = this._db.batch();
|
|
2613
|
+
this._headsStore.setHeads(documentId, heads, batch);
|
|
2614
|
+
await batch.write();
|
|
2220
2615
|
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
const snapshot = {
|
|
2225
|
-
timeframe: this._pipeline.state.timeframe,
|
|
2226
|
-
messages: this._spaceStateMachine.credentialEntries.map((entry) => ({
|
|
2227
|
-
feedKey: entry.sourceFeed,
|
|
2228
|
-
credential: entry.credential
|
|
2229
|
-
}))
|
|
2230
|
-
};
|
|
2231
|
-
await this._pipeline.unpause();
|
|
2232
|
-
log8("save snapshot", {
|
|
2233
|
-
key: this._spaceKey,
|
|
2234
|
-
snapshot
|
|
2235
|
-
}, {
|
|
2236
|
-
F: __dxlog_file10,
|
|
2237
|
-
L: 163,
|
|
2616
|
+
log10.info("done re-indexing heads", void 0, {
|
|
2617
|
+
F: __dxlog_file12,
|
|
2618
|
+
L: 255,
|
|
2238
2619
|
S: this,
|
|
2239
2620
|
C: (f, a) => f(...a)
|
|
2240
2621
|
});
|
|
2241
|
-
await this._metadata.setSpaceControlPipelineSnapshot(this._spaceKey, snapshot);
|
|
2242
2622
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
S: this,
|
|
2254
|
-
C: (f, a) => f(...a)
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
span.end();
|
|
2623
|
+
// TODO(dmaretskyi): Share based on HALO permissions and space affinity.
|
|
2624
|
+
// Hosts, running in the worker, don't share documents unless requested by other peers.
|
|
2625
|
+
// NOTE: If both peers return sharePolicy=false the replication will not happen
|
|
2626
|
+
// https://github.com/automerge/automerge-repo/pull/292
|
|
2627
|
+
async _sharePolicy(peerId, documentId) {
|
|
2628
|
+
if (peerId.startsWith("client-")) {
|
|
2629
|
+
return false;
|
|
2630
|
+
}
|
|
2631
|
+
if (!documentId) {
|
|
2632
|
+
return false;
|
|
2258
2633
|
}
|
|
2634
|
+
const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
|
|
2635
|
+
if (isEchoPeerMetadata(peerMetadata)) {
|
|
2636
|
+
return this._echoNetworkAdapter.shouldAdvertise(peerId, {
|
|
2637
|
+
documentId
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
return false;
|
|
2259
2641
|
}
|
|
2260
|
-
async
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
}, {
|
|
2265
|
-
F: __dxlog_file10,
|
|
2266
|
-
L: 186,
|
|
2267
|
-
S: this,
|
|
2268
|
-
C: (f, a) => f(...a)
|
|
2269
|
-
});
|
|
2270
|
-
if (msg.data.payload.credential) {
|
|
2271
|
-
const timer = tracer.mark("dxos.echo.pipeline.control");
|
|
2272
|
-
const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, {
|
|
2273
|
-
sourceFeed: PublicKey4.from(msg.feedKey)
|
|
2274
|
-
});
|
|
2275
|
-
timer.end();
|
|
2276
|
-
if (!result) {
|
|
2277
|
-
log8.warn("processing failed", {
|
|
2278
|
-
msg
|
|
2279
|
-
}, {
|
|
2280
|
-
F: __dxlog_file10,
|
|
2281
|
-
L: 195,
|
|
2282
|
-
S: this,
|
|
2283
|
-
C: (f, a) => f(...a)
|
|
2284
|
-
});
|
|
2285
|
-
} else {
|
|
2286
|
-
await this._noteTargetStateIfNeeded(this._pipeline.state.pendingTimeframe);
|
|
2287
|
-
}
|
|
2288
|
-
this._snapshotTask.schedule();
|
|
2642
|
+
async _beforeSave({ path, batch }) {
|
|
2643
|
+
const handle = this._repo.handles[path[0]];
|
|
2644
|
+
if (!handle) {
|
|
2645
|
+
return;
|
|
2289
2646
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
this._lastTimeframeSaveTime = Date.now();
|
|
2294
|
-
await this._saveTargetTimeframe(timeframe);
|
|
2647
|
+
const doc = handle.docSync();
|
|
2648
|
+
if (!doc) {
|
|
2649
|
+
return;
|
|
2295
2650
|
}
|
|
2651
|
+
const heads = getHeads(doc);
|
|
2652
|
+
this._headsStore.setHeads(handle.documentId, heads, batch);
|
|
2653
|
+
const spaceKey = getSpaceKeyFromDoc(doc) ?? void 0;
|
|
2654
|
+
const objectIds = Object.keys(doc.objects ?? {});
|
|
2655
|
+
const encodedIds = objectIds.map((objectId) => objectPointerCodec.encode({
|
|
2656
|
+
documentId: handle.documentId,
|
|
2657
|
+
objectId,
|
|
2658
|
+
spaceKey
|
|
2659
|
+
}));
|
|
2660
|
+
const idToLastHash = new Map(encodedIds.map((id) => [
|
|
2661
|
+
id,
|
|
2662
|
+
heads
|
|
2663
|
+
]));
|
|
2664
|
+
this._indexMetadataStore.markDirty(idToLastHash, batch);
|
|
2296
2665
|
}
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
C: (f, a) => f(...a)
|
|
2303
|
-
});
|
|
2304
|
-
await this._ctx.dispose();
|
|
2305
|
-
await this._pipeline.stop();
|
|
2306
|
-
await this._saveTargetTimeframe(this._pipeline.state.timeframe);
|
|
2307
|
-
log8("stopped", void 0, {
|
|
2308
|
-
F: __dxlog_file10,
|
|
2309
|
-
L: 219,
|
|
2310
|
-
S: this,
|
|
2311
|
-
C: (f, a) => f(...a)
|
|
2312
|
-
});
|
|
2313
|
-
}
|
|
2314
|
-
async _saveTargetTimeframe(timeframe) {
|
|
2315
|
-
try {
|
|
2316
|
-
const newTimeframe = Timeframe3.merge(this._targetTimeframe ?? new Timeframe3(), timeframe);
|
|
2317
|
-
await this._metadata.setSpaceControlLatestTimeframe(this._spaceKey, newTimeframe);
|
|
2318
|
-
this._targetTimeframe = newTimeframe;
|
|
2319
|
-
} catch (err) {
|
|
2320
|
-
log8(err, void 0, {
|
|
2321
|
-
F: __dxlog_file10,
|
|
2322
|
-
L: 228,
|
|
2323
|
-
S: this,
|
|
2324
|
-
C: (f, a) => f(...a)
|
|
2666
|
+
_shouldSyncCollection(collectionId, peerId) {
|
|
2667
|
+
const peerMetadata = this._repo.peerMetadataByPeerId[peerId];
|
|
2668
|
+
if (isEchoPeerMetadata(peerMetadata)) {
|
|
2669
|
+
return this._echoNetworkAdapter.shouldSyncCollection(peerId, {
|
|
2670
|
+
collectionId
|
|
2325
2671
|
});
|
|
2326
2672
|
}
|
|
2327
|
-
|
|
2328
|
-
};
|
|
2329
|
-
_ts_decorate5([
|
|
2330
|
-
trace2.metricsCounter()
|
|
2331
|
-
], ControlPipeline.prototype, "_usage", void 0);
|
|
2332
|
-
_ts_decorate5([
|
|
2333
|
-
trace2.metricsCounter()
|
|
2334
|
-
], ControlPipeline.prototype, "_mutations", void 0);
|
|
2335
|
-
_ts_decorate5([
|
|
2336
|
-
trace2.span({
|
|
2337
|
-
showInBrowserTimeline: true
|
|
2338
|
-
})
|
|
2339
|
-
], ControlPipeline.prototype, "start", null);
|
|
2340
|
-
_ts_decorate5([
|
|
2341
|
-
trace2.span()
|
|
2342
|
-
], ControlPipeline.prototype, "_consumePipeline", null);
|
|
2343
|
-
_ts_decorate5([
|
|
2344
|
-
trace2.span()
|
|
2345
|
-
], ControlPipeline.prototype, "_processMessage", null);
|
|
2346
|
-
ControlPipeline = _ts_decorate5([
|
|
2347
|
-
trace2.resource(),
|
|
2348
|
-
trackLeaks("start", "stop")
|
|
2349
|
-
], ControlPipeline);
|
|
2350
|
-
|
|
2351
|
-
// packages/core/echo/echo-pipeline/src/space/space.ts
|
|
2352
|
-
function _ts_decorate6(decorators, target, key, desc) {
|
|
2353
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2354
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
2355
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2356
|
-
else
|
|
2357
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
2358
|
-
if (d = decorators[i])
|
|
2359
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2360
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2361
|
-
}
|
|
2362
|
-
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space.ts";
|
|
2363
|
-
var Space = class extends Resource5 {
|
|
2364
|
-
constructor(params) {
|
|
2365
|
-
super();
|
|
2366
|
-
this.onCredentialProcessed = new Callback2();
|
|
2367
|
-
this.stateUpdate = new Event5();
|
|
2368
|
-
invariant9(params.spaceKey && params.feedProvider, void 0, {
|
|
2369
|
-
F: __dxlog_file11,
|
|
2370
|
-
L: 76,
|
|
2371
|
-
S: this,
|
|
2372
|
-
A: [
|
|
2373
|
-
"params.spaceKey && params.feedProvider",
|
|
2374
|
-
""
|
|
2375
|
-
]
|
|
2376
|
-
});
|
|
2377
|
-
this._id = params.id;
|
|
2378
|
-
this._key = params.spaceKey;
|
|
2379
|
-
this._genesisFeedKey = params.genesisFeed.key;
|
|
2380
|
-
this._feedProvider = params.feedProvider;
|
|
2381
|
-
this._snapshotManager = params.snapshotManager;
|
|
2382
|
-
this._controlPipeline = new ControlPipeline({
|
|
2383
|
-
spaceKey: params.spaceKey,
|
|
2384
|
-
genesisFeed: params.genesisFeed,
|
|
2385
|
-
feedProvider: params.feedProvider,
|
|
2386
|
-
metadataStore: params.metadataStore
|
|
2387
|
-
});
|
|
2388
|
-
this._controlPipeline.onFeedAdmitted.set(async (info) => {
|
|
2389
|
-
const sparse = info.assertion.designation === AdmittedFeed2.Designation.DATA;
|
|
2390
|
-
if (!info.key.equals(params.genesisFeed.key)) {
|
|
2391
|
-
queueMicrotask(async () => {
|
|
2392
|
-
this.protocol.addFeed(await params.feedProvider(info.key, {
|
|
2393
|
-
sparse
|
|
2394
|
-
}));
|
|
2395
|
-
});
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
this._controlPipeline.onCredentialProcessed.set(async (credential) => {
|
|
2399
|
-
await this.onCredentialProcessed.callIfSet(credential);
|
|
2400
|
-
log9("onCredentialProcessed", {
|
|
2401
|
-
credential
|
|
2402
|
-
}, {
|
|
2403
|
-
F: __dxlog_file11,
|
|
2404
|
-
L: 104,
|
|
2405
|
-
S: this,
|
|
2406
|
-
C: (f, a) => f(...a)
|
|
2407
|
-
});
|
|
2408
|
-
this.stateUpdate.emit();
|
|
2409
|
-
});
|
|
2410
|
-
this._controlPipeline.onDelegatedInvitation.set(async (invitation) => {
|
|
2411
|
-
log9("onDelegatedInvitation", {
|
|
2412
|
-
invitation
|
|
2413
|
-
}, {
|
|
2414
|
-
F: __dxlog_file11,
|
|
2415
|
-
L: 108,
|
|
2416
|
-
S: this,
|
|
2417
|
-
C: (f, a) => f(...a)
|
|
2418
|
-
});
|
|
2419
|
-
await params.onDelegatedInvitationStatusChange(invitation, true);
|
|
2420
|
-
});
|
|
2421
|
-
this._controlPipeline.onDelegatedInvitationRemoved.set(async (invitation) => {
|
|
2422
|
-
log9("onDelegatedInvitationRemoved", {
|
|
2423
|
-
invitation
|
|
2424
|
-
}, {
|
|
2425
|
-
F: __dxlog_file11,
|
|
2426
|
-
L: 112,
|
|
2427
|
-
S: this,
|
|
2428
|
-
C: (f, a) => f(...a)
|
|
2429
|
-
});
|
|
2430
|
-
await params.onDelegatedInvitationStatusChange(invitation, false);
|
|
2431
|
-
});
|
|
2432
|
-
this._controlPipeline.onMemberRoleChanged.set(async (changedMembers) => {
|
|
2433
|
-
log9("onMemberRoleChanged", () => ({
|
|
2434
|
-
changedMembers: changedMembers.map((m) => [
|
|
2435
|
-
m.key,
|
|
2436
|
-
m.role
|
|
2437
|
-
])
|
|
2438
|
-
}), {
|
|
2439
|
-
F: __dxlog_file11,
|
|
2440
|
-
L: 116,
|
|
2441
|
-
S: this,
|
|
2442
|
-
C: (f, a) => f(...a)
|
|
2443
|
-
});
|
|
2444
|
-
await params.onMemberRolesChanged(changedMembers);
|
|
2445
|
-
});
|
|
2446
|
-
this.protocol = params.protocol;
|
|
2447
|
-
this.protocol.addFeed(params.genesisFeed);
|
|
2448
|
-
}
|
|
2449
|
-
get id() {
|
|
2450
|
-
return this._id;
|
|
2451
|
-
}
|
|
2452
|
-
get key() {
|
|
2453
|
-
return this._key;
|
|
2454
|
-
}
|
|
2455
|
-
get isOpen() {
|
|
2456
|
-
return this._lifecycleState === LifecycleState3.OPEN;
|
|
2457
|
-
}
|
|
2458
|
-
get genesisFeedKey() {
|
|
2459
|
-
return this._genesisFeedKey;
|
|
2460
|
-
}
|
|
2461
|
-
get controlFeedKey() {
|
|
2462
|
-
return this._controlFeed?.key;
|
|
2463
|
-
}
|
|
2464
|
-
get dataFeedKey() {
|
|
2465
|
-
return this._dataFeed?.key;
|
|
2466
|
-
}
|
|
2467
|
-
get spaceState() {
|
|
2468
|
-
return this._controlPipeline.spaceState;
|
|
2673
|
+
return false;
|
|
2469
2674
|
}
|
|
2470
2675
|
/**
|
|
2471
|
-
*
|
|
2676
|
+
* Called by AutomergeStorageAdapter after levelDB batch commit.
|
|
2472
2677
|
*/
|
|
2473
|
-
|
|
2474
|
-
|
|
2678
|
+
async _afterSave(path) {
|
|
2679
|
+
this._indexMetadataStore.notifyMarkedDirty();
|
|
2680
|
+
const documentId = path[0];
|
|
2681
|
+
const document = this._repo.handles[documentId]?.docSync();
|
|
2682
|
+
if (document) {
|
|
2683
|
+
const heads = getHeads(document);
|
|
2684
|
+
this._onHeadsChanged(documentId, heads);
|
|
2685
|
+
}
|
|
2475
2686
|
}
|
|
2476
|
-
|
|
2477
|
-
return this.
|
|
2687
|
+
_automergePeers() {
|
|
2688
|
+
return this._repo.peers;
|
|
2478
2689
|
}
|
|
2479
|
-
async
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
});
|
|
2489
|
-
this._controlFeed = feed;
|
|
2490
|
-
await this._controlPipeline.setWriteFeed(feed);
|
|
2491
|
-
return this;
|
|
2690
|
+
async _isDocumentInRemoteCollection(params) {
|
|
2691
|
+
for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
|
|
2692
|
+
const remoteCollections = this._collectionSynchronizer.getRemoteCollectionStates(collectionId);
|
|
2693
|
+
const remotePeerDocs = remoteCollections.get(params.peerId)?.documents;
|
|
2694
|
+
if (remotePeerDocs && params.documentId in remotePeerDocs) {
|
|
2695
|
+
return true;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
return false;
|
|
2492
2699
|
}
|
|
2493
|
-
async
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
this._dataFeed = feed;
|
|
2504
|
-
return this;
|
|
2700
|
+
async _getContainingSpaceForDocument(documentId) {
|
|
2701
|
+
const doc = this._repo.handles[documentId]?.docSync();
|
|
2702
|
+
if (!doc) {
|
|
2703
|
+
return null;
|
|
2704
|
+
}
|
|
2705
|
+
const spaceKeyHex = getSpaceKeyFromDoc(doc);
|
|
2706
|
+
if (!spaceKeyHex) {
|
|
2707
|
+
return null;
|
|
2708
|
+
}
|
|
2709
|
+
return PublicKey6.from(spaceKeyHex);
|
|
2505
2710
|
}
|
|
2506
2711
|
/**
|
|
2507
|
-
*
|
|
2712
|
+
* Flush documents to disk.
|
|
2508
2713
|
*/
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
}
|
|
2512
|
-
async _open(ctx) {
|
|
2513
|
-
log9("opening...", void 0, {
|
|
2514
|
-
F: __dxlog_file11,
|
|
2515
|
-
L: 190,
|
|
2516
|
-
S: this,
|
|
2517
|
-
C: (f, a) => f(...a)
|
|
2518
|
-
});
|
|
2519
|
-
await this._controlPipeline.start();
|
|
2520
|
-
await this.protocol.start();
|
|
2521
|
-
log9("opened", void 0, {
|
|
2522
|
-
F: __dxlog_file11,
|
|
2523
|
-
L: 196,
|
|
2524
|
-
S: this,
|
|
2525
|
-
C: (f, a) => f(...a)
|
|
2526
|
-
});
|
|
2527
|
-
}
|
|
2528
|
-
async _close() {
|
|
2529
|
-
log9("closing...", {
|
|
2530
|
-
key: this._key
|
|
2531
|
-
}, {
|
|
2532
|
-
F: __dxlog_file11,
|
|
2533
|
-
L: 201,
|
|
2534
|
-
S: this,
|
|
2535
|
-
C: (f, a) => f(...a)
|
|
2536
|
-
});
|
|
2537
|
-
await this.protocol.stop();
|
|
2538
|
-
await this._controlPipeline.stop();
|
|
2539
|
-
log9("closed", void 0, {
|
|
2540
|
-
F: __dxlog_file11,
|
|
2541
|
-
L: 207,
|
|
2542
|
-
S: this,
|
|
2543
|
-
C: (f, a) => f(...a)
|
|
2544
|
-
});
|
|
2545
|
-
}
|
|
2546
|
-
};
|
|
2547
|
-
_ts_decorate6([
|
|
2548
|
-
trace3.info()
|
|
2549
|
-
], Space.prototype, "protocol", void 0);
|
|
2550
|
-
_ts_decorate6([
|
|
2551
|
-
trace3.info()
|
|
2552
|
-
], Space.prototype, "_controlPipeline", void 0);
|
|
2553
|
-
_ts_decorate6([
|
|
2554
|
-
logInfo,
|
|
2555
|
-
trace3.info()
|
|
2556
|
-
], Space.prototype, "id", null);
|
|
2557
|
-
_ts_decorate6([
|
|
2558
|
-
logInfo,
|
|
2559
|
-
trace3.info()
|
|
2560
|
-
], Space.prototype, "key", null);
|
|
2561
|
-
_ts_decorate6([
|
|
2562
|
-
trace3.span()
|
|
2563
|
-
], Space.prototype, "_open", null);
|
|
2564
|
-
_ts_decorate6([
|
|
2565
|
-
synchronized3
|
|
2566
|
-
], Space.prototype, "_close", null);
|
|
2567
|
-
Space = _ts_decorate6([
|
|
2568
|
-
trackLeaks2("open", "close"),
|
|
2569
|
-
trace3.resource()
|
|
2570
|
-
], Space);
|
|
2571
|
-
var SPACE_IDS_CACHE = new ComplexMap2(PublicKey5.hash);
|
|
2572
|
-
var createIdFromSpaceKey = async (spaceKey) => {
|
|
2573
|
-
const cachedValue = SPACE_IDS_CACHE.get(spaceKey);
|
|
2574
|
-
if (cachedValue !== void 0) {
|
|
2575
|
-
return cachedValue;
|
|
2714
|
+
async flush({ documentIds } = {}) {
|
|
2715
|
+
await this._repo.flush(documentIds);
|
|
2576
2716
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/admission-discovery-extension.ts";
|
|
2590
|
-
var CredentialRetrieverExtension = class extends RpcExtension2 {
|
|
2591
|
-
constructor(_request, _onResult) {
|
|
2592
|
-
super({
|
|
2593
|
-
requested: {
|
|
2594
|
-
AdmissionDiscoveryService: schema5.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
|
|
2717
|
+
async getHeads(documentIds) {
|
|
2718
|
+
const result = [];
|
|
2719
|
+
const storeRequestIds = [];
|
|
2720
|
+
const storeResultIndices = [];
|
|
2721
|
+
for (const documentId of documentIds) {
|
|
2722
|
+
const doc = this._repo.handles[documentId]?.docSync();
|
|
2723
|
+
if (doc) {
|
|
2724
|
+
result.push(getHeads(doc));
|
|
2725
|
+
} else {
|
|
2726
|
+
storeRequestIds.push(documentId);
|
|
2727
|
+
storeResultIndices.push(result.length);
|
|
2728
|
+
result.push(void 0);
|
|
2595
2729
|
}
|
|
2596
|
-
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
L: 25
|
|
2602
|
-
});
|
|
2603
|
-
}
|
|
2604
|
-
async getHandlers() {
|
|
2605
|
-
return {};
|
|
2606
|
-
}
|
|
2607
|
-
async onOpen(context) {
|
|
2608
|
-
await super.onOpen(context);
|
|
2609
|
-
scheduleTask3(this._ctx, async () => {
|
|
2610
|
-
try {
|
|
2611
|
-
const result = await this.rpc.AdmissionDiscoveryService.getAdmissionCredential(this._request);
|
|
2612
|
-
this._onResult.wake(result.admissionCredential);
|
|
2613
|
-
} catch (err) {
|
|
2614
|
-
context.close(err);
|
|
2730
|
+
}
|
|
2731
|
+
if (storeRequestIds.length > 0) {
|
|
2732
|
+
const storedHeads = await this._headsStore.getHeads(storeRequestIds);
|
|
2733
|
+
for (let i = 0; i < storedHeads.length; i++) {
|
|
2734
|
+
result[storeResultIndices[i]] = storedHeads[i];
|
|
2615
2735
|
}
|
|
2616
|
-
}
|
|
2736
|
+
}
|
|
2737
|
+
return result;
|
|
2617
2738
|
}
|
|
2618
|
-
|
|
2619
|
-
|
|
2739
|
+
//
|
|
2740
|
+
// Collection sync.
|
|
2741
|
+
//
|
|
2742
|
+
getLocalCollectionState(collectionId) {
|
|
2743
|
+
return this._collectionSynchronizer.getLocalCollectionState(collectionId);
|
|
2620
2744
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2745
|
+
getRemoteCollectionStates(collectionId) {
|
|
2746
|
+
return this._collectionSynchronizer.getRemoteCollectionStates(collectionId);
|
|
2623
2747
|
}
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
constructor(_space) {
|
|
2627
|
-
super({
|
|
2628
|
-
exposed: {
|
|
2629
|
-
AdmissionDiscoveryService: schema5.getService("dxos.mesh.teleport.AdmissionDiscoveryService")
|
|
2630
|
-
}
|
|
2631
|
-
});
|
|
2632
|
-
this._space = _space;
|
|
2748
|
+
refreshCollection(collectionId) {
|
|
2749
|
+
this._collectionSynchronizer.refreshCollection(collectionId);
|
|
2633
2750
|
}
|
|
2634
|
-
async
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
getAdmissionCredential: async (request) => {
|
|
2638
|
-
const memberInfo = this._space.spaceState.members.get(request.memberKey);
|
|
2639
|
-
if (!memberInfo?.credential) {
|
|
2640
|
-
throw new ProtocolError("Space member not found.", request);
|
|
2641
|
-
}
|
|
2642
|
-
return {
|
|
2643
|
-
admissionCredential: memberInfo.credential
|
|
2644
|
-
};
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2751
|
+
async getCollectionSyncState(collectionId) {
|
|
2752
|
+
const result = {
|
|
2753
|
+
peers: []
|
|
2647
2754
|
};
|
|
2755
|
+
const localState = this.getLocalCollectionState(collectionId);
|
|
2756
|
+
const remoteState = this.getRemoteCollectionStates(collectionId);
|
|
2757
|
+
if (!localState) {
|
|
2758
|
+
return result;
|
|
2759
|
+
}
|
|
2760
|
+
for (const [peerId, state] of remoteState) {
|
|
2761
|
+
const diff = diffCollectionState(localState, state);
|
|
2762
|
+
result.peers.push({
|
|
2763
|
+
peerId,
|
|
2764
|
+
differentDocuments: diff.different.length
|
|
2765
|
+
});
|
|
2766
|
+
}
|
|
2767
|
+
return result;
|
|
2648
2768
|
}
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
import { ComplexMap as ComplexMap3 } from "@dxos/util";
|
|
2661
|
-
function _ts_decorate7(decorators, target, key, desc) {
|
|
2662
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2663
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
2664
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
2665
|
-
else
|
|
2666
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
2667
|
-
if (d = decorators[i])
|
|
2668
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2669
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2670
|
-
}
|
|
2671
|
-
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space-protocol.ts";
|
|
2672
|
-
var MOCK_AUTH_PROVIDER = async (nonce) => Buffer.from("mock");
|
|
2673
|
-
var MOCK_AUTH_VERIFIER = async (nonce, credential) => true;
|
|
2674
|
-
var SpaceProtocol = class {
|
|
2675
|
-
constructor({ topic, swarmIdentity, networkManager, onSessionAuth, onAuthFailure, blobStore }) {
|
|
2676
|
-
this._feeds = /* @__PURE__ */ new Set();
|
|
2677
|
-
this._sessions = new ComplexMap3(PublicKey6.hash);
|
|
2678
|
-
// TODO(burdon): Move to config (with sensible defaults).
|
|
2679
|
-
this._topology = new MMSTTopology({
|
|
2680
|
-
originateConnections: 4,
|
|
2681
|
-
maxPeers: 10,
|
|
2682
|
-
sampleSize: 20
|
|
2683
|
-
});
|
|
2684
|
-
this._spaceKey = topic;
|
|
2685
|
-
this._networkManager = networkManager;
|
|
2686
|
-
this._swarmIdentity = swarmIdentity;
|
|
2687
|
-
this._onSessionAuth = onSessionAuth;
|
|
2688
|
-
this._onAuthFailure = onAuthFailure;
|
|
2689
|
-
this.blobSync = new BlobSync({
|
|
2690
|
-
blobStore
|
|
2769
|
+
/**
|
|
2770
|
+
* Update the local collection state based on the locally stored document heads.
|
|
2771
|
+
*/
|
|
2772
|
+
async updateLocalCollectionState(collectionId, documentIds) {
|
|
2773
|
+
const heads = await this.getHeads(documentIds);
|
|
2774
|
+
const documents = Object.fromEntries(heads.map((heads2, index) => [
|
|
2775
|
+
documentIds[index],
|
|
2776
|
+
heads2 ?? []
|
|
2777
|
+
]));
|
|
2778
|
+
this._collectionSynchronizer.setLocalCollectionState(collectionId, {
|
|
2779
|
+
documents
|
|
2691
2780
|
});
|
|
2692
|
-
this._topic = subtleCrypto3.digest("SHA-256", topic.asBuffer()).then(discoveryKey).then(PublicKey6.from);
|
|
2693
2781
|
}
|
|
2694
|
-
|
|
2695
|
-
|
|
2782
|
+
_onCollectionStateQueried(collectionId, peerId) {
|
|
2783
|
+
this._collectionSynchronizer.onCollectionStateQueried(collectionId, peerId);
|
|
2784
|
+
}
|
|
2785
|
+
_onCollectionStateReceived(collectionId, peerId, state) {
|
|
2786
|
+
this._collectionSynchronizer.onRemoteStateReceived(collectionId, peerId, decodeCollectionState(state));
|
|
2787
|
+
}
|
|
2788
|
+
_queryCollectionState(collectionId, peerId) {
|
|
2789
|
+
this._echoNetworkAdapter.queryCollectionState(collectionId, peerId);
|
|
2696
2790
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
2791
|
+
_sendCollectionState(collectionId, peerId, state) {
|
|
2792
|
+
this._echoNetworkAdapter.sendCollectionState(collectionId, peerId, encodeCollectionState(state));
|
|
2699
2793
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2794
|
+
_onPeerConnected(peerId) {
|
|
2795
|
+
this._collectionSynchronizer.onConnectionOpen(peerId);
|
|
2702
2796
|
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
log10("addFeed", {
|
|
2706
|
-
key: feed.key
|
|
2707
|
-
}, {
|
|
2708
|
-
F: __dxlog_file13,
|
|
2709
|
-
L: 109,
|
|
2710
|
-
S: this,
|
|
2711
|
-
C: (f, a) => f(...a)
|
|
2712
|
-
});
|
|
2713
|
-
this._feeds.add(feed);
|
|
2714
|
-
for (const session of this._sessions.values()) {
|
|
2715
|
-
session.replicator.addFeed(feed);
|
|
2716
|
-
}
|
|
2797
|
+
_onPeerDisconnected(peerId) {
|
|
2798
|
+
this._collectionSynchronizer.onConnectionClosed(peerId);
|
|
2717
2799
|
}
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2800
|
+
_onRemoteCollectionStateUpdated(collectionId, peerId) {
|
|
2801
|
+
const localState = this._collectionSynchronizer.getLocalCollectionState(collectionId);
|
|
2802
|
+
const remoteState = this._collectionSynchronizer.getRemoteCollectionStates(collectionId).get(peerId);
|
|
2803
|
+
if (!localState || !remoteState) {
|
|
2721
2804
|
return;
|
|
2722
2805
|
}
|
|
2723
|
-
const
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
this._connection = await this._networkManager.joinSwarm({
|
|
2733
|
-
protocolProvider: this._createProtocolProvider(credentials),
|
|
2734
|
-
peerId: this._swarmIdentity.peerKey,
|
|
2735
|
-
topic,
|
|
2736
|
-
topology: this._topology,
|
|
2737
|
-
label: `swarm ${topic.truncate()} for space ${this._spaceKey.truncate()}`
|
|
2738
|
-
});
|
|
2739
|
-
log10("started", void 0, {
|
|
2740
|
-
F: __dxlog_file13,
|
|
2741
|
-
L: 138,
|
|
2806
|
+
const { different } = diffCollectionState(localState, remoteState);
|
|
2807
|
+
if (different.length === 0) {
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
log10.info("replication documents after collection sync", {
|
|
2811
|
+
count: different.length
|
|
2812
|
+
}, {
|
|
2813
|
+
F: __dxlog_file12,
|
|
2814
|
+
L: 475,
|
|
2742
2815
|
S: this,
|
|
2743
2816
|
C: (f, a) => f(...a)
|
|
2744
2817
|
});
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
this._topology.forceUpdate();
|
|
2748
|
-
}
|
|
2749
|
-
async stop() {
|
|
2750
|
-
await this.blobSync.close();
|
|
2751
|
-
if (this._connection) {
|
|
2752
|
-
log10("stopping...", void 0, {
|
|
2753
|
-
F: __dxlog_file13,
|
|
2754
|
-
L: 149,
|
|
2755
|
-
S: this,
|
|
2756
|
-
C: (f, a) => f(...a)
|
|
2757
|
-
});
|
|
2758
|
-
await this._connection.close();
|
|
2759
|
-
log10("stopped", void 0, {
|
|
2760
|
-
F: __dxlog_file13,
|
|
2761
|
-
L: 151,
|
|
2762
|
-
S: this,
|
|
2763
|
-
C: (f, a) => f(...a)
|
|
2764
|
-
});
|
|
2818
|
+
for (const documentId of different) {
|
|
2819
|
+
this._repo.find(documentId);
|
|
2765
2820
|
}
|
|
2766
2821
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
const
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
blobSync: this.blobSync
|
|
2775
|
-
});
|
|
2776
|
-
this._sessions.set(wireParams.remotePeerId, session);
|
|
2777
|
-
for (const feed of this._feeds) {
|
|
2778
|
-
session.replicator.addFeed(feed);
|
|
2822
|
+
_onHeadsChanged(documentId, heads) {
|
|
2823
|
+
for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
|
|
2824
|
+
const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
|
|
2825
|
+
if (state?.documents[documentId]) {
|
|
2826
|
+
const newState = structuredClone(state);
|
|
2827
|
+
newState.documents[documentId] = heads;
|
|
2828
|
+
this._collectionSynchronizer.setLocalCollectionState(collectionId, newState);
|
|
2779
2829
|
}
|
|
2780
|
-
|
|
2781
|
-
};
|
|
2830
|
+
}
|
|
2782
2831
|
}
|
|
2783
2832
|
};
|
|
2784
2833
|
_ts_decorate7([
|
|
2785
|
-
logInfo2,
|
|
2786
2834
|
trace4.info()
|
|
2787
|
-
],
|
|
2835
|
+
], AutomergeHost.prototype, "_peerId", void 0);
|
|
2788
2836
|
_ts_decorate7([
|
|
2789
|
-
trace4.info(
|
|
2790
|
-
|
|
2837
|
+
trace4.info({
|
|
2838
|
+
depth: null
|
|
2839
|
+
})
|
|
2840
|
+
], AutomergeHost.prototype, "_automergePeers", null);
|
|
2791
2841
|
_ts_decorate7([
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2842
|
+
trace4.span({
|
|
2843
|
+
showInBrowserTimeline: true
|
|
2844
|
+
})
|
|
2845
|
+
], AutomergeHost.prototype, "flush", null);
|
|
2846
|
+
AutomergeHost = _ts_decorate7([
|
|
2795
2847
|
trace4.resource()
|
|
2796
|
-
],
|
|
2797
|
-
var
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
AuthStatus2["FAILURE"] = "FAILURE";
|
|
2802
|
-
})(AuthStatus || (AuthStatus = {}));
|
|
2803
|
-
var SpaceProtocolSession = class {
|
|
2804
|
-
// TODO(dmaretskyi): Allow to pass in extra extensions.
|
|
2805
|
-
constructor({ wireParams, swarmIdentity, onSessionAuth, onAuthFailure, blobSync }) {
|
|
2806
|
-
// TODO(dmaretskyi): Start with upload=false when switching it on the fly works.
|
|
2807
|
-
this.replicator = new ReplicatorExtension().setOptions({
|
|
2808
|
-
upload: true
|
|
2809
|
-
});
|
|
2810
|
-
this._authStatus = "INITIAL";
|
|
2811
|
-
this._wireParams = wireParams;
|
|
2812
|
-
this._swarmIdentity = swarmIdentity;
|
|
2813
|
-
this._onSessionAuth = onSessionAuth;
|
|
2814
|
-
this._onAuthFailure = onAuthFailure;
|
|
2815
|
-
this._blobSync = blobSync;
|
|
2816
|
-
this._teleport = new Teleport(wireParams);
|
|
2817
|
-
}
|
|
2818
|
-
get authStatus() {
|
|
2819
|
-
return this._authStatus;
|
|
2820
|
-
}
|
|
2821
|
-
get stats() {
|
|
2822
|
-
return this._teleport.stats;
|
|
2823
|
-
}
|
|
2824
|
-
get stream() {
|
|
2825
|
-
return this._teleport.stream;
|
|
2848
|
+
], AutomergeHost);
|
|
2849
|
+
var getSpaceKeyFromDoc = (doc) => {
|
|
2850
|
+
const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
|
|
2851
|
+
if (rawSpaceKey == null) {
|
|
2852
|
+
return null;
|
|
2826
2853
|
}
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
S: this,
|
|
2837
|
-
C: (f, a) => f(...a)
|
|
2838
|
-
});
|
|
2839
|
-
this._authStatus = "SUCCESS";
|
|
2840
|
-
this._onSessionAuth?.(this._teleport);
|
|
2841
|
-
},
|
|
2842
|
-
onAuthFailure: () => {
|
|
2843
|
-
this._authStatus = "FAILURE";
|
|
2844
|
-
this._onAuthFailure?.(this._teleport);
|
|
2854
|
+
return String(rawSpaceKey);
|
|
2855
|
+
};
|
|
2856
|
+
var waitForHeads = async (handle, heads) => {
|
|
2857
|
+
const unavailableHeads = new Set(heads);
|
|
2858
|
+
await handle.whenReady();
|
|
2859
|
+
await Event5.wrap(handle, "change").waitForCondition(() => {
|
|
2860
|
+
for (const changeHash of unavailableHeads.values()) {
|
|
2861
|
+
if (changeIsPresentInDoc(handle.docSync(), changeHash)) {
|
|
2862
|
+
unavailableHeads.delete(changeHash);
|
|
2845
2863
|
}
|
|
2846
|
-
}
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2864
|
+
}
|
|
2865
|
+
return unavailableHeads.size === 0;
|
|
2866
|
+
});
|
|
2867
|
+
};
|
|
2868
|
+
var changeIsPresentInDoc = (doc, changeHash) => {
|
|
2869
|
+
return !!getBackend(doc).getChangeByHash(changeHash);
|
|
2870
|
+
};
|
|
2871
|
+
var decodeCollectionState = (state) => {
|
|
2872
|
+
invariant8(typeof state === "object" && state !== null, "Invalid state", {
|
|
2873
|
+
F: __dxlog_file12,
|
|
2874
|
+
L: 528,
|
|
2875
|
+
S: void 0,
|
|
2876
|
+
A: [
|
|
2877
|
+
"typeof state === 'object' && state !== null",
|
|
2878
|
+
"'Invalid state'"
|
|
2879
|
+
]
|
|
2880
|
+
});
|
|
2881
|
+
return state;
|
|
2882
|
+
};
|
|
2883
|
+
var encodeCollectionState = (state) => {
|
|
2884
|
+
return state;
|
|
2862
2885
|
};
|
|
2863
|
-
_ts_decorate7([
|
|
2864
|
-
logInfo2
|
|
2865
|
-
], SpaceProtocolSession.prototype, "_wireParams", void 0);
|
|
2866
|
-
_ts_decorate7([
|
|
2867
|
-
logInfo2
|
|
2868
|
-
], SpaceProtocolSession.prototype, "authStatus", null);
|
|
2869
|
-
|
|
2870
|
-
// packages/core/echo/echo-pipeline/src/space/space-manager.ts
|
|
2871
|
-
import { synchronized as synchronized4, trackLeaks as trackLeaks3, Trigger as Trigger3 } from "@dxos/async";
|
|
2872
|
-
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
2873
|
-
import { PublicKey as PublicKey8 } from "@dxos/keys";
|
|
2874
|
-
import { log as log14 } from "@dxos/log";
|
|
2875
|
-
import { trace as trace6 } from "@dxos/protocols";
|
|
2876
|
-
import { ComplexMap as ComplexMap4 } from "@dxos/util";
|
|
2877
|
-
|
|
2878
|
-
// packages/core/echo/echo-pipeline/src/db-host/data-service.ts
|
|
2879
|
-
import { Stream } from "@dxos/codec-protobuf";
|
|
2880
|
-
import { invariant as invariant12 } from "@dxos/invariant";
|
|
2881
|
-
import { SpaceId as SpaceId3 } from "@dxos/keys";
|
|
2882
|
-
import { log as log13 } from "@dxos/log";
|
|
2883
2886
|
|
|
2884
2887
|
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
|
|
2885
2888
|
import { invariant as invariant11 } from "@dxos/invariant";
|
|
@@ -2888,12 +2891,13 @@ import { log as log12 } from "@dxos/log";
|
|
|
2888
2891
|
import { ComplexSet, defaultMap as defaultMap2 } from "@dxos/util";
|
|
2889
2892
|
|
|
2890
2893
|
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts
|
|
2894
|
+
import * as A2 from "@dxos/automerge/automerge";
|
|
2891
2895
|
import { cbor } from "@dxos/automerge/automerge-repo";
|
|
2892
2896
|
import { Resource as Resource6 } from "@dxos/context";
|
|
2893
|
-
import { invariant as
|
|
2897
|
+
import { invariant as invariant9 } from "@dxos/invariant";
|
|
2894
2898
|
import { log as log11 } from "@dxos/log";
|
|
2895
2899
|
import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
|
|
2896
|
-
var
|
|
2900
|
+
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
|
|
2897
2901
|
var DEFAULT_FACTORY = (params) => new AutomergeReplicator(...params);
|
|
2898
2902
|
var MeshReplicatorConnection = class extends Resource6 {
|
|
2899
2903
|
constructor(_params) {
|
|
@@ -2911,9 +2915,9 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
2911
2915
|
});
|
|
2912
2916
|
this.writable = new WritableStream({
|
|
2913
2917
|
write: async (message, controller) => {
|
|
2914
|
-
|
|
2915
|
-
F:
|
|
2916
|
-
L:
|
|
2918
|
+
invariant9(this._isEnabled, "Writing to a disabled connection", {
|
|
2919
|
+
F: __dxlog_file13,
|
|
2920
|
+
L: 49,
|
|
2917
2921
|
S: this,
|
|
2918
2922
|
A: [
|
|
2919
2923
|
"this._isEnabled",
|
|
@@ -2921,6 +2925,7 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
2921
2925
|
]
|
|
2922
2926
|
});
|
|
2923
2927
|
try {
|
|
2928
|
+
logSendSync(message);
|
|
2924
2929
|
await this.replicatorExtension.sendSyncMessage({
|
|
2925
2930
|
payload: cbor.encode(message)
|
|
2926
2931
|
});
|
|
@@ -2944,8 +2949,8 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
2944
2949
|
thisPeerId: this.peerId,
|
|
2945
2950
|
remotePeerId: remotePeerId.toHex()
|
|
2946
2951
|
}, {
|
|
2947
|
-
F:
|
|
2948
|
-
L:
|
|
2952
|
+
F: __dxlog_file13,
|
|
2953
|
+
L: 84,
|
|
2949
2954
|
S: this,
|
|
2950
2955
|
C: (f, a) => f(...a)
|
|
2951
2956
|
});
|
|
@@ -2970,9 +2975,9 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
2970
2975
|
}
|
|
2971
2976
|
}
|
|
2972
2977
|
get peerId() {
|
|
2973
|
-
|
|
2974
|
-
F:
|
|
2975
|
-
L:
|
|
2978
|
+
invariant9(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
2979
|
+
F: __dxlog_file13,
|
|
2980
|
+
L: 110,
|
|
2976
2981
|
S: this,
|
|
2977
2982
|
A: [
|
|
2978
2983
|
"this._remotePeerId != null",
|
|
@@ -2992,9 +2997,9 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
2992
2997
|
* Call after the remote peer has connected.
|
|
2993
2998
|
*/
|
|
2994
2999
|
enable() {
|
|
2995
|
-
|
|
2996
|
-
F:
|
|
2997
|
-
L:
|
|
3000
|
+
invariant9(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
3001
|
+
F: __dxlog_file13,
|
|
3002
|
+
L: 127,
|
|
2998
3003
|
S: this,
|
|
2999
3004
|
A: [
|
|
3000
3005
|
"this._remotePeerId != null",
|
|
@@ -3010,6 +3015,45 @@ var MeshReplicatorConnection = class extends Resource6 {
|
|
|
3010
3015
|
this._isEnabled = false;
|
|
3011
3016
|
}
|
|
3012
3017
|
};
|
|
3018
|
+
var logSendSync = (message) => {
|
|
3019
|
+
log11("sendSyncMessage", () => {
|
|
3020
|
+
const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
|
|
3021
|
+
return {
|
|
3022
|
+
sync: decodedSyncMessage && {
|
|
3023
|
+
headsLength: decodedSyncMessage.heads.length,
|
|
3024
|
+
requesting: decodedSyncMessage.need.length > 0,
|
|
3025
|
+
sendingChanges: decodedSyncMessage.changes.length > 0
|
|
3026
|
+
},
|
|
3027
|
+
type: message.type,
|
|
3028
|
+
from: message.senderId,
|
|
3029
|
+
to: message.targetId
|
|
3030
|
+
};
|
|
3031
|
+
}, {
|
|
3032
|
+
F: __dxlog_file13,
|
|
3033
|
+
L: 140,
|
|
3034
|
+
S: void 0,
|
|
3035
|
+
C: (f, a) => f(...a)
|
|
3036
|
+
});
|
|
3037
|
+
};
|
|
3038
|
+
|
|
3039
|
+
// packages/core/echo/echo-pipeline/src/automerge/space-collection.ts
|
|
3040
|
+
import { invariant as invariant10 } from "@dxos/invariant";
|
|
3041
|
+
import { SpaceId as SpaceId2 } from "@dxos/keys";
|
|
3042
|
+
var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
|
|
3043
|
+
var deriveCollectionIdFromSpaceId = (spaceId) => `space:${spaceId}`;
|
|
3044
|
+
var getSpaceIdFromCollectionId = (collectionId) => {
|
|
3045
|
+
const spaceId = collectionId.replace(/^space:/, "");
|
|
3046
|
+
invariant10(SpaceId2.isValid(spaceId), void 0, {
|
|
3047
|
+
F: __dxlog_file14,
|
|
3048
|
+
L: 12,
|
|
3049
|
+
S: void 0,
|
|
3050
|
+
A: [
|
|
3051
|
+
"SpaceId.isValid(spaceId)",
|
|
3052
|
+
""
|
|
3053
|
+
]
|
|
3054
|
+
});
|
|
3055
|
+
return spaceId;
|
|
3056
|
+
};
|
|
3013
3057
|
|
|
3014
3058
|
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
|
|
3015
3059
|
var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
|
|
@@ -3115,16 +3159,21 @@ var MeshEchoReplicator = class {
|
|
|
3115
3159
|
try {
|
|
3116
3160
|
const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
|
|
3117
3161
|
if (!spaceKey) {
|
|
3118
|
-
|
|
3162
|
+
const remoteDocumentExists = await this._context.isDocumentInRemoteCollection({
|
|
3163
|
+
documentId: params.documentId,
|
|
3164
|
+
peerId: connection.peerId
|
|
3165
|
+
});
|
|
3166
|
+
log12("document not found locally for share policy check, accepting the remote document", {
|
|
3119
3167
|
peerId: connection.peerId,
|
|
3120
|
-
documentId: params.documentId
|
|
3168
|
+
documentId: params.documentId,
|
|
3169
|
+
remoteDocumentExists
|
|
3121
3170
|
}, {
|
|
3122
3171
|
F: __dxlog_file15,
|
|
3123
|
-
L:
|
|
3172
|
+
L: 90,
|
|
3124
3173
|
S: this,
|
|
3125
3174
|
C: (f, a) => f(...a)
|
|
3126
3175
|
});
|
|
3127
|
-
return
|
|
3176
|
+
return remoteDocumentExists;
|
|
3128
3177
|
}
|
|
3129
3178
|
const spaceId = await createIdFromSpaceKey(spaceKey);
|
|
3130
3179
|
const authorizedDevices = this._authorizedDevices.get(spaceId);
|
|
@@ -3134,7 +3183,7 @@ var MeshEchoReplicator = class {
|
|
|
3134
3183
|
documentId: params.documentId
|
|
3135
3184
|
}, {
|
|
3136
3185
|
F: __dxlog_file15,
|
|
3137
|
-
L:
|
|
3186
|
+
L: 106,
|
|
3138
3187
|
S: this,
|
|
3139
3188
|
C: (f, a) => f(...a)
|
|
3140
3189
|
});
|
|
@@ -3150,7 +3199,7 @@ var MeshEchoReplicator = class {
|
|
|
3150
3199
|
isAuthorized
|
|
3151
3200
|
}, {
|
|
3152
3201
|
F: __dxlog_file15,
|
|
3153
|
-
L:
|
|
3202
|
+
L: 114,
|
|
3154
3203
|
S: this,
|
|
3155
3204
|
C: (f, a) => f(...a)
|
|
3156
3205
|
});
|
|
@@ -3158,7 +3207,7 @@ var MeshEchoReplicator = class {
|
|
|
3158
3207
|
} catch (err) {
|
|
3159
3208
|
log12.catch(err, void 0, {
|
|
3160
3209
|
F: __dxlog_file15,
|
|
3161
|
-
L:
|
|
3210
|
+
L: 124,
|
|
3162
3211
|
S: this,
|
|
3163
3212
|
C: (f, a) => f(...a)
|
|
3164
3213
|
});
|
|
@@ -3174,7 +3223,7 @@ var MeshEchoReplicator = class {
|
|
|
3174
3223
|
collectionId
|
|
3175
3224
|
}, {
|
|
3176
3225
|
F: __dxlog_file15,
|
|
3177
|
-
L:
|
|
3226
|
+
L: 134,
|
|
3178
3227
|
S: this,
|
|
3179
3228
|
C: (f, a) => f(...a)
|
|
3180
3229
|
});
|
|
@@ -3193,7 +3242,7 @@ var MeshEchoReplicator = class {
|
|
|
3193
3242
|
deviceKey
|
|
3194
3243
|
}, {
|
|
3195
3244
|
F: __dxlog_file15,
|
|
3196
|
-
L:
|
|
3245
|
+
L: 151,
|
|
3197
3246
|
S: this,
|
|
3198
3247
|
C: (f, a) => f(...a)
|
|
3199
3248
|
});
|
|
@@ -3703,7 +3752,7 @@ function _ts_decorate9(decorators, target, key, desc) {
|
|
|
3703
3752
|
}
|
|
3704
3753
|
var __dxlog_file17 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/space/space-manager.ts";
|
|
3705
3754
|
var SpaceManager = class {
|
|
3706
|
-
constructor({ feedStore, networkManager, metadataStore, snapshotStore, blobStore }) {
|
|
3755
|
+
constructor({ feedStore, networkManager, metadataStore, snapshotStore, blobStore, disableP2pReplication }) {
|
|
3707
3756
|
this._spaces = new ComplexMap4(PublicKey8.hash);
|
|
3708
3757
|
this._instanceId = PublicKey8.random().toHex();
|
|
3709
3758
|
this._feedStore = feedStore;
|
|
@@ -3711,6 +3760,7 @@ var SpaceManager = class {
|
|
|
3711
3760
|
this._metadataStore = metadataStore;
|
|
3712
3761
|
this._snapshotStore = snapshotStore;
|
|
3713
3762
|
this._blobStore = blobStore;
|
|
3763
|
+
this._disableP2pReplication = disableP2pReplication ?? false;
|
|
3714
3764
|
}
|
|
3715
3765
|
// TODO(burdon): Remove.
|
|
3716
3766
|
get spaces() {
|
|
@@ -3728,7 +3778,7 @@ var SpaceManager = class {
|
|
|
3728
3778
|
id: this._instanceId
|
|
3729
3779
|
}), {
|
|
3730
3780
|
F: __dxlog_file17,
|
|
3731
|
-
L:
|
|
3781
|
+
L: 114,
|
|
3732
3782
|
S: this,
|
|
3733
3783
|
C: (f, a) => f(...a)
|
|
3734
3784
|
});
|
|
@@ -3736,7 +3786,7 @@ var SpaceManager = class {
|
|
|
3736
3786
|
spaceKey: metadata.genesisFeedKey
|
|
3737
3787
|
}, {
|
|
3738
3788
|
F: __dxlog_file17,
|
|
3739
|
-
L:
|
|
3789
|
+
L: 115,
|
|
3740
3790
|
S: this,
|
|
3741
3791
|
C: (f, a) => f(...a)
|
|
3742
3792
|
});
|
|
@@ -3749,7 +3799,8 @@ var SpaceManager = class {
|
|
|
3749
3799
|
networkManager: this._networkManager,
|
|
3750
3800
|
onSessionAuth: onAuthorizedConnection,
|
|
3751
3801
|
onAuthFailure,
|
|
3752
|
-
blobStore: this._blobStore
|
|
3802
|
+
blobStore: this._blobStore,
|
|
3803
|
+
disableP2pReplication: this._disableP2pReplication
|
|
3753
3804
|
});
|
|
3754
3805
|
const snapshotManager = new SnapshotManager(this._snapshotStore, this._blobStore, protocol.blobSync);
|
|
3755
3806
|
const space = new Space({
|
|
@@ -3769,7 +3820,7 @@ var SpaceManager = class {
|
|
|
3769
3820
|
id: this._instanceId
|
|
3770
3821
|
}), {
|
|
3771
3822
|
F: __dxlog_file17,
|
|
3772
|
-
L:
|
|
3823
|
+
L: 147,
|
|
3773
3824
|
S: this,
|
|
3774
3825
|
C: (f, a) => f(...a)
|
|
3775
3826
|
});
|
|
@@ -3781,7 +3832,7 @@ var SpaceManager = class {
|
|
|
3781
3832
|
id: this._instanceId
|
|
3782
3833
|
}), {
|
|
3783
3834
|
F: __dxlog_file17,
|
|
3784
|
-
L:
|
|
3835
|
+
L: 153,
|
|
3785
3836
|
S: this,
|
|
3786
3837
|
C: (f, a) => f(...a)
|
|
3787
3838
|
});
|
|
@@ -3789,7 +3840,7 @@ var SpaceManager = class {
|
|
|
3789
3840
|
spaceKey: params.spaceKey
|
|
3790
3841
|
}, {
|
|
3791
3842
|
F: __dxlog_file17,
|
|
3792
|
-
L:
|
|
3843
|
+
L: 154,
|
|
3793
3844
|
S: this,
|
|
3794
3845
|
C: (f, a) => f(...a)
|
|
3795
3846
|
});
|
|
@@ -3805,7 +3856,8 @@ var SpaceManager = class {
|
|
|
3805
3856
|
}, onCredentialResolved));
|
|
3806
3857
|
},
|
|
3807
3858
|
onAuthFailure: (session) => session.close(),
|
|
3808
|
-
blobStore: this._blobStore
|
|
3859
|
+
blobStore: this._blobStore,
|
|
3860
|
+
disableP2pReplication: this._disableP2pReplication
|
|
3809
3861
|
});
|
|
3810
3862
|
try {
|
|
3811
3863
|
await protocol.start();
|
|
@@ -3816,7 +3868,7 @@ var SpaceManager = class {
|
|
|
3816
3868
|
id: this._instanceId
|
|
3817
3869
|
}), {
|
|
3818
3870
|
F: __dxlog_file17,
|
|
3819
|
-
L:
|
|
3871
|
+
L: 178,
|
|
3820
3872
|
S: this,
|
|
3821
3873
|
C: (f, a) => f(...a)
|
|
3822
3874
|
});
|
|
@@ -3827,7 +3879,7 @@ var SpaceManager = class {
|
|
|
3827
3879
|
error: err
|
|
3828
3880
|
}), {
|
|
3829
3881
|
F: __dxlog_file17,
|
|
3830
|
-
L:
|
|
3882
|
+
L: 181,
|
|
3831
3883
|
S: this,
|
|
3832
3884
|
C: (f, a) => f(...a)
|
|
3833
3885
|
});
|
|
@@ -4198,12 +4250,6 @@ export {
|
|
|
4198
4250
|
SnapshotStore,
|
|
4199
4251
|
DocumentsSynchronizer,
|
|
4200
4252
|
diffCollectionState,
|
|
4201
|
-
LevelDBStorageAdapter,
|
|
4202
|
-
encodingOptions,
|
|
4203
|
-
AutomergeHost,
|
|
4204
|
-
getSpaceKeyFromDoc,
|
|
4205
|
-
deriveCollectionIdFromSpaceId,
|
|
4206
|
-
getSpaceIdFromCollectionId,
|
|
4207
4253
|
AuthExtension,
|
|
4208
4254
|
mapTimeframeToFeedIndexes,
|
|
4209
4255
|
mapFeedIndexesToTimeframe,
|
|
@@ -4220,10 +4266,16 @@ export {
|
|
|
4220
4266
|
AuthStatus,
|
|
4221
4267
|
SpaceProtocolSession,
|
|
4222
4268
|
SpaceManager,
|
|
4269
|
+
LevelDBStorageAdapter,
|
|
4270
|
+
encodingOptions,
|
|
4271
|
+
AutomergeHost,
|
|
4272
|
+
getSpaceKeyFromDoc,
|
|
4273
|
+
deriveCollectionIdFromSpaceId,
|
|
4274
|
+
getSpaceIdFromCollectionId,
|
|
4223
4275
|
MeshEchoReplicator,
|
|
4224
4276
|
EchoDataMonitor,
|
|
4225
4277
|
DataServiceImpl,
|
|
4226
4278
|
MetadataStore,
|
|
4227
4279
|
hasInvitationExpired
|
|
4228
4280
|
};
|
|
4229
|
-
//# sourceMappingURL=chunk-
|
|
4281
|
+
//# sourceMappingURL=chunk-P6XSIJKM.mjs.map
|