@ibgib/core-gib 0.1.28 → 0.1.30
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/.vscode/launch.json +17 -1
- package/dist/common/meta-stone/meta-stone-helper.d.mts.map +1 -1
- package/dist/common/meta-stone/meta-stone-helper.mjs +30 -12
- package/dist/common/meta-stone/meta-stone-helper.mjs.map +1 -1
- package/dist/common/meta-stone/meta-stone-types.d.mts +5 -2
- package/dist/common/meta-stone/meta-stone-types.d.mts.map +1 -1
- package/dist/sync/strategies/conflict-optimistic.d.mts +16 -0
- package/dist/sync/strategies/conflict-optimistic.d.mts.map +1 -1
- package/dist/sync/strategies/conflict-optimistic.mjs +28 -1
- package/dist/sync/strategies/conflict-optimistic.mjs.map +1 -1
- package/dist/sync/sync-conflict.respec.mjs +5 -5
- package/dist/sync/sync-conflict.respec.mjs.map +1 -1
- package/dist/sync/sync-helpers.d.mts +4 -4
- package/dist/sync/sync-helpers.d.mts.map +1 -1
- package/dist/sync/sync-helpers.mjs +12 -8
- package/dist/sync/sync-helpers.mjs.map +1 -1
- package/dist/sync/sync-innerspace-constants.respec.mjs +36 -36
- package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs +3 -1
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +62 -9
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace.respec.mjs +45 -16
- package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +0 -9
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +25 -43
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +2 -2
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +15 -10
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +304 -163
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +3 -3
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
- package/dist/sync/sync-types.d.mts +12 -18
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/dist/sync/sync-types.mjs +15 -21
- package/dist/sync/sync-types.mjs.map +1 -1
- package/dist/timeline/timeline-api.d.mts +12 -0
- package/dist/timeline/timeline-api.d.mts.map +1 -1
- package/dist/timeline/timeline-api.mjs +26 -0
- package/dist/timeline/timeline-api.mjs.map +1 -1
- package/dist/witness/space/inner-space/inner-space-v1.d.mts +19 -0
- package/dist/witness/space/inner-space/inner-space-v1.d.mts.map +1 -1
- package/dist/witness/space/inner-space/inner-space-v1.mjs +189 -30
- package/dist/witness/space/inner-space/inner-space-v1.mjs.map +1 -1
- package/dist/witness/space/inner-space/inner-space-v1.respec.mjs +9 -0
- package/dist/witness/space/inner-space/inner-space-v1.respec.mjs.map +1 -1
- package/dist/witness/space/space-helper.d.mts.map +1 -1
- package/dist/witness/space/space-helper.mjs +2 -1
- package/dist/witness/space/space-helper.mjs.map +1 -1
- package/package.json +2 -1
- package/src/common/meta-stone/meta-stone-helper.mts +25 -11
- package/src/common/meta-stone/meta-stone-types.mts +5 -2
- package/src/sync/README.md +4 -4
- package/src/sync/docs/architecture.md +6 -6
- package/src/sync/strategies/conflict-optimistic.mts +41 -4
- package/src/sync/sync-conflict.respec.mts +5 -5
- package/src/sync/sync-helpers.mts +13 -9
- package/src/sync/sync-innerspace-constants.respec.mts +39 -39
- package/src/sync/sync-innerspace-deep-updates.respec.mts +5 -5
- package/src/sync/sync-innerspace-dest-ahead.respec.mts +73 -9
- package/src/sync/sync-innerspace.respec.mts +17 -16
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +23 -60
- package/src/sync/sync-peer/sync-peer-v1.mts +2 -2
- package/src/sync/sync-saga-coordinator.mts +231 -173
- package/src/sync/sync-saga-message/sync-saga-message-types.mts +3 -3
- package/src/sync/sync-types.mts +19 -26
- package/src/timeline/timeline-api.mts +51 -11
- package/src/witness/space/inner-space/inner-space-v1.mts +191 -29
- package/src/witness/space/inner-space/inner-space-v1.respec.mts +13 -0
- package/src/witness/space/space-helper.mts +3 -2
- package/test_output.log +0 -0
- package/tmp.md +170 -62
|
@@ -2,12 +2,13 @@ import { extractErrorMsg, getUUID, // so our timestamp in ticks as a string are
|
|
|
2
2
|
pretty, delay, } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
|
|
3
3
|
import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
4
4
|
import { Factory_V1 } from "@ibgib/ts-gib/dist/V1/factory.mjs";
|
|
5
|
+
import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
|
|
5
6
|
import { putInSpace, getLatestAddrs, getFromSpace } from "../witness/space/space-helper.mjs";
|
|
6
7
|
import { SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN, } from "./sync-constants.mjs";
|
|
7
|
-
import { appendToTimeline, createTimeline } from "../timeline/timeline-api.mjs";
|
|
8
|
+
import { appendToTimeline, createTimeline, getHistoryAddrs } from "../timeline/timeline-api.mjs";
|
|
8
9
|
import { SyncConflictStrategy, SyncMode, SYNC_CONFLICT_STRATEGY_VALID_VALUES, } from "./sync-types.mjs";
|
|
9
|
-
import { getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
|
|
10
|
-
import { getDeltaDependencyGraph, getDependencyGraph
|
|
10
|
+
import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
|
|
11
|
+
import { getDeltaDependencyGraph, getDependencyGraph } from "../common/other/graph-helper.mjs";
|
|
11
12
|
import { getSyncSagaMessageIb } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
12
13
|
import { SYNC_SAGA_MSG_ATOM } from "./sync-saga-message/sync-saga-message-constants.mjs";
|
|
13
14
|
import { splitPerTjpAndOrDna, getTimelinesGroupedByTjp, isIbGib } from "../common/other/ibgib-helper.mjs";
|
|
@@ -16,9 +17,8 @@ import { newupSubject, } from "../common/pubsub/subject/subject-helper.mjs";
|
|
|
16
17
|
import { mergeDivergentTimelines } from "./strategies/conflict-optimistic.mjs";
|
|
17
18
|
import { getSyncSagaMessageFromFrame } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
18
19
|
import { fnObs } from "../common/pubsub/observer/observer-helper.mjs";
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const logalotControlDomain = true;
|
|
20
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
21
|
+
const logalotControlDomain = false;
|
|
22
22
|
const lcControlDomain = '[ControlDomain]';
|
|
23
23
|
/**
|
|
24
24
|
* Orchestrates the synchronization process between two spaces (Source and Destination).
|
|
@@ -407,8 +407,13 @@ export class SyncSagaCoordinator {
|
|
|
407
407
|
metaspace,
|
|
408
408
|
});
|
|
409
409
|
if (!contextResult) {
|
|
410
|
+
// should this ever hit?
|
|
411
|
+
console.error(`${lc} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
410
415
|
if (logalot) {
|
|
411
|
-
console.log(`${lc} Handler returned null (Saga End). (I:
|
|
416
|
+
console.log(`${lc} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
|
|
412
417
|
}
|
|
413
418
|
break;
|
|
414
419
|
}
|
|
@@ -419,9 +424,6 @@ export class SyncSagaCoordinator {
|
|
|
419
424
|
else if (!contextResult.nextFrameInfo) {
|
|
420
425
|
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
|
|
421
426
|
}
|
|
422
|
-
else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
423
|
-
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo.sagaComplete? logic flow should not have gotten here. (E: 104a32381db816b7183435e805b3d626)`);
|
|
424
|
-
}
|
|
425
427
|
// #endregion error conditions throw
|
|
426
428
|
// we have another frame to process and send out, with possibly
|
|
427
429
|
// payload domain ibgibs as well
|
|
@@ -439,11 +441,11 @@ export class SyncSagaCoordinator {
|
|
|
439
441
|
}
|
|
440
442
|
}
|
|
441
443
|
/**
|
|
442
|
-
* Helper to get Knowledge
|
|
444
|
+
* Helper to get Knowledge Map for specific domain ibGibs or TJPs.
|
|
443
445
|
* Useful for testing and external validation.
|
|
444
446
|
*/
|
|
445
|
-
async
|
|
446
|
-
const lc = `${this.lc}[${this.
|
|
447
|
+
async getKnowledgeMap({ space, metaspace, domainIbGibs, tjpAddrs, }) {
|
|
448
|
+
const lc = `${this.lc}[${this.getKnowledgeMap.name}]`;
|
|
447
449
|
try {
|
|
448
450
|
if (logalot) {
|
|
449
451
|
console.log(`${lc} starting... (I: e184f8a7818666febfbbd2d841ed3826)`);
|
|
@@ -484,7 +486,7 @@ export class SyncSagaCoordinator {
|
|
|
484
486
|
else {
|
|
485
487
|
// No info provided. Return empty? Or throw?
|
|
486
488
|
// User test context implied "everything", but implementation requires scope.
|
|
487
|
-
console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty
|
|
489
|
+
console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty Knowledge.`);
|
|
488
490
|
return {};
|
|
489
491
|
}
|
|
490
492
|
if (tjps.length === 0) {
|
|
@@ -538,7 +540,7 @@ export class SyncSagaCoordinator {
|
|
|
538
540
|
* @remarks
|
|
539
541
|
* **Execution Context**: **Sender (Local)**.
|
|
540
542
|
*
|
|
541
|
-
* Generates the first frame containing the Knowledge
|
|
543
|
+
* Generates the first frame containing the Knowledge Map of the Local Space.
|
|
542
544
|
* This is sent to the Receiver to begin Gap Analysis.
|
|
543
545
|
*/
|
|
544
546
|
async createInitFrame({ sagaId, sessionIdentity, domainIbGibs, conflictStrategy, metaspace, localSpace, tempSpace, }) {
|
|
@@ -553,17 +555,17 @@ export class SyncSagaCoordinator {
|
|
|
553
555
|
const { timelinesMap: srcTimelinesMap, fullGraph, stones: srcStones, } = analysis;
|
|
554
556
|
// we need to store the fullGraph in our tempSpace for later...
|
|
555
557
|
await putInSpace({ ibGibs: Object.values(fullGraph), space: tempSpace });
|
|
556
|
-
// populate our knowledge
|
|
557
|
-
const
|
|
558
|
+
// populate our knowledge map with tjp -> latest addr/tip in timeline
|
|
559
|
+
const knowledgeMap = {};
|
|
558
560
|
Object.keys(srcTimelinesMap).forEach(tjp => {
|
|
559
561
|
const timeline = srcTimelinesMap[tjp];
|
|
560
562
|
const tip = timeline.at(-1);
|
|
561
|
-
|
|
563
|
+
knowledgeMap[tjp] = getIbGibAddr({ ibGib: tip });
|
|
562
564
|
});
|
|
563
565
|
const initData = {
|
|
564
566
|
sagaId,
|
|
565
567
|
stage: SyncStage.init,
|
|
566
|
-
|
|
568
|
+
knowledgeMap: knowledgeMap,
|
|
567
569
|
identity: sessionIdentity, // KeystoneIbGib is already public data
|
|
568
570
|
mode: SyncMode.sync,
|
|
569
571
|
stones: srcStones.map(s => getIbGibAddr({ ibGib: s })),
|
|
@@ -670,16 +672,21 @@ export class SyncSagaCoordinator {
|
|
|
670
672
|
*
|
|
671
673
|
* ## 1. Sender
|
|
672
674
|
*
|
|
673
|
-
* On the sender, this is called within the
|
|
674
|
-
* initiates and drives the
|
|
675
|
+
* On the sender, this is called repeatedly within the the sync saga
|
|
676
|
+
* coordinator's {@link executeSagaLoop} which initiates and drives the
|
|
677
|
+
* overall sync process. This loop continues until there are no more frames
|
|
678
|
+
* to be exchanged between endpoints.
|
|
675
679
|
*
|
|
676
680
|
* ## 2. Receiver
|
|
677
681
|
*
|
|
678
|
-
* On the receiver, this is called directly
|
|
679
|
-
*
|
|
680
|
-
*
|
|
682
|
+
* On the receiver, this is called directly from {@link continueSync}, which
|
|
683
|
+
* itself is called either directly by the concrete sync peer or from within
|
|
684
|
+
* the receiving node endpoint. That endpoint's job is basically to get
|
|
685
|
+
* these things collocated and prepared to make this call.
|
|
681
686
|
*
|
|
682
|
-
*
|
|
687
|
+
* In contrast to the sender, this can be thought of as a one-off on the
|
|
688
|
+
* receiver, since the sender's {@link executeSagaLoop} is what actually
|
|
689
|
+
* drives the ping-pong process.
|
|
683
690
|
*/
|
|
684
691
|
async handleResponseSagaContext({ sagaContext, initDomainGraph, mySpace, myTempSpace, identity, identitySecret, metaspace, }) {
|
|
685
692
|
const lc = `${this.lc}[${this.handleResponseSagaContext.name}]`;
|
|
@@ -699,10 +706,6 @@ export class SyncSagaCoordinator {
|
|
|
699
706
|
if (logalot) {
|
|
700
707
|
console.log(`${lc} handling frame stage: ${stage}`);
|
|
701
708
|
}
|
|
702
|
-
/**
|
|
703
|
-
* don't like this name, need to refactor
|
|
704
|
-
*/
|
|
705
|
-
const srcGraph = toFlatGraph({ ibGibs: sagaContext.payloadIbGibsDomain }) ?? {};
|
|
706
709
|
let nextFrameInfo;
|
|
707
710
|
switch (stage) {
|
|
708
711
|
case SyncStage.init:
|
|
@@ -729,15 +732,19 @@ export class SyncSagaCoordinator {
|
|
|
729
732
|
nextFrameInfo = await this.handleDeltaFrame({
|
|
730
733
|
sagaContext,
|
|
731
734
|
sagaIbGib,
|
|
732
|
-
|
|
733
|
-
metaspace,
|
|
734
|
-
mySpace,
|
|
735
|
-
myTempSpace,
|
|
735
|
+
metaspace, mySpace, myTempSpace,
|
|
736
736
|
identity,
|
|
737
737
|
});
|
|
738
738
|
break;
|
|
739
739
|
case SyncStage.commit:
|
|
740
|
-
|
|
740
|
+
if (logalot) {
|
|
741
|
+
console.log(`${lc}[${getSyncSagaFrameOrigin({ sagaFrame: sagaIbGib })}] mySpace.ib: ${mySpace.ib} (I: 5b270996d848907238d817fffa64a126)`);
|
|
742
|
+
}
|
|
743
|
+
nextFrameInfo = await this.handleCommitFrame({
|
|
744
|
+
sagaIbGib,
|
|
745
|
+
metaspace, mySpace, myTempSpace,
|
|
746
|
+
identity,
|
|
747
|
+
});
|
|
741
748
|
break;
|
|
742
749
|
default:
|
|
743
750
|
throw new Error(`${lc} (UNEXPECTED) Unknown sync stage: ${stage} (E: 9c2b4c8a6d34469f8263544710183355)`);
|
|
@@ -766,7 +773,7 @@ export class SyncSagaCoordinator {
|
|
|
766
773
|
* **Execution Context**: **Receiver (Remote)**.
|
|
767
774
|
*
|
|
768
775
|
* The Receiver performs Gap Analysis here:
|
|
769
|
-
* 1. Compares Sender's Knowledge
|
|
776
|
+
* 1. Compares Sender's Knowledge Map (in `sagaIbGib`) vs Receiver's Local Knowledge Map.
|
|
770
777
|
* 2. Identifies what Sender needs (`pushOfferAddrs`).
|
|
771
778
|
* 3. Identifies what Receiver needs (`deltaRequestAddrInfos`).
|
|
772
779
|
* 4. Returns an `Ack` frame containing these lists.
|
|
@@ -779,15 +786,17 @@ export class SyncSagaCoordinator {
|
|
|
779
786
|
if (logalot) {
|
|
780
787
|
console.log(`${lc} starting... (I: 9d88dcad0408c029e898a4bcf3b08426)`);
|
|
781
788
|
}
|
|
782
|
-
|
|
789
|
+
if (logalot) {
|
|
790
|
+
console.log(`${lc} [TEST DEBUG] Receiver mySpace: ${mySpace.ib}`);
|
|
791
|
+
}
|
|
783
792
|
// Extract Init Data
|
|
784
793
|
const initData = messageData; // Using renamed variable for clarity
|
|
785
794
|
if (initData.stage !== SyncStage.init) {
|
|
786
795
|
throw new Error(`${lc} Invalid init frame: initData.stage !== SyncStage.init (E: c91be82970e4decc58f56bf8fc1ffc26)`);
|
|
787
796
|
}
|
|
788
797
|
// if (logalot) { console.log(`${lc} initData: ${pretty(initData)} (I: 46b0f8441b96ad7a388f1ce3239dd826)`); }
|
|
789
|
-
if (!initData || !initData.
|
|
790
|
-
throw new Error(`${lc} Invalid init frame: missing
|
|
798
|
+
if (!initData || !initData.knowledgeMap) {
|
|
799
|
+
throw new Error(`${lc} Invalid init frame: missing knowledgeMap (E: ed02c869e028d2d06841b9c7f80f2826)`);
|
|
791
800
|
}
|
|
792
801
|
// Determine Strategy from Saga Data (since V1 stores it in root)
|
|
793
802
|
const conflictStrategy = sagaIbGib.data.conflictStrategy || SyncConflictStrategy.abort;
|
|
@@ -822,12 +831,14 @@ export class SyncSagaCoordinator {
|
|
|
822
831
|
/**
|
|
823
832
|
* "remote" is sender in this case
|
|
824
833
|
*/
|
|
825
|
-
const
|
|
834
|
+
const remoteKnowledge = initData.knowledgeMap;
|
|
826
835
|
if (logalot) {
|
|
827
|
-
console.log(`${lc}
|
|
836
|
+
console.log(`${lc} remoteKnowledge: ${pretty(remoteKnowledge)} (I: 9f957862356dfeae183c200854e86e26)`);
|
|
837
|
+
}
|
|
838
|
+
const remoteTjps = Object.keys(remoteKnowledge);
|
|
839
|
+
if (logalot) {
|
|
840
|
+
console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`);
|
|
828
841
|
}
|
|
829
|
-
const remoteTjps = Object.keys(remoteKV);
|
|
830
|
-
console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`);
|
|
831
842
|
if (logalot) {
|
|
832
843
|
console.log(`${lc} remoteTjps: ${pretty(remoteTjps)} (I: 86ea4c53db0dc184c8b253386c402126)`);
|
|
833
844
|
}
|
|
@@ -846,18 +857,22 @@ export class SyncSagaCoordinator {
|
|
|
846
857
|
throw new Error(`(UNEXPECTED) resGetLatestAddrs.data.latestAddrsMap falsy? (E: 16bc386dd51d0ff53a49620b1e641826)`);
|
|
847
858
|
}
|
|
848
859
|
localLatestAddrsMap = resGetLatestAddrs.data.latestAddrsMap;
|
|
849
|
-
console.log(`${lc} [TEST DEBUG] localKV: ${JSON.stringify(localLatestAddrsMap)}`);
|
|
850
860
|
if (logalot) {
|
|
851
|
-
console.log(`${lc}
|
|
861
|
+
console.log(`${lc} [TEST DEBUG] localKnowledge: ${JSON.stringify(localLatestAddrsMap)}`);
|
|
862
|
+
}
|
|
863
|
+
if (logalot) {
|
|
864
|
+
console.log(`${lc} localKnowledge: ${pretty(localLatestAddrsMap)} (I: 980975642cbccd8018cf0cd808d30826)`);
|
|
852
865
|
}
|
|
853
866
|
}
|
|
854
867
|
// 2. Gap Analysis
|
|
855
868
|
for (const tjp of remoteTjps) {
|
|
856
|
-
const remoteAddr =
|
|
869
|
+
const remoteAddr = remoteKnowledge[tjp];
|
|
857
870
|
const localAddr = localLatestAddrsMap[tjp];
|
|
858
871
|
if (!localAddr) {
|
|
859
872
|
// We (Receiver) don't have this timeline at all. Request it.
|
|
860
|
-
|
|
873
|
+
if (logalot) {
|
|
874
|
+
console.log(`${lc} [TEST DEBUG] Missing local timeline for TJP: ${tjp}. Requesting remoteAddr: ${remoteAddr}`);
|
|
875
|
+
}
|
|
861
876
|
deltaRequestAddrInfos.push({
|
|
862
877
|
addr: remoteAddr,
|
|
863
878
|
tjpAddr: tjp,
|
|
@@ -869,10 +884,14 @@ export class SyncSagaCoordinator {
|
|
|
869
884
|
// we do have this timeline...
|
|
870
885
|
if (localAddr === remoteAddr) {
|
|
871
886
|
// ...already synced
|
|
872
|
-
|
|
887
|
+
if (logalot) {
|
|
888
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Synced (localAddr === remoteAddr)`);
|
|
889
|
+
}
|
|
873
890
|
continue;
|
|
874
891
|
}
|
|
875
|
-
|
|
892
|
+
if (logalot) {
|
|
893
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: localAddr=${localAddr}, remoteAddr=${remoteAddr} - checking for divergence...`);
|
|
894
|
+
}
|
|
876
895
|
// we have this timeline but it's not synced...
|
|
877
896
|
// We're executing on receiver. Check if Remote (Sender) is in
|
|
878
897
|
// our past, and if so, we are ahead and need to push the delta
|
|
@@ -885,7 +904,9 @@ export class SyncSagaCoordinator {
|
|
|
885
904
|
if (remoteIsInPast) {
|
|
886
905
|
// we're ahead, so push the delta of what the sender doesn't
|
|
887
906
|
// have (we have full knowledge)
|
|
888
|
-
|
|
907
|
+
if (logalot) {
|
|
908
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Remote (sender) is in past - offering push`);
|
|
909
|
+
}
|
|
889
910
|
const deltaGraph = await getDeltaDependencyGraph({
|
|
890
911
|
ibGibAddr: localAddr,
|
|
891
912
|
live: false, // always live: false right?
|
|
@@ -906,7 +927,6 @@ export class SyncSagaCoordinator {
|
|
|
906
927
|
*/
|
|
907
928
|
let localIsInPast = false;
|
|
908
929
|
try {
|
|
909
|
-
// we could
|
|
910
930
|
localIsInPast = await isPastFrame({
|
|
911
931
|
olderAddr: localAddr,
|
|
912
932
|
newerAddr: remoteAddr,
|
|
@@ -921,7 +941,9 @@ export class SyncSagaCoordinator {
|
|
|
921
941
|
}
|
|
922
942
|
if (localIsInPast) {
|
|
923
943
|
// Fast-Forward: We update to remote's tip.
|
|
924
|
-
|
|
944
|
+
if (logalot) {
|
|
945
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Local is in past - requesting delta`);
|
|
946
|
+
}
|
|
925
947
|
deltaRequestAddrInfos.push({
|
|
926
948
|
addr: remoteAddr,
|
|
927
949
|
tjpAddr: tjp,
|
|
@@ -930,7 +952,9 @@ export class SyncSagaCoordinator {
|
|
|
930
952
|
}
|
|
931
953
|
else {
|
|
932
954
|
// DIVERGENCE: Both have changes the other doesn't know about.
|
|
933
|
-
|
|
955
|
+
if (logalot) {
|
|
956
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: DIVERGENCE DETECTED! conflictStrategy=${conflictStrategy}`);
|
|
957
|
+
}
|
|
934
958
|
if (conflictStrategy === 'abort') {
|
|
935
959
|
// Abort Strategy: We will treat this as terminal.
|
|
936
960
|
// But for Unified Ack, we just mark it terminal in the list?
|
|
@@ -944,26 +968,23 @@ export class SyncSagaCoordinator {
|
|
|
944
968
|
reason: 'divergence',
|
|
945
969
|
terminal: true
|
|
946
970
|
});
|
|
971
|
+
// todo: create error saga frame for when aborting or other terminal error
|
|
947
972
|
}
|
|
948
973
|
else if (conflictStrategy === 'optimistic') {
|
|
949
974
|
// Optimistic: We want resolve this.
|
|
950
975
|
// We need to send our history to the Sender so they can Merge.
|
|
951
976
|
// Fetch Full History for Local Timeline
|
|
952
|
-
// Note: We might optimize this to only send "recent" history if we had a KV?
|
|
953
|
-
// But for now, get full past.
|
|
954
|
-
// Optimization: localKV might not have full history.
|
|
955
|
-
// We need to inspect the 'past' of the local tip.
|
|
956
|
-
// We need the ACTUAL object to get the past.
|
|
957
|
-
// We have localAddr.
|
|
958
977
|
const resLocalTip = await getFromSpace({ space: mySpace, addr: localAddr });
|
|
959
978
|
if (!resLocalTip.success || resLocalTip.ibGibs?.length !== 1) {
|
|
960
|
-
throw new Error(`couldn't get local tip (${localAddr}) from space (${mySpace.ib}) (E: 83cb88a767e22bbda99c6788bec50526)`);
|
|
979
|
+
throw new Error(`couldn't get local tip (${localAddr}) from space (${mySpace.ib}). errorMsg: ${resLocalTip.errorMsg ?? '[unknown error (E: b3c3d823276300aa384ebdba4a8eb826)]'} (E: 83cb88a767e22bbda99c6788bec50526)`);
|
|
961
980
|
}
|
|
962
981
|
const localTip = resLocalTip.ibGibs[0];
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
982
|
+
const pastAddrs = await getHistoryAddrs({
|
|
983
|
+
timeline: localTip,
|
|
984
|
+
space: mySpace,
|
|
985
|
+
metaspace,
|
|
986
|
+
});
|
|
987
|
+
const timelineAddrs = [...pastAddrs, localAddr];
|
|
967
988
|
conflicts.push({
|
|
968
989
|
tjpAddr: tjp,
|
|
969
990
|
localAddr,
|
|
@@ -1134,15 +1155,21 @@ export class SyncSagaCoordinator {
|
|
|
1134
1155
|
// #region sanity/validation
|
|
1135
1156
|
// 1. Check for Conflicts
|
|
1136
1157
|
const conflicts = ackData.conflicts || [];
|
|
1137
|
-
|
|
1138
|
-
|
|
1158
|
+
if (logalot) {
|
|
1159
|
+
console.log(`${lc} [CONFLICT DEBUG] Received conflicts from Ack: ${conflicts.length}`);
|
|
1160
|
+
}
|
|
1161
|
+
if (logalot && conflicts.length > 0) {
|
|
1139
1162
|
console.log(`${lc} [CONFLICT DEBUG] Conflicts detail: ${JSON.stringify(conflicts, null, 2)}`);
|
|
1140
1163
|
}
|
|
1141
1164
|
const terminalConflicts = conflicts.filter(c => c.terminal);
|
|
1142
1165
|
if (terminalConflicts.length > 0) {
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1166
|
+
if (logalot) {
|
|
1167
|
+
console.warn(`${lc} Received terminal conflicts from Ack: ${JSON.stringify(terminalConflicts)}`);
|
|
1168
|
+
}
|
|
1169
|
+
// Terminal failure. Sender should probably Commit(Fail) or just
|
|
1170
|
+
// Abort. For now, throw to trigger abort. the incoming ack
|
|
1171
|
+
// frame has already been persisted in local durable space by
|
|
1172
|
+
// now.
|
|
1146
1173
|
throw new Error(`${lc} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
|
|
1147
1174
|
}
|
|
1148
1175
|
// at this point, if we have conflicts, they are non-terminal
|
|
@@ -1153,7 +1180,9 @@ export class SyncSagaCoordinator {
|
|
|
1153
1180
|
*/
|
|
1154
1181
|
const outgoingDeltaAddrRequestInfos = []; // Additional requests for merging
|
|
1155
1182
|
if (conflicts.length > 0) {
|
|
1156
|
-
|
|
1183
|
+
if (logalot) {
|
|
1184
|
+
console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
|
|
1185
|
+
}
|
|
1157
1186
|
// We need to resolve these.
|
|
1158
1187
|
// Strategy:
|
|
1159
1188
|
// 1. Analyze Divergence (Sender vs Receiver)
|
|
@@ -1261,10 +1290,14 @@ export class SyncSagaCoordinator {
|
|
|
1261
1290
|
// console.log(`${lc} [CONFLICT DEBUG] No receiver-only frames found for this conflict`);
|
|
1262
1291
|
// }
|
|
1263
1292
|
}
|
|
1264
|
-
|
|
1293
|
+
if (logalot) {
|
|
1294
|
+
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingDeltaAddrRequestInfos: ${outgoingDeltaAddrRequestInfos.length}`);
|
|
1295
|
+
}
|
|
1265
1296
|
}
|
|
1266
1297
|
else {
|
|
1267
|
-
|
|
1298
|
+
if (logalot) {
|
|
1299
|
+
console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`);
|
|
1300
|
+
}
|
|
1268
1301
|
}
|
|
1269
1302
|
// 2. Prepare Delta Payload (What Receiver Requesting + Our Conflict Logic)
|
|
1270
1303
|
/**
|
|
@@ -1345,7 +1378,7 @@ export class SyncSagaCoordinator {
|
|
|
1345
1378
|
* 2. **Fulfillment**: Checks `requests`. If Peer requested data, gathers it and prepares `outgoingPayload`.
|
|
1346
1379
|
* 3. **Completion**: If no more requests, transitions to `Commit`.
|
|
1347
1380
|
*/
|
|
1348
|
-
async handleDeltaFrame({ sagaContext, sagaIbGib,
|
|
1381
|
+
async handleDeltaFrame({ sagaContext, sagaIbGib, mySpace, myTempSpace, metaspace, identity, }) {
|
|
1349
1382
|
const lc = `${this.lc}[${this.handleDeltaFrame.name}]`;
|
|
1350
1383
|
try {
|
|
1351
1384
|
if (logalot) {
|
|
@@ -1364,32 +1397,44 @@ export class SyncSagaCoordinator {
|
|
|
1364
1397
|
console.log(`${lc} deltaData: ${pretty(deltaData)} (I: a76008681df458cfbcdc4848f825a826)`);
|
|
1365
1398
|
}
|
|
1366
1399
|
// #endregion validate/sanity
|
|
1367
|
-
|
|
1400
|
+
if (logalot) {
|
|
1401
|
+
console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`);
|
|
1402
|
+
}
|
|
1368
1403
|
const peerProposesCommit = deltaData.proposeCommit || false;
|
|
1369
1404
|
/**
|
|
1370
1405
|
* these are already in the local temp space
|
|
1371
1406
|
*/
|
|
1372
1407
|
const receivedPayloadIbGibs = sagaContext.payloadIbGibsDomain ?? [];
|
|
1373
1408
|
// 2. Fulfill Peer Requests (Outgoing Payload with Delta Dependencies)
|
|
1374
|
-
|
|
1409
|
+
if (logalot) {
|
|
1410
|
+
console.log(`${lc} [CONFLICT DEBUG] Fulfilling ${(deltaData.deltaRequestAddrInfos || []).length} peer requests`);
|
|
1411
|
+
}
|
|
1375
1412
|
const outgoingPayload = await this.getPayloadsForRequestedInfos({
|
|
1376
1413
|
deltaRequestAddrInfos: deltaData.deltaRequestAddrInfos || [],
|
|
1377
1414
|
mySpace,
|
|
1378
1415
|
});
|
|
1379
|
-
|
|
1416
|
+
if (logalot) {
|
|
1417
|
+
console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`);
|
|
1418
|
+
}
|
|
1380
1419
|
// 3. Execute Merges (If applicable)
|
|
1381
1420
|
// Check if we have pending conflicts that we CAN resolve now that we have data.
|
|
1382
1421
|
// We look at the Saga History (Ack Frame) to find conflicts.
|
|
1383
1422
|
// Optimization: Do this only if we received payloads.
|
|
1384
1423
|
const mergeResultIbGibs = [];
|
|
1385
|
-
|
|
1424
|
+
if (logalot) {
|
|
1425
|
+
console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`);
|
|
1426
|
+
}
|
|
1386
1427
|
if (receivedPayloadIbGibs.length > 0) {
|
|
1387
|
-
|
|
1428
|
+
if (logalot) {
|
|
1429
|
+
console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`);
|
|
1430
|
+
}
|
|
1388
1431
|
// Find the Ack frame in history to get conflicts
|
|
1389
1432
|
// Optimization: Batch fetch history from `sagaIbGib.rel8ns.past`
|
|
1390
1433
|
// V1 timelines carry full history in `past`.
|
|
1391
1434
|
const pastAddrs = sagaIbGib.rel8ns?.past || [];
|
|
1392
|
-
|
|
1435
|
+
if (logalot) {
|
|
1436
|
+
console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`);
|
|
1437
|
+
}
|
|
1393
1438
|
const sagaHistory = await getFullSyncSagaHistory({
|
|
1394
1439
|
sagaIbGib,
|
|
1395
1440
|
space: mySpace,
|
|
@@ -1428,9 +1473,13 @@ export class SyncSagaCoordinator {
|
|
|
1428
1473
|
// We blindly attempt merge if we have both tips accessible?
|
|
1429
1474
|
// We need `receiverTip` (localAddr in Ack) and `senderTip` (remoteAddr).
|
|
1430
1475
|
// Check if we have receiverTip in space
|
|
1431
|
-
|
|
1476
|
+
if (logalot) {
|
|
1477
|
+
console.log(`${lc} [CONFLICT DEBUG] Attempting merge for conflict. ReceiverTip: ${receiverTip}, SenderTip: ${senderTip}`);
|
|
1478
|
+
}
|
|
1432
1479
|
const resRecTip = await getFromSpace({ addr: receiverTip, space: myTempSpace }); // Check myTempSpace for incoming data
|
|
1433
|
-
|
|
1480
|
+
if (logalot) {
|
|
1481
|
+
console.log(`${lc} [CONFLICT DEBUG] ReceiverTip found in myTempSpace: ${!!resRecTip.ibGibs?.[0]}`);
|
|
1482
|
+
}
|
|
1434
1483
|
if (resRecTip.success && resRecTip.ibGibs?.[0]) {
|
|
1435
1484
|
// We have the tip!
|
|
1436
1485
|
// Do we have the full history?
|
|
@@ -1445,7 +1494,9 @@ export class SyncSagaCoordinator {
|
|
|
1445
1494
|
metaspace,
|
|
1446
1495
|
});
|
|
1447
1496
|
if (mergeResult) {
|
|
1448
|
-
|
|
1497
|
+
if (logalot) {
|
|
1498
|
+
console.log(`${lc} [TEST DEBUG] Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1499
|
+
}
|
|
1449
1500
|
if (logalot) {
|
|
1450
1501
|
console.log(`${lc} Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1451
1502
|
}
|
|
@@ -1454,7 +1505,7 @@ export class SyncSagaCoordinator {
|
|
|
1454
1505
|
}
|
|
1455
1506
|
}
|
|
1456
1507
|
catch (e) {
|
|
1457
|
-
console.error(`${lc} Merge failed: ${e}`);
|
|
1508
|
+
console.error(`${lc} (NOT THROWN) Merge failed: ${e} (E: 491b464fc6f4857f52ff3df213105826)`);
|
|
1458
1509
|
// If merge fails, we might Abort or just continue?
|
|
1459
1510
|
}
|
|
1460
1511
|
}
|
|
@@ -1602,15 +1653,47 @@ export class SyncSagaCoordinator {
|
|
|
1602
1653
|
/**
|
|
1603
1654
|
* should throw if fails
|
|
1604
1655
|
*/
|
|
1605
|
-
async executeLocalCommit({ deltaFrame, sagaHistory, metaspace, localSpace, localTempSpace, identity, }) {
|
|
1656
|
+
async executeLocalCommit({ deltaFrame, commitFrame, sagaHistory, metaspace, localSpace, localTempSpace, identity, }) {
|
|
1606
1657
|
const lc = `${this.lc}[${this.executeLocalCommit.name}]`;
|
|
1607
1658
|
try {
|
|
1608
1659
|
if (logalot) {
|
|
1609
1660
|
console.log(`${lc} starting... (I: 6734980446b86a63c1af6e2e206de826)`);
|
|
1610
1661
|
}
|
|
1662
|
+
if (!deltaFrame && !commitFrame) {
|
|
1663
|
+
throw new Error(`(UNEXPECTED) !deltaFrame && !commitFrame? we're expecting to execute the commit based off of EITHER a delta OR a commit frame. (E: 10cae319a2685a672866f5583514e326)`);
|
|
1664
|
+
}
|
|
1665
|
+
else if (deltaFrame && commitFrame) {
|
|
1666
|
+
throw new Error(`(UNEXPECTED) deltaFrame && commitFrame? we're expecting to execute the commit based off of EITHER a delta OR a commit frame. (E: b9037b1ed6d8684ac8a5d01328bad826)`);
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Sync has a two-stage commit. The first is from a delta frame with
|
|
1670
|
+
* `proposeCommit: true`. That produces a commit frame, which on the
|
|
1671
|
+
* other end triggers the second leg.
|
|
1672
|
+
*/
|
|
1673
|
+
const isFirstCommitLeg = !!deltaFrame;
|
|
1674
|
+
const currentFrame = isFirstCommitLeg ? deltaFrame : commitFrame;
|
|
1675
|
+
if (!currentFrame) {
|
|
1676
|
+
throw new Error(`(UNEXPECTED) !currentFrame? something wrong with my logic. (E: 4ec0ce6625cc1d677bc902c839ca1a26)`);
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* we only want to register new ibgibs from the other end, so we
|
|
1680
|
+
* will compare the history payloads/push offers with the context
|
|
1681
|
+
* that provided those payloads.
|
|
1682
|
+
*
|
|
1683
|
+
* So we will filter out the history that we produced, which should
|
|
1684
|
+
* leave us only with externally created payload addrs.
|
|
1685
|
+
*
|
|
1686
|
+
* NOTE: I have this at the beginning of the function PURELY to get
|
|
1687
|
+
* a log value in to understand the context of this function's
|
|
1688
|
+
* output.
|
|
1689
|
+
*/
|
|
1690
|
+
const currentFrameOrigin = getSyncSagaFrameOrigin({ sagaFrame: currentFrame });
|
|
1691
|
+
if (logalot) {
|
|
1692
|
+
console.log(`${lc} currentFrameOrigin: ${currentFrameOrigin} (I: 3add8f8390c89743ae554bd3cc60b826)`);
|
|
1693
|
+
}
|
|
1611
1694
|
// #region validate/sanity
|
|
1612
|
-
if (!
|
|
1613
|
-
throw new Error(`(UNEXPECTED)
|
|
1695
|
+
if (!currentFrame.data) {
|
|
1696
|
+
throw new Error(`(UNEXPECTED) currentFrame.data falsy? (E: a8be68d48668d93d992d793834823826)`);
|
|
1614
1697
|
}
|
|
1615
1698
|
// #endregion validate/sanity
|
|
1616
1699
|
// * move all payload addrs from temp space to local space
|
|
@@ -1622,10 +1705,16 @@ export class SyncSagaCoordinator {
|
|
|
1622
1705
|
allPayloadAddrsDomainTransferred.push(addr);
|
|
1623
1706
|
}
|
|
1624
1707
|
};
|
|
1625
|
-
sagaHistory.
|
|
1708
|
+
sagaHistory.filter(x => {
|
|
1709
|
+
const frameExecutionContext = getSyncSagaFrameOrigin({ sagaFrame: x.sagaIbGib });
|
|
1710
|
+
return currentFrameOrigin === frameExecutionContext;
|
|
1711
|
+
}).forEach(x => {
|
|
1626
1712
|
if (!x.sagaIbGib.data) {
|
|
1627
1713
|
throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: 34d7f8cdee14717ce828878d98f89826)`);
|
|
1628
1714
|
}
|
|
1715
|
+
if (logalot) {
|
|
1716
|
+
console.log(`${lc}[${currentFrameOrigin}] history slice: ${pretty(x)} (I: e5a9436fb66b0df3183bd6d81be2ca26)`);
|
|
1717
|
+
}
|
|
1629
1718
|
x.msgStones.forEach(msgStone => {
|
|
1630
1719
|
if (!msgStone.data) {
|
|
1631
1720
|
throw new Error(`(UNEXPECTED) msgStone.data falsy? (E: 21406101f91847514cc759c8a7382f26)`);
|
|
@@ -1646,58 +1735,101 @@ export class SyncSagaCoordinator {
|
|
|
1646
1735
|
}
|
|
1647
1736
|
});
|
|
1648
1737
|
});
|
|
1738
|
+
if (logalot) {
|
|
1739
|
+
console.log(`${lc}[${currentFrameOrigin}] allPayloadAddrsDomainTransferred: ${allPayloadAddrsDomainTransferred.length > 0 ? allPayloadAddrsDomainTransferred.join(', ') : 'none'} (I: a1950eb3ca95bdc9ec18a4b8823e9826)`);
|
|
1740
|
+
}
|
|
1649
1741
|
// at this point, we have a list of ALL payload addrs retrieved.
|
|
1650
1742
|
let allPayloadIbGibsDomainTransferred = [];
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1743
|
+
if (allPayloadAddrsDomainTransferred.length > 0) {
|
|
1744
|
+
const resGetAllTransferred = await getFromSpace({ addrs: allPayloadAddrsDomainTransferred, space: localTempSpace });
|
|
1745
|
+
if (resGetAllTransferred.success && resGetAllTransferred.ibGibs && resGetAllTransferred.ibGibs.length === allPayloadAddrsDomainTransferred.length) {
|
|
1746
|
+
allPayloadIbGibsDomainTransferred = resGetAllTransferred.ibGibs.concat();
|
|
1747
|
+
}
|
|
1748
|
+
else {
|
|
1749
|
+
// errored out, gather info
|
|
1750
|
+
if (!resGetAllTransferred.rawResultIbGib) {
|
|
1751
|
+
throw new Error(`(UNEXPECTED) !resGetAllTransferred.rawResultIbGib falsy? (E: dc6cf8729668f4fbe8c024f887d97a26)`);
|
|
1752
|
+
}
|
|
1753
|
+
const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data;
|
|
1754
|
+
throw new Error(`(UNEXPECTED) we couldn't get all addrs transferred throughout the saga from the tempspace (${localTempSpace.ib})? addrsNotFound: ${addrsNotFound ?? []}. addrsErrored: ${addrsErrored ?? []}. errors: ${errors ?? []}(E: 222e341e634862b4d88ae7282584d826)`);
|
|
1659
1755
|
}
|
|
1660
|
-
const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data;
|
|
1661
|
-
throw new Error(`(UNEXPECTED) we couldn't get all addrs transferred throughout the saga from the tempspace (${localTempSpace.ib})? addrsNotFound: ${addrsNotFound ?? []}. addrsErrored: ${addrsErrored ?? []}. errors: ${errors ?? []}(E: 222e341e634862b4d88ae7282584d826)`);
|
|
1662
1756
|
}
|
|
1663
1757
|
// now we have all ibgibs transferred, first put them all the local space
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } = splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1669
|
-
// first register all non-tjp stones
|
|
1670
|
-
const nontjps = Object.values(mapWithoutTjps);
|
|
1671
|
-
for (const nontjp of nontjps) {
|
|
1672
|
-
await metaspace.registerNewIbGib({
|
|
1673
|
-
ibGib: nontjp,
|
|
1674
|
-
space: localSpace,
|
|
1675
|
-
});
|
|
1676
|
-
}
|
|
1677
|
-
// next register each timeline in order...
|
|
1678
|
-
// ...first the ones without dna...
|
|
1679
|
-
const timelinesByTjpAddr_NoDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
|
|
1680
|
-
const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
|
|
1681
|
-
for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
|
|
1682
|
-
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
1683
|
-
for (const ibGib of timelineIbGibs) {
|
|
1684
|
-
await metaspace.registerNewIbGib({
|
|
1685
|
-
ibGib,
|
|
1686
|
-
space: localSpace,
|
|
1687
|
-
});
|
|
1758
|
+
if (allPayloadIbGibsDomainTransferred.length === 0) {
|
|
1759
|
+
// nothing was synced
|
|
1760
|
+
if (logalot) {
|
|
1761
|
+
console.log(`${lc}[${currentFrameOrigin}] no changes on this end (I: fa30d18e83a87ee9e8487fbb5d632b26)`);
|
|
1688
1762
|
}
|
|
1689
1763
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1764
|
+
else {
|
|
1765
|
+
if (logalot) {
|
|
1766
|
+
console.log(`${lc}[${currentFrameOrigin}] ${allPayloadIbGibsDomainTransferred.length} changes detected (I: fa30d18e83a87ee9e8487fbb5d632b26)`);
|
|
1767
|
+
}
|
|
1768
|
+
if (logalot) {
|
|
1769
|
+
console.log(`${lc} put all into localSpace (${localSpace.ib}) starting... (I: d5e0d9870e380b61e80c729660058826)`);
|
|
1770
|
+
}
|
|
1771
|
+
const { payload_Dnas, payload_NonDnas } = await putInSpace_dnasThenNonDnas({
|
|
1772
|
+
ibGibs: allPayloadIbGibsDomainTransferred,
|
|
1773
|
+
space: localSpace
|
|
1774
|
+
});
|
|
1775
|
+
if (logalot) {
|
|
1776
|
+
console.log(`${lc} put all into localSpace (${localSpace.ib}) complete. (I: d5e0d9870e380b61e80c729660058826)`);
|
|
1777
|
+
}
|
|
1778
|
+
const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } = splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1779
|
+
// first register all non-tjp stones
|
|
1780
|
+
if (logalot) {
|
|
1781
|
+
console.log(`${lc} register mapWithoutTjps starting... (I: 2b84d8f8dda85adde88696d8419bf726)`);
|
|
1782
|
+
}
|
|
1783
|
+
const nontjps = Object.values(mapWithoutTjps);
|
|
1784
|
+
for (const nontjp of nontjps) {
|
|
1785
|
+
if (logalot) {
|
|
1786
|
+
console.log(`${lc} registering ${getIbGibAddr({ ibGib: nontjp })} (I: 4647b4f42d27cffe0fbfce8846755826)`);
|
|
1787
|
+
}
|
|
1696
1788
|
await metaspace.registerNewIbGib({
|
|
1697
|
-
ibGib,
|
|
1789
|
+
ibGib: nontjp,
|
|
1698
1790
|
space: localSpace,
|
|
1699
1791
|
});
|
|
1700
1792
|
}
|
|
1793
|
+
if (logalot) {
|
|
1794
|
+
console.log(`${lc} mapWithoutTjps complete. (I: 2b84d8f8dda85adde88696d8419bf726)`);
|
|
1795
|
+
}
|
|
1796
|
+
// next register each timeline in order...
|
|
1797
|
+
// ...first the ones without dna...
|
|
1798
|
+
if (logalot) {
|
|
1799
|
+
console.log(`${lc} register mapWithTjp_NoDna starting... (I: 96e648e4db382499b8bfaa1b37c24826)`);
|
|
1800
|
+
}
|
|
1801
|
+
const timelinesByTjpAddr_NoDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
|
|
1802
|
+
const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
|
|
1803
|
+
for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
|
|
1804
|
+
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
1805
|
+
for (const ibGib of timelineIbGibs) {
|
|
1806
|
+
await metaspace.registerNewIbGib({
|
|
1807
|
+
ibGib,
|
|
1808
|
+
space: localSpace,
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
if (logalot) {
|
|
1813
|
+
console.log(`${lc} register mapWithTjp_NoDna complete. (I: 96e648e4db382499b8bfaa1b37c24826)`);
|
|
1814
|
+
}
|
|
1815
|
+
// ...then the ones WITH dna.
|
|
1816
|
+
if (logalot) {
|
|
1817
|
+
console.log(`${lc} register mapWithTjp_YesDna starting... (I: d54a820e9442dee4681f6228a6795926)`);
|
|
1818
|
+
}
|
|
1819
|
+
const timelinesByTjpAddr_YesDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_YesDna) });
|
|
1820
|
+
const tjpAddrs_YesDna = Object.keys(timelinesByTjpAddr_YesDna);
|
|
1821
|
+
for (const tjpAddr_YesDna of tjpAddrs_YesDna) {
|
|
1822
|
+
const timelineIbGibs = timelinesByTjpAddr_YesDna[tjpAddr_YesDna];
|
|
1823
|
+
for (const ibGib of timelineIbGibs) {
|
|
1824
|
+
await metaspace.registerNewIbGib({
|
|
1825
|
+
ibGib,
|
|
1826
|
+
space: localSpace,
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
if (logalot) {
|
|
1831
|
+
console.log(`${lc} register mapWithTjp_YesDna complete. (I: d54a820e9442dee4681f6228a6795926)`);
|
|
1832
|
+
}
|
|
1701
1833
|
}
|
|
1702
1834
|
}
|
|
1703
1835
|
catch (error) {
|
|
@@ -1760,46 +1892,55 @@ export class SyncSagaCoordinator {
|
|
|
1760
1892
|
if (logalot) {
|
|
1761
1893
|
console.log(`${lc} starting... (I: e179573bdd881202f8ba3168da1c3826)`);
|
|
1762
1894
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
const
|
|
1895
|
+
if (!sagaIbGib.data) {
|
|
1896
|
+
throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: cbc31dbb7d28b5b8c8cddb510d7d2826)`);
|
|
1897
|
+
}
|
|
1898
|
+
if (sagaIbGib.data.errors && sagaIbGib.data.errors.length > 0) {
|
|
1899
|
+
// our saga errored out but we already committed the darn
|
|
1900
|
+
// changes previously
|
|
1901
|
+
throw new Error(`not implemented...saga errored out on other end but we've already committed our changes. we need to implement undoing our changes, i.e., rollback commit, which basically is deleting all the payloads that we already put in in our previous commit. (E: e8eb789e0c08f0b3cf93607cb73e9f26)`);
|
|
1902
|
+
}
|
|
1903
|
+
else {
|
|
1904
|
+
// Sender Logic (Finalizing):
|
|
1905
|
+
// If we are here, we received a Commit frame from the Peer.
|
|
1906
|
+
// This implies the Peer has successfully committed.
|
|
1907
|
+
// We should now:
|
|
1908
|
+
// 1. Validate (implicitly done by receiving valid frame)
|
|
1909
|
+
// 2. Perform our own cleanup (Temp -> Dest, if applicable)
|
|
1910
|
+
// 3. Return saga completion.
|
|
1911
|
+
// one last validate entire history ?
|
|
1912
|
+
const history = await getFullSyncSagaHistory({
|
|
1781
1913
|
sagaIbGib,
|
|
1914
|
+
space: mySpace,
|
|
1915
|
+
});
|
|
1916
|
+
const validationErrors = await validateFullSyncSagaHistory({
|
|
1917
|
+
history,
|
|
1918
|
+
});
|
|
1919
|
+
if (validationErrors.length > 0) {
|
|
1920
|
+
const errorCommitFrame = await this.createCommitFrame({
|
|
1921
|
+
sagaIbGib,
|
|
1922
|
+
metaspace,
|
|
1923
|
+
mySpace,
|
|
1924
|
+
identity,
|
|
1925
|
+
errors: validationErrors,
|
|
1926
|
+
});
|
|
1927
|
+
return { frame: errorCommitFrame, }; /* <<<< returns early */
|
|
1928
|
+
}
|
|
1929
|
+
await this.executeLocalCommit({
|
|
1930
|
+
commitFrame: sagaIbGib,
|
|
1931
|
+
sagaHistory: history,
|
|
1932
|
+
localSpace: mySpace,
|
|
1933
|
+
localTempSpace: myTempSpace,
|
|
1782
1934
|
metaspace,
|
|
1783
|
-
mySpace,
|
|
1784
|
-
identity,
|
|
1785
|
-
errors: validationErrors,
|
|
1786
1935
|
});
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
metaspace,
|
|
1795
|
-
});
|
|
1796
|
-
// todo: implement explicit cleanup logic here and in peer
|
|
1797
|
-
console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
|
|
1798
|
-
if (logalot) {
|
|
1799
|
-
console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`);
|
|
1936
|
+
// todo: implement explicit cleanup logic here and in peer
|
|
1937
|
+
console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
|
|
1938
|
+
if (logalot) {
|
|
1939
|
+
console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`);
|
|
1940
|
+
}
|
|
1941
|
+
// the holy grail!
|
|
1942
|
+
return { sagaComplete: true };
|
|
1800
1943
|
}
|
|
1801
|
-
// the holy grail!
|
|
1802
|
-
return { sagaComplete: true };
|
|
1803
1944
|
}
|
|
1804
1945
|
catch (error) {
|
|
1805
1946
|
const emsg = `${lc} ${extractErrorMsg(error)}`;
|