@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
|
@@ -23,17 +23,15 @@ import {
|
|
|
23
23
|
SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN,
|
|
24
24
|
} from "./sync-constants.mjs";
|
|
25
25
|
import {
|
|
26
|
-
appendToTimeline, createTimeline, Rel8nInfo, Rel8nRemovalInfo
|
|
26
|
+
appendToTimeline, createTimeline, getHistory, getHistoryAddrs, Rel8nInfo, Rel8nRemovalInfo
|
|
27
27
|
} from "../timeline/timeline-api.mjs";
|
|
28
28
|
import {
|
|
29
29
|
SyncData_V1, SyncIbGib_V1, SyncConflictStrategy, SyncMode, SyncOptions,
|
|
30
30
|
SyncRel8ns_V1, DomainIbGibAnalysisInfo, NextSagaFrameInfo,
|
|
31
31
|
SYNC_CONFLICT_STRATEGY_VALID_VALUES, HandleSagaResponseContextResult,
|
|
32
|
-
SyncExecutionContext,
|
|
33
|
-
SYNC_EXECUTION_CONTEXT_VALID_VALUES,
|
|
34
32
|
SyncSagaFrameDependencyGraph,
|
|
35
33
|
} from "./sync-types.mjs";
|
|
36
|
-
import {
|
|
34
|
+
import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
|
|
37
35
|
import { getDeltaDependencyGraph, getDependencyGraph, toFlatGraph } from "../common/other/graph-helper.mjs";
|
|
38
36
|
import {
|
|
39
37
|
SyncSagaMessageData_V1, SyncSagaMessageInitData_V1,
|
|
@@ -58,9 +56,8 @@ import { IbGibSpaceResultData, IbGibSpaceResultIbGib, IbGibSpaceResultRel8ns } f
|
|
|
58
56
|
import { FlatIbGibGraph } from "../common/other/graph-types.mjs";
|
|
59
57
|
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
const logalotControlDomain = true;
|
|
59
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
60
|
+
const logalotControlDomain = false;
|
|
64
61
|
const lcControlDomain = '[ControlDomain]';
|
|
65
62
|
|
|
66
63
|
/**
|
|
@@ -505,7 +502,11 @@ export class SyncSagaCoordinator {
|
|
|
505
502
|
});
|
|
506
503
|
|
|
507
504
|
if (!contextResult) {
|
|
508
|
-
|
|
505
|
+
// should this ever hit?
|
|
506
|
+
console.error(`${lc} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
|
|
507
|
+
break;
|
|
508
|
+
} else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
509
|
+
if (logalot) { console.log(`${lc} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`); }
|
|
509
510
|
break;
|
|
510
511
|
}
|
|
511
512
|
|
|
@@ -514,8 +515,6 @@ export class SyncSagaCoordinator {
|
|
|
514
515
|
throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: c948e81d513b2a0eb8b8afa878edc626)`);
|
|
515
516
|
} else if (!contextResult.nextFrameInfo) {
|
|
516
517
|
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
|
|
517
|
-
} else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
518
|
-
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo.sagaComplete? logic flow should not have gotten here. (E: 104a32381db816b7183435e805b3d626)`);
|
|
519
518
|
}
|
|
520
519
|
// #endregion error conditions throw
|
|
521
520
|
|
|
@@ -537,10 +536,10 @@ export class SyncSagaCoordinator {
|
|
|
537
536
|
}
|
|
538
537
|
|
|
539
538
|
/**
|
|
540
|
-
* Helper to get Knowledge
|
|
539
|
+
* Helper to get Knowledge Map for specific domain ibGibs or TJPs.
|
|
541
540
|
* Useful for testing and external validation.
|
|
542
541
|
*/
|
|
543
|
-
public async
|
|
542
|
+
public async getKnowledgeMap({
|
|
544
543
|
space,
|
|
545
544
|
metaspace,
|
|
546
545
|
domainIbGibs,
|
|
@@ -551,7 +550,7 @@ export class SyncSagaCoordinator {
|
|
|
551
550
|
domainIbGibs?: IbGib_V1[],
|
|
552
551
|
tjpAddrs?: string[],
|
|
553
552
|
}): Promise<{ [tjp: string]: string | null }> {
|
|
554
|
-
const lc = `${this.lc}[${this.
|
|
553
|
+
const lc = `${this.lc}[${this.getKnowledgeMap.name}]`;
|
|
555
554
|
try {
|
|
556
555
|
if (logalot) { console.log(`${lc} starting... (I: e184f8a7818666febfbbd2d841ed3826)`); }
|
|
557
556
|
// console.dir(space);
|
|
@@ -589,7 +588,7 @@ export class SyncSagaCoordinator {
|
|
|
589
588
|
} else {
|
|
590
589
|
// No info provided. Return empty? Or throw?
|
|
591
590
|
// User test context implied "everything", but implementation requires scope.
|
|
592
|
-
console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty
|
|
591
|
+
console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty Knowledge.`);
|
|
593
592
|
return {};
|
|
594
593
|
}
|
|
595
594
|
|
|
@@ -656,7 +655,7 @@ export class SyncSagaCoordinator {
|
|
|
656
655
|
* @remarks
|
|
657
656
|
* **Execution Context**: **Sender (Local)**.
|
|
658
657
|
*
|
|
659
|
-
* Generates the first frame containing the Knowledge
|
|
658
|
+
* Generates the first frame containing the Knowledge Map of the Local Space.
|
|
660
659
|
* This is sent to the Receiver to begin Gap Analysis.
|
|
661
660
|
*/
|
|
662
661
|
private async createInitFrame({
|
|
@@ -688,17 +687,17 @@ export class SyncSagaCoordinator {
|
|
|
688
687
|
// we need to store the fullGraph in our tempSpace for later...
|
|
689
688
|
await putInSpace({ ibGibs: Object.values(fullGraph), space: tempSpace });
|
|
690
689
|
|
|
691
|
-
// populate our knowledge
|
|
692
|
-
const
|
|
690
|
+
// populate our knowledge map with tjp -> latest addr/tip in timeline
|
|
691
|
+
const knowledgeMap: { [tjp: string]: IbGibAddr } = {};
|
|
693
692
|
Object.keys(srcTimelinesMap).forEach(tjp => {
|
|
694
693
|
const timeline = srcTimelinesMap[tjp];
|
|
695
694
|
const tip = timeline.at(-1)!;
|
|
696
|
-
|
|
695
|
+
knowledgeMap[tjp] = getIbGibAddr({ ibGib: tip });
|
|
697
696
|
});
|
|
698
697
|
const initData: SyncSagaMessageInitData_V1 = {
|
|
699
698
|
sagaId,
|
|
700
699
|
stage: SyncStage.init,
|
|
701
|
-
|
|
700
|
+
knowledgeMap: knowledgeMap,
|
|
702
701
|
identity: sessionIdentity, // KeystoneIbGib is already public data
|
|
703
702
|
mode: SyncMode.sync,
|
|
704
703
|
stones: srcStones.map(s => getIbGibAddr({ ibGib: s })),
|
|
@@ -816,16 +815,21 @@ export class SyncSagaCoordinator {
|
|
|
816
815
|
*
|
|
817
816
|
* ## 1. Sender
|
|
818
817
|
*
|
|
819
|
-
* On the sender, this is called within the
|
|
820
|
-
* initiates and drives the
|
|
818
|
+
* On the sender, this is called repeatedly within the the sync saga
|
|
819
|
+
* coordinator's {@link executeSagaLoop} which initiates and drives the
|
|
820
|
+
* overall sync process. This loop continues until there are no more frames
|
|
821
|
+
* to be exchanged between endpoints.
|
|
821
822
|
*
|
|
822
823
|
* ## 2. Receiver
|
|
823
824
|
*
|
|
824
|
-
* On the receiver, this is called directly
|
|
825
|
-
*
|
|
826
|
-
*
|
|
825
|
+
* On the receiver, this is called directly from {@link continueSync}, which
|
|
826
|
+
* itself is called either directly by the concrete sync peer or from within
|
|
827
|
+
* the receiving node endpoint. That endpoint's job is basically to get
|
|
828
|
+
* these things collocated and prepared to make this call.
|
|
827
829
|
*
|
|
828
|
-
*
|
|
830
|
+
* In contrast to the sender, this can be thought of as a one-off on the
|
|
831
|
+
* receiver, since the sender's {@link executeSagaLoop} is what actually
|
|
832
|
+
* drives the ping-pong process.
|
|
829
833
|
*/
|
|
830
834
|
private async handleResponseSagaContext({
|
|
831
835
|
sagaContext,
|
|
@@ -869,11 +873,6 @@ export class SyncSagaCoordinator {
|
|
|
869
873
|
|
|
870
874
|
if (logalot) { console.log(`${lc} handling frame stage: ${stage}`); }
|
|
871
875
|
|
|
872
|
-
/**
|
|
873
|
-
* don't like this name, need to refactor
|
|
874
|
-
*/
|
|
875
|
-
const srcGraph = toFlatGraph({ ibGibs: sagaContext.payloadIbGibsDomain }) ?? {};
|
|
876
|
-
|
|
877
876
|
let nextFrameInfo: NextSagaFrameInfo;
|
|
878
877
|
switch (stage) {
|
|
879
878
|
case SyncStage.init:
|
|
@@ -900,16 +899,18 @@ export class SyncSagaCoordinator {
|
|
|
900
899
|
nextFrameInfo = await this.handleDeltaFrame({
|
|
901
900
|
sagaContext,
|
|
902
901
|
sagaIbGib,
|
|
903
|
-
|
|
904
|
-
metaspace,
|
|
905
|
-
mySpace,
|
|
906
|
-
myTempSpace,
|
|
902
|
+
metaspace, mySpace, myTempSpace,
|
|
907
903
|
identity,
|
|
908
904
|
});
|
|
909
905
|
break;
|
|
910
906
|
|
|
911
907
|
case SyncStage.commit:
|
|
912
|
-
|
|
908
|
+
if (logalot) { console.log(`${lc}[${getSyncSagaFrameOrigin({ sagaFrame: sagaIbGib })}] mySpace.ib: ${mySpace.ib} (I: 5b270996d848907238d817fffa64a126)`); }
|
|
909
|
+
nextFrameInfo = await this.handleCommitFrame({
|
|
910
|
+
sagaIbGib,
|
|
911
|
+
metaspace, mySpace, myTempSpace,
|
|
912
|
+
identity,
|
|
913
|
+
});
|
|
913
914
|
break;
|
|
914
915
|
|
|
915
916
|
default:
|
|
@@ -938,7 +939,7 @@ export class SyncSagaCoordinator {
|
|
|
938
939
|
* **Execution Context**: **Receiver (Remote)**.
|
|
939
940
|
*
|
|
940
941
|
* The Receiver performs Gap Analysis here:
|
|
941
|
-
* 1. Compares Sender's Knowledge
|
|
942
|
+
* 1. Compares Sender's Knowledge Map (in `sagaIbGib`) vs Receiver's Local Knowledge Map.
|
|
942
943
|
* 2. Identifies what Sender needs (`pushOfferAddrs`).
|
|
943
944
|
* 3. Identifies what Receiver needs (`deltaRequestAddrInfos`).
|
|
944
945
|
* 4. Returns an `Ack` frame containing these lists.
|
|
@@ -973,7 +974,7 @@ export class SyncSagaCoordinator {
|
|
|
973
974
|
try {
|
|
974
975
|
if (logalot) { console.log(`${lc} starting... (I: 9d88dcad0408c029e898a4bcf3b08426)`); }
|
|
975
976
|
|
|
976
|
-
console.log(`${lc} [TEST DEBUG] Receiver mySpace: ${mySpace.ib}`);
|
|
977
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] Receiver mySpace: ${mySpace.ib}`); }
|
|
977
978
|
|
|
978
979
|
// Extract Init Data
|
|
979
980
|
const initData = messageData as SyncSagaMessageInitData_V1; // Using renamed variable for clarity
|
|
@@ -981,8 +982,8 @@ export class SyncSagaCoordinator {
|
|
|
981
982
|
throw new Error(`${lc} Invalid init frame: initData.stage !== SyncStage.init (E: c91be82970e4decc58f56bf8fc1ffc26)`);
|
|
982
983
|
}
|
|
983
984
|
// if (logalot) { console.log(`${lc} initData: ${pretty(initData)} (I: 46b0f8441b96ad7a388f1ce3239dd826)`); }
|
|
984
|
-
if (!initData || !initData.
|
|
985
|
-
throw new Error(`${lc} Invalid init frame: missing
|
|
985
|
+
if (!initData || !initData.knowledgeMap) {
|
|
986
|
+
throw new Error(`${lc} Invalid init frame: missing knowledgeMap (E: ed02c869e028d2d06841b9c7f80f2826)`);
|
|
986
987
|
}
|
|
987
988
|
|
|
988
989
|
// Determine Strategy from Saga Data (since V1 stores it in root)
|
|
@@ -1015,10 +1016,10 @@ export class SyncSagaCoordinator {
|
|
|
1015
1016
|
/**
|
|
1016
1017
|
* "remote" is sender in this case
|
|
1017
1018
|
*/
|
|
1018
|
-
const
|
|
1019
|
-
if (logalot) { console.log(`${lc}
|
|
1020
|
-
const remoteTjps = Object.keys(
|
|
1021
|
-
console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`);
|
|
1019
|
+
const remoteKnowledge = initData.knowledgeMap;
|
|
1020
|
+
if (logalot) { console.log(`${lc} remoteKnowledge: ${pretty(remoteKnowledge)} (I: 9f957862356dfeae183c200854e86e26)`); }
|
|
1021
|
+
const remoteTjps = Object.keys(remoteKnowledge);
|
|
1022
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`); }
|
|
1022
1023
|
if (logalot) { console.log(`${lc} remoteTjps: ${pretty(remoteTjps)} (I: 86ea4c53db0dc184c8b253386c402126)`); }
|
|
1023
1024
|
|
|
1024
1025
|
// 1. Get Local Latest Addrs for all TJPs
|
|
@@ -1032,18 +1033,18 @@ export class SyncSagaCoordinator {
|
|
|
1032
1033
|
if (!resGetLatestAddrs.data) { throw new Error(`(UNEXPECTED) resGetLatestAddrs.data falsy? (E: b180d813c088042b38e1e02e06a16926)`); }
|
|
1033
1034
|
if (!resGetLatestAddrs.data.latestAddrsMap) { throw new Error(`(UNEXPECTED) resGetLatestAddrs.data.latestAddrsMap falsy? (E: 16bc386dd51d0ff53a49620b1e641826)`); }
|
|
1034
1035
|
localLatestAddrsMap = resGetLatestAddrs.data.latestAddrsMap;
|
|
1035
|
-
console.log(`${lc} [TEST DEBUG]
|
|
1036
|
-
if (logalot) { console.log(`${lc}
|
|
1036
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] localKnowledge: ${JSON.stringify(localLatestAddrsMap)}`); }
|
|
1037
|
+
if (logalot) { console.log(`${lc} localKnowledge: ${pretty(localLatestAddrsMap)} (I: 980975642cbccd8018cf0cd808d30826)`); }
|
|
1037
1038
|
}
|
|
1038
1039
|
|
|
1039
1040
|
// 2. Gap Analysis
|
|
1040
1041
|
for (const tjp of remoteTjps) {
|
|
1041
|
-
const remoteAddr =
|
|
1042
|
+
const remoteAddr = remoteKnowledge[tjp];
|
|
1042
1043
|
const localAddr = localLatestAddrsMap[tjp];
|
|
1043
1044
|
|
|
1044
1045
|
if (!localAddr) {
|
|
1045
1046
|
// We (Receiver) don't have this timeline at all. Request it.
|
|
1046
|
-
console.log(`${lc} [TEST DEBUG] Missing local timeline for TJP: ${tjp}. Requesting remoteAddr: ${remoteAddr}`);
|
|
1047
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] Missing local timeline for TJP: ${tjp}. Requesting remoteAddr: ${remoteAddr}`); }
|
|
1047
1048
|
deltaRequestAddrInfos.push({
|
|
1048
1049
|
addr: remoteAddr,
|
|
1049
1050
|
tjpAddr: tjp,
|
|
@@ -1057,10 +1058,10 @@ export class SyncSagaCoordinator {
|
|
|
1057
1058
|
|
|
1058
1059
|
if (localAddr === remoteAddr) {
|
|
1059
1060
|
// ...already synced
|
|
1060
|
-
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Synced (localAddr === remoteAddr)`);
|
|
1061
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Synced (localAddr === remoteAddr)`); }
|
|
1061
1062
|
continue;
|
|
1062
1063
|
}
|
|
1063
|
-
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: localAddr=${localAddr}, remoteAddr=${remoteAddr} - checking for divergence...`);
|
|
1064
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] TJP ${tjp}: localAddr=${localAddr}, remoteAddr=${remoteAddr} - checking for divergence...`); }
|
|
1064
1065
|
|
|
1065
1066
|
// we have this timeline but it's not synced...
|
|
1066
1067
|
|
|
@@ -1076,7 +1077,7 @@ export class SyncSagaCoordinator {
|
|
|
1076
1077
|
if (remoteIsInPast) {
|
|
1077
1078
|
// we're ahead, so push the delta of what the sender doesn't
|
|
1078
1079
|
// have (we have full knowledge)
|
|
1079
|
-
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Remote (sender) is in past - offering push`);
|
|
1080
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Remote (sender) is in past - offering push`); }
|
|
1080
1081
|
const deltaGraph = await getDeltaDependencyGraph({
|
|
1081
1082
|
ibGibAddr: localAddr,
|
|
1082
1083
|
live: false, // always live: false right?
|
|
@@ -1097,7 +1098,6 @@ export class SyncSagaCoordinator {
|
|
|
1097
1098
|
*/
|
|
1098
1099
|
let localIsInPast = false;
|
|
1099
1100
|
try {
|
|
1100
|
-
// we could
|
|
1101
1101
|
localIsInPast = await isPastFrame({
|
|
1102
1102
|
olderAddr: localAddr,
|
|
1103
1103
|
newerAddr: remoteAddr,
|
|
@@ -1110,7 +1110,7 @@ export class SyncSagaCoordinator {
|
|
|
1110
1110
|
|
|
1111
1111
|
if (localIsInPast) {
|
|
1112
1112
|
// Fast-Forward: We update to remote's tip.
|
|
1113
|
-
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Local is in past - requesting delta`);
|
|
1113
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Local is in past - requesting delta`); }
|
|
1114
1114
|
deltaRequestAddrInfos.push({
|
|
1115
1115
|
addr: remoteAddr,
|
|
1116
1116
|
tjpAddr: tjp,
|
|
@@ -1118,7 +1118,7 @@ export class SyncSagaCoordinator {
|
|
|
1118
1118
|
});
|
|
1119
1119
|
} else {
|
|
1120
1120
|
// DIVERGENCE: Both have changes the other doesn't know about.
|
|
1121
|
-
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: DIVERGENCE DETECTED! conflictStrategy=${conflictStrategy}`);
|
|
1121
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] TJP ${tjp}: DIVERGENCE DETECTED! conflictStrategy=${conflictStrategy}`); }
|
|
1122
1122
|
|
|
1123
1123
|
if (conflictStrategy === 'abort') {
|
|
1124
1124
|
// Abort Strategy: We will treat this as terminal.
|
|
@@ -1133,27 +1133,23 @@ export class SyncSagaCoordinator {
|
|
|
1133
1133
|
reason: 'divergence',
|
|
1134
1134
|
terminal: true
|
|
1135
1135
|
});
|
|
1136
|
+
// todo: create error saga frame for when aborting or other terminal error
|
|
1136
1137
|
} else if (conflictStrategy === 'optimistic') {
|
|
1137
1138
|
// Optimistic: We want resolve this.
|
|
1138
1139
|
// We need to send our history to the Sender so they can Merge.
|
|
1139
1140
|
|
|
1140
1141
|
// Fetch Full History for Local Timeline
|
|
1141
|
-
// Note: We might optimize this to only send "recent" history if we had a KV?
|
|
1142
|
-
// But for now, get full past.
|
|
1143
|
-
// Optimization: localKV might not have full history.
|
|
1144
|
-
// We need to inspect the 'past' of the local tip.
|
|
1145
|
-
|
|
1146
|
-
// We need the ACTUAL object to get the past.
|
|
1147
|
-
// We have localAddr.
|
|
1148
1142
|
const resLocalTip = await getFromSpace({ space: mySpace, addr: localAddr });
|
|
1149
1143
|
if (!resLocalTip.success || resLocalTip.ibGibs?.length !== 1) {
|
|
1150
|
-
throw new Error(`couldn't get local tip (${localAddr}) from space (${mySpace.ib}) (E: 83cb88a767e22bbda99c6788bec50526)`);
|
|
1144
|
+
throw new Error(`couldn't get local tip (${localAddr}) from space (${mySpace.ib}). errorMsg: ${resLocalTip.errorMsg ?? '[unknown error (E: b3c3d823276300aa384ebdba4a8eb826)]'} (E: 83cb88a767e22bbda99c6788bec50526)`);
|
|
1151
1145
|
}
|
|
1152
1146
|
const localTip = resLocalTip.ibGibs[0];
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1147
|
+
const pastAddrs = await getHistoryAddrs({
|
|
1148
|
+
timeline: localTip,
|
|
1149
|
+
space: mySpace,
|
|
1150
|
+
metaspace,
|
|
1151
|
+
});
|
|
1152
|
+
const timelineAddrs = [...pastAddrs, localAddr];
|
|
1157
1153
|
conflicts.push({
|
|
1158
1154
|
tjpAddr: tjp,
|
|
1159
1155
|
localAddr,
|
|
@@ -1339,16 +1335,18 @@ export class SyncSagaCoordinator {
|
|
|
1339
1335
|
|
|
1340
1336
|
// 1. Check for Conflicts
|
|
1341
1337
|
const conflicts = ackData.conflicts || [];
|
|
1342
|
-
console.log(`${lc} [CONFLICT DEBUG] Received conflicts from Ack: ${conflicts.length}`);
|
|
1343
|
-
if (conflicts.length > 0) {
|
|
1338
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Received conflicts from Ack: ${conflicts.length}`); }
|
|
1339
|
+
if (logalot && conflicts.length > 0) {
|
|
1344
1340
|
console.log(`${lc} [CONFLICT DEBUG] Conflicts detail: ${JSON.stringify(conflicts, null, 2)}`);
|
|
1345
1341
|
}
|
|
1346
1342
|
|
|
1347
1343
|
const terminalConflicts = conflicts.filter(c => c.terminal);
|
|
1348
1344
|
if (terminalConflicts.length > 0) {
|
|
1349
|
-
console.warn(`${lc} Received terminal conflicts from Ack: ${JSON.stringify(terminalConflicts)}`);
|
|
1350
|
-
// Terminal failure. Sender should probably Commit(Fail) or just
|
|
1351
|
-
// For now, throw to trigger abort.
|
|
1345
|
+
if (logalot) { console.warn(`${lc} Received terminal conflicts from Ack: ${JSON.stringify(terminalConflicts)}`); }
|
|
1346
|
+
// Terminal failure. Sender should probably Commit(Fail) or just
|
|
1347
|
+
// Abort. For now, throw to trigger abort. the incoming ack
|
|
1348
|
+
// frame has already been persisted in local durable space by
|
|
1349
|
+
// now.
|
|
1352
1350
|
throw new Error(`${lc} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
|
|
1353
1351
|
}
|
|
1354
1352
|
|
|
@@ -1362,7 +1360,7 @@ export class SyncSagaCoordinator {
|
|
|
1362
1360
|
const outgoingDeltaAddrRequestInfos: SyncSagaRequestAddrInfo[] = []; // Additional requests for merging
|
|
1363
1361
|
|
|
1364
1362
|
if (conflicts.length > 0) {
|
|
1365
|
-
console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
|
|
1363
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`); }
|
|
1366
1364
|
// We need to resolve these.
|
|
1367
1365
|
// Strategy:
|
|
1368
1366
|
// 1. Analyze Divergence (Sender vs Receiver)
|
|
@@ -1495,9 +1493,9 @@ export class SyncSagaCoordinator {
|
|
|
1495
1493
|
// }
|
|
1496
1494
|
}
|
|
1497
1495
|
|
|
1498
|
-
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingDeltaAddrRequestInfos: ${outgoingDeltaAddrRequestInfos.length}`);
|
|
1496
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingDeltaAddrRequestInfos: ${outgoingDeltaAddrRequestInfos.length}`); }
|
|
1499
1497
|
} else {
|
|
1500
|
-
console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`);
|
|
1498
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`); }
|
|
1501
1499
|
}
|
|
1502
1500
|
|
|
1503
1501
|
// 2. Prepare Delta Payload (What Receiver Requesting + Our Conflict Logic)
|
|
@@ -1581,7 +1579,6 @@ export class SyncSagaCoordinator {
|
|
|
1581
1579
|
private async handleDeltaFrame({
|
|
1582
1580
|
sagaContext,
|
|
1583
1581
|
sagaIbGib,
|
|
1584
|
-
srcGraph,
|
|
1585
1582
|
mySpace,
|
|
1586
1583
|
myTempSpace,
|
|
1587
1584
|
metaspace,
|
|
@@ -1589,7 +1586,6 @@ export class SyncSagaCoordinator {
|
|
|
1589
1586
|
}: {
|
|
1590
1587
|
sagaContext: SyncSagaContextIbGib_V1,
|
|
1591
1588
|
sagaIbGib: SyncIbGib_V1,
|
|
1592
|
-
srcGraph: { [addr: string]: IbGib_V1 },
|
|
1593
1589
|
mySpace: IbGibSpaceAny,
|
|
1594
1590
|
myTempSpace: IbGibSpaceAny,
|
|
1595
1591
|
metaspace: MetaspaceService,
|
|
@@ -1608,7 +1604,7 @@ export class SyncSagaCoordinator {
|
|
|
1608
1604
|
if (logalot) { console.log(`${lc} deltaData: ${pretty(deltaData)} (I: a76008681df458cfbcdc4848f825a826)`); }
|
|
1609
1605
|
// #endregion validate/sanity
|
|
1610
1606
|
|
|
1611
|
-
console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`);
|
|
1607
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`); }
|
|
1612
1608
|
|
|
1613
1609
|
const peerProposesCommit = deltaData.proposeCommit || false;
|
|
1614
1610
|
|
|
@@ -1618,12 +1614,12 @@ export class SyncSagaCoordinator {
|
|
|
1618
1614
|
const receivedPayloadIbGibs: IbGib_V1[] = sagaContext.payloadIbGibsDomain ?? [];
|
|
1619
1615
|
|
|
1620
1616
|
// 2. Fulfill Peer Requests (Outgoing Payload with Delta Dependencies)
|
|
1621
|
-
console.log(`${lc} [CONFLICT DEBUG] Fulfilling ${(deltaData.deltaRequestAddrInfos || []).length} peer requests`);
|
|
1617
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Fulfilling ${(deltaData.deltaRequestAddrInfos || []).length} peer requests`); }
|
|
1622
1618
|
const outgoingPayload = await this.getPayloadsForRequestedInfos({
|
|
1623
1619
|
deltaRequestAddrInfos: deltaData.deltaRequestAddrInfos || [],
|
|
1624
1620
|
mySpace,
|
|
1625
1621
|
});
|
|
1626
|
-
console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`);
|
|
1622
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`); }
|
|
1627
1623
|
|
|
1628
1624
|
// 3. Execute Merges (If applicable)
|
|
1629
1625
|
// Check if we have pending conflicts that we CAN resolve now that we have data.
|
|
@@ -1631,15 +1627,15 @@ export class SyncSagaCoordinator {
|
|
|
1631
1627
|
// Optimization: Do this only if we received payloads.
|
|
1632
1628
|
const mergeResultIbGibs: IbGib_V1[] = [];
|
|
1633
1629
|
|
|
1634
|
-
console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`);
|
|
1630
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`); }
|
|
1635
1631
|
|
|
1636
1632
|
if (receivedPayloadIbGibs.length > 0) {
|
|
1637
|
-
console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`);
|
|
1633
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`); }
|
|
1638
1634
|
// Find the Ack frame in history to get conflicts
|
|
1639
1635
|
// Optimization: Batch fetch history from `sagaIbGib.rel8ns.past`
|
|
1640
1636
|
// V1 timelines carry full history in `past`.
|
|
1641
1637
|
const pastAddrs = sagaIbGib.rel8ns?.past || [];
|
|
1642
|
-
console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`);
|
|
1638
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`); }
|
|
1643
1639
|
|
|
1644
1640
|
const sagaHistory = await getFullSyncSagaHistory({
|
|
1645
1641
|
sagaIbGib,
|
|
@@ -1679,9 +1675,9 @@ export class SyncSagaCoordinator {
|
|
|
1679
1675
|
// We need `receiverTip` (localAddr in Ack) and `senderTip` (remoteAddr).
|
|
1680
1676
|
|
|
1681
1677
|
// Check if we have receiverTip in space
|
|
1682
|
-
console.log(`${lc} [CONFLICT DEBUG] Attempting merge for conflict. ReceiverTip: ${receiverTip}, SenderTip: ${senderTip}`);
|
|
1678
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] Attempting merge for conflict. ReceiverTip: ${receiverTip}, SenderTip: ${senderTip}`); }
|
|
1683
1679
|
const resRecTip = await getFromSpace({ addr: receiverTip, space: myTempSpace }); // Check myTempSpace for incoming data
|
|
1684
|
-
console.log(`${lc} [CONFLICT DEBUG] ReceiverTip found in myTempSpace: ${!!resRecTip.ibGibs?.[0]}`);
|
|
1680
|
+
if (logalot) { console.log(`${lc} [CONFLICT DEBUG] ReceiverTip found in myTempSpace: ${!!resRecTip.ibGibs?.[0]}`); }
|
|
1685
1681
|
if (resRecTip.success && resRecTip.ibGibs?.[0]) {
|
|
1686
1682
|
// We have the tip!
|
|
1687
1683
|
// Do we have the full history?
|
|
@@ -1697,13 +1693,13 @@ export class SyncSagaCoordinator {
|
|
|
1697
1693
|
metaspace,
|
|
1698
1694
|
});
|
|
1699
1695
|
if (mergeResult) {
|
|
1700
|
-
console.log(`${lc} [TEST DEBUG] Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1696
|
+
if (logalot) { console.log(`${lc} [TEST DEBUG] Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`); }
|
|
1701
1697
|
if (logalot) { console.log(`${lc} Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`); }
|
|
1702
1698
|
mergeResultIbGibs.push(mergeResult);
|
|
1703
1699
|
outgoingPayload.push(mergeResult); // Send result to peer
|
|
1704
1700
|
}
|
|
1705
1701
|
} catch (e) {
|
|
1706
|
-
console.error(`${lc} Merge failed: ${e}`);
|
|
1702
|
+
console.error(`${lc} (NOT THROWN) Merge failed: ${e} (E: 491b464fc6f4857f52ff3df213105826)`);
|
|
1707
1703
|
// If merge fails, we might Abort or just continue?
|
|
1708
1704
|
}
|
|
1709
1705
|
}
|
|
@@ -1864,11 +1860,13 @@ export class SyncSagaCoordinator {
|
|
|
1864
1860
|
*/
|
|
1865
1861
|
private async executeLocalCommit({
|
|
1866
1862
|
deltaFrame,
|
|
1863
|
+
commitFrame,
|
|
1867
1864
|
sagaHistory,
|
|
1868
1865
|
metaspace, localSpace, localTempSpace,
|
|
1869
1866
|
identity,
|
|
1870
1867
|
}: {
|
|
1871
|
-
deltaFrame
|
|
1868
|
+
deltaFrame?: SyncIbGib_V1;
|
|
1869
|
+
commitFrame?: SyncIbGib_V1;
|
|
1872
1870
|
sagaHistory: SyncSagaFrameDependencyGraph[];
|
|
1873
1871
|
metaspace: MetaspaceService;
|
|
1874
1872
|
localSpace: IbGibSpaceAny;
|
|
@@ -1878,9 +1876,39 @@ export class SyncSagaCoordinator {
|
|
|
1878
1876
|
const lc = `${this.lc}[${this.executeLocalCommit.name}]`;
|
|
1879
1877
|
try {
|
|
1880
1878
|
if (logalot) { console.log(`${lc} starting... (I: 6734980446b86a63c1af6e2e206de826)`); }
|
|
1879
|
+
if (!deltaFrame && !commitFrame) {
|
|
1880
|
+
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)`);
|
|
1881
|
+
} else if (deltaFrame && commitFrame) {
|
|
1882
|
+
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)`);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
/**
|
|
1886
|
+
* Sync has a two-stage commit. The first is from a delta frame with
|
|
1887
|
+
* `proposeCommit: true`. That produces a commit frame, which on the
|
|
1888
|
+
* other end triggers the second leg.
|
|
1889
|
+
*/
|
|
1890
|
+
const isFirstCommitLeg = !!deltaFrame;
|
|
1891
|
+
const currentFrame = isFirstCommitLeg ? deltaFrame : commitFrame;
|
|
1892
|
+
if (!currentFrame) { throw new Error(`(UNEXPECTED) !currentFrame? something wrong with my logic. (E: 4ec0ce6625cc1d677bc902c839ca1a26)`); }
|
|
1893
|
+
|
|
1894
|
+
/**
|
|
1895
|
+
* we only want to register new ibgibs from the other end, so we
|
|
1896
|
+
* will compare the history payloads/push offers with the context
|
|
1897
|
+
* that provided those payloads.
|
|
1898
|
+
*
|
|
1899
|
+
* So we will filter out the history that we produced, which should
|
|
1900
|
+
* leave us only with externally created payload addrs.
|
|
1901
|
+
*
|
|
1902
|
+
* NOTE: I have this at the beginning of the function PURELY to get
|
|
1903
|
+
* a log value in to understand the context of this function's
|
|
1904
|
+
* output.
|
|
1905
|
+
*/
|
|
1906
|
+
const currentFrameOrigin = getSyncSagaFrameOrigin({ sagaFrame: currentFrame });
|
|
1907
|
+
|
|
1908
|
+
if (logalot) { console.log(`${lc} currentFrameOrigin: ${currentFrameOrigin} (I: 3add8f8390c89743ae554bd3cc60b826)`); }
|
|
1881
1909
|
|
|
1882
1910
|
// #region validate/sanity
|
|
1883
|
-
if (!
|
|
1911
|
+
if (!currentFrame.data) { throw new Error(`(UNEXPECTED) currentFrame.data falsy? (E: a8be68d48668d93d992d793834823826)`); }
|
|
1884
1912
|
// #endregion validate/sanity
|
|
1885
1913
|
|
|
1886
1914
|
// * move all payload addrs from temp space to local space
|
|
@@ -1894,8 +1922,12 @@ export class SyncSagaCoordinator {
|
|
|
1894
1922
|
}
|
|
1895
1923
|
}
|
|
1896
1924
|
|
|
1897
|
-
sagaHistory.
|
|
1925
|
+
sagaHistory.filter(x => {
|
|
1926
|
+
const frameExecutionContext = getSyncSagaFrameOrigin({ sagaFrame: x.sagaIbGib });
|
|
1927
|
+
return currentFrameOrigin === frameExecutionContext;
|
|
1928
|
+
}).forEach(x => {
|
|
1898
1929
|
if (!x.sagaIbGib.data) { throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: 34d7f8cdee14717ce828878d98f89826)`); }
|
|
1930
|
+
if (logalot) { console.log(`${lc}[${currentFrameOrigin}] history slice: ${pretty(x)} (I: e5a9436fb66b0df3183bd6d81be2ca26)`); }
|
|
1899
1931
|
x.msgStones.forEach(msgStone => {
|
|
1900
1932
|
if (!msgStone.data) { throw new Error(`(UNEXPECTED) msgStone.data falsy? (E: 21406101f91847514cc759c8a7382f26)`); }
|
|
1901
1933
|
if (msgStone.data.stage === SyncStage.ack) {
|
|
@@ -1914,70 +1946,90 @@ export class SyncSagaCoordinator {
|
|
|
1914
1946
|
})
|
|
1915
1947
|
});
|
|
1916
1948
|
|
|
1949
|
+
if (logalot) { console.log(`${lc}[${currentFrameOrigin}] allPayloadAddrsDomainTransferred: ${allPayloadAddrsDomainTransferred.length > 0 ? allPayloadAddrsDomainTransferred.join(', ') : 'none'} (I: a1950eb3ca95bdc9ec18a4b8823e9826)`); }
|
|
1950
|
+
|
|
1917
1951
|
// at this point, we have a list of ALL payload addrs retrieved.
|
|
1918
1952
|
let allPayloadIbGibsDomainTransferred: IbGib_V1[] = [];
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1953
|
+
if (allPayloadAddrsDomainTransferred.length > 0) {
|
|
1954
|
+
const resGetAllTransferred =
|
|
1955
|
+
await getFromSpace({ addrs: allPayloadAddrsDomainTransferred, space: localTempSpace });
|
|
1956
|
+
if (resGetAllTransferred.success && resGetAllTransferred.ibGibs && resGetAllTransferred.ibGibs.length === allPayloadAddrsDomainTransferred.length) {
|
|
1957
|
+
allPayloadIbGibsDomainTransferred = resGetAllTransferred.ibGibs.concat();
|
|
1958
|
+
} else {
|
|
1959
|
+
// errored out, gather info
|
|
1960
|
+
if (!resGetAllTransferred.rawResultIbGib) { throw new Error(`(UNEXPECTED) !resGetAllTransferred.rawResultIbGib falsy? (E: dc6cf8729668f4fbe8c024f887d97a26)`); }
|
|
1961
|
+
const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data as IbGibSpaceResultData;
|
|
1962
|
+
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)`);
|
|
1963
|
+
}
|
|
1928
1964
|
}
|
|
1929
1965
|
|
|
1930
1966
|
// now we have all ibgibs transferred, first put them all the local space
|
|
1967
|
+
if (allPayloadIbGibsDomainTransferred.length === 0) {
|
|
1968
|
+
// nothing was synced
|
|
1969
|
+
if (logalot) { console.log(`${lc}[${currentFrameOrigin}] no changes on this end (I: fa30d18e83a87ee9e8487fbb5d632b26)`); }
|
|
1970
|
+
} else {
|
|
1971
|
+
if (logalot) { console.log(`${lc}[${currentFrameOrigin}] ${allPayloadIbGibsDomainTransferred.length} changes detected (I: fa30d18e83a87ee9e8487fbb5d632b26)`); }
|
|
1931
1972
|
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1940
|
-
|
|
1941
|
-
// first register all non-tjp stones
|
|
1942
|
-
const nontjps = Object.values(mapWithoutTjps);
|
|
1943
|
-
for (const nontjp of nontjps) {
|
|
1944
|
-
await metaspace.registerNewIbGib({
|
|
1945
|
-
ibGib: nontjp,
|
|
1946
|
-
space: localSpace,
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1973
|
+
if (logalot) { console.log(`${lc} put all into localSpace (${localSpace.ib}) starting... (I: d5e0d9870e380b61e80c729660058826)`); }
|
|
1974
|
+
const { payload_Dnas, payload_NonDnas } =
|
|
1975
|
+
await putInSpace_dnasThenNonDnas({
|
|
1976
|
+
ibGibs: allPayloadIbGibsDomainTransferred,
|
|
1977
|
+
space: localSpace
|
|
1978
|
+
});
|
|
1979
|
+
if (logalot) { console.log(`${lc} put all into localSpace (${localSpace.ib}) complete. (I: d5e0d9870e380b61e80c729660058826)`); }
|
|
1949
1980
|
|
|
1950
|
-
|
|
1981
|
+
const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } =
|
|
1982
|
+
splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1951
1983
|
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
1958
|
-
for (const ibGib of timelineIbGibs) {
|
|
1984
|
+
// first register all non-tjp stones
|
|
1985
|
+
if (logalot) { console.log(`${lc} register mapWithoutTjps starting... (I: 2b84d8f8dda85adde88696d8419bf726)`); }
|
|
1986
|
+
const nontjps = Object.values(mapWithoutTjps);
|
|
1987
|
+
for (const nontjp of nontjps) {
|
|
1988
|
+
if (logalot) { console.log(`${lc} registering ${getIbGibAddr({ ibGib: nontjp })} (I: 4647b4f42d27cffe0fbfce8846755826)`); }
|
|
1959
1989
|
await metaspace.registerNewIbGib({
|
|
1960
|
-
ibGib,
|
|
1990
|
+
ibGib: nontjp,
|
|
1961
1991
|
space: localSpace,
|
|
1962
1992
|
});
|
|
1963
1993
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1994
|
+
if (logalot) { console.log(`${lc} mapWithoutTjps complete. (I: 2b84d8f8dda85adde88696d8419bf726)`); }
|
|
1995
|
+
|
|
1996
|
+
// next register each timeline in order...
|
|
1997
|
+
|
|
1998
|
+
// ...first the ones without dna...
|
|
1999
|
+
if (logalot) { console.log(`${lc} register mapWithTjp_NoDna starting... (I: 96e648e4db382499b8bfaa1b37c24826)`); }
|
|
2000
|
+
const timelinesByTjpAddr_NoDna =
|
|
2001
|
+
getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
|
|
2002
|
+
const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
|
|
2003
|
+
for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
|
|
2004
|
+
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
2005
|
+
for (const ibGib of timelineIbGibs) {
|
|
2006
|
+
await metaspace.registerNewIbGib({
|
|
2007
|
+
ibGib,
|
|
2008
|
+
space: localSpace,
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
1977
2011
|
}
|
|
2012
|
+
if (logalot) { console.log(`${lc} register mapWithTjp_NoDna complete. (I: 96e648e4db382499b8bfaa1b37c24826)`); }
|
|
2013
|
+
|
|
2014
|
+
// ...then the ones WITH dna.
|
|
2015
|
+
if (logalot) { console.log(`${lc} register mapWithTjp_YesDna starting... (I: d54a820e9442dee4681f6228a6795926)`); }
|
|
2016
|
+
const timelinesByTjpAddr_YesDna =
|
|
2017
|
+
getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_YesDna) });
|
|
2018
|
+
const tjpAddrs_YesDna = Object.keys(timelinesByTjpAddr_YesDna);
|
|
2019
|
+
for (const tjpAddr_YesDna of tjpAddrs_YesDna) {
|
|
2020
|
+
const timelineIbGibs = timelinesByTjpAddr_YesDna[tjpAddr_YesDna];
|
|
2021
|
+
for (const ibGib of timelineIbGibs) {
|
|
2022
|
+
await metaspace.registerNewIbGib({
|
|
2023
|
+
ibGib,
|
|
2024
|
+
space: localSpace,
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
if (logalot) { console.log(`${lc} register mapWithTjp_YesDna complete. (I: d54a820e9442dee4681f6228a6795926)`); }
|
|
1978
2029
|
}
|
|
1979
2030
|
|
|
1980
2031
|
|
|
2032
|
+
|
|
1981
2033
|
} catch (error) {
|
|
1982
2034
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1983
2035
|
throw error;
|
|
@@ -2059,49 +2111,55 @@ export class SyncSagaCoordinator {
|
|
|
2059
2111
|
try {
|
|
2060
2112
|
if (logalot) { console.log(`${lc} starting... (I: e179573bdd881202f8ba3168da1c3826)`); }
|
|
2061
2113
|
|
|
2062
|
-
|
|
2114
|
+
if (!sagaIbGib.data) { throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: cbc31dbb7d28b5b8c8cddb510d7d2826)`); }
|
|
2063
2115
|
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
history
|
|
2079
|
-
});
|
|
2080
|
-
if (validationErrors.length > 0) {
|
|
2081
|
-
const errorCommitFrame = await this.createCommitFrame({
|
|
2116
|
+
if (sagaIbGib.data.errors && sagaIbGib.data.errors.length > 0) {
|
|
2117
|
+
// our saga errored out but we already committed the darn
|
|
2118
|
+
// changes previously
|
|
2119
|
+
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)`);
|
|
2120
|
+
} else {
|
|
2121
|
+
// Sender Logic (Finalizing):
|
|
2122
|
+
// If we are here, we received a Commit frame from the Peer.
|
|
2123
|
+
// This implies the Peer has successfully committed.
|
|
2124
|
+
// We should now:
|
|
2125
|
+
// 1. Validate (implicitly done by receiving valid frame)
|
|
2126
|
+
// 2. Perform our own cleanup (Temp -> Dest, if applicable)
|
|
2127
|
+
// 3. Return saga completion.
|
|
2128
|
+
|
|
2129
|
+
// one last validate entire history ?
|
|
2130
|
+
const history = await getFullSyncSagaHistory({
|
|
2082
2131
|
sagaIbGib,
|
|
2083
|
-
|
|
2084
|
-
mySpace,
|
|
2085
|
-
identity,
|
|
2086
|
-
errors: validationErrors,
|
|
2132
|
+
space: mySpace,
|
|
2087
2133
|
});
|
|
2088
|
-
|
|
2089
|
-
|
|
2134
|
+
const validationErrors = await validateFullSyncSagaHistory({
|
|
2135
|
+
history,
|
|
2136
|
+
});
|
|
2137
|
+
if (validationErrors.length > 0) {
|
|
2138
|
+
const errorCommitFrame = await this.createCommitFrame({
|
|
2139
|
+
sagaIbGib,
|
|
2140
|
+
metaspace,
|
|
2141
|
+
mySpace,
|
|
2142
|
+
identity,
|
|
2143
|
+
errors: validationErrors,
|
|
2144
|
+
});
|
|
2145
|
+
return { frame: errorCommitFrame, }; /* <<<< returns early */
|
|
2146
|
+
}
|
|
2090
2147
|
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2148
|
+
await this.executeLocalCommit({
|
|
2149
|
+
commitFrame: sagaIbGib,
|
|
2150
|
+
sagaHistory: history,
|
|
2151
|
+
localSpace: mySpace,
|
|
2152
|
+
localTempSpace: myTempSpace,
|
|
2153
|
+
metaspace,
|
|
2154
|
+
});
|
|
2098
2155
|
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2156
|
+
// todo: implement explicit cleanup logic here and in peer
|
|
2157
|
+
console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
|
|
2158
|
+
if (logalot) { console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`); }
|
|
2102
2159
|
|
|
2103
|
-
|
|
2104
|
-
|
|
2160
|
+
// the holy grail!
|
|
2161
|
+
return { sagaComplete: true };
|
|
2162
|
+
}
|
|
2105
2163
|
} catch (error) {
|
|
2106
2164
|
const emsg = `${lc} ${extractErrorMsg(error)}`;
|
|
2107
2165
|
console.error(emsg);
|