@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.
Files changed (76) hide show
  1. package/.vscode/launch.json +17 -1
  2. package/dist/common/meta-stone/meta-stone-helper.d.mts.map +1 -1
  3. package/dist/common/meta-stone/meta-stone-helper.mjs +30 -12
  4. package/dist/common/meta-stone/meta-stone-helper.mjs.map +1 -1
  5. package/dist/common/meta-stone/meta-stone-types.d.mts +5 -2
  6. package/dist/common/meta-stone/meta-stone-types.d.mts.map +1 -1
  7. package/dist/sync/strategies/conflict-optimistic.d.mts +16 -0
  8. package/dist/sync/strategies/conflict-optimistic.d.mts.map +1 -1
  9. package/dist/sync/strategies/conflict-optimistic.mjs +28 -1
  10. package/dist/sync/strategies/conflict-optimistic.mjs.map +1 -1
  11. package/dist/sync/sync-conflict.respec.mjs +5 -5
  12. package/dist/sync/sync-conflict.respec.mjs.map +1 -1
  13. package/dist/sync/sync-helpers.d.mts +4 -4
  14. package/dist/sync/sync-helpers.d.mts.map +1 -1
  15. package/dist/sync/sync-helpers.mjs +12 -8
  16. package/dist/sync/sync-helpers.mjs.map +1 -1
  17. package/dist/sync/sync-innerspace-constants.respec.mjs +36 -36
  18. package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
  19. package/dist/sync/sync-innerspace-deep-updates.respec.mjs +3 -1
  20. package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
  21. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +62 -9
  22. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
  23. package/dist/sync/sync-innerspace.respec.mjs +45 -16
  24. package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
  25. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +0 -9
  26. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  27. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +25 -43
  28. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  29. package/dist/sync/sync-peer/sync-peer-v1.mjs +2 -2
  30. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  31. package/dist/sync/sync-saga-coordinator.d.mts +15 -10
  32. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  33. package/dist/sync/sync-saga-coordinator.mjs +304 -163
  34. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  35. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +3 -3
  36. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  37. package/dist/sync/sync-types.d.mts +12 -18
  38. package/dist/sync/sync-types.d.mts.map +1 -1
  39. package/dist/sync/sync-types.mjs +15 -21
  40. package/dist/sync/sync-types.mjs.map +1 -1
  41. package/dist/timeline/timeline-api.d.mts +12 -0
  42. package/dist/timeline/timeline-api.d.mts.map +1 -1
  43. package/dist/timeline/timeline-api.mjs +26 -0
  44. package/dist/timeline/timeline-api.mjs.map +1 -1
  45. package/dist/witness/space/inner-space/inner-space-v1.d.mts +19 -0
  46. package/dist/witness/space/inner-space/inner-space-v1.d.mts.map +1 -1
  47. package/dist/witness/space/inner-space/inner-space-v1.mjs +189 -30
  48. package/dist/witness/space/inner-space/inner-space-v1.mjs.map +1 -1
  49. package/dist/witness/space/inner-space/inner-space-v1.respec.mjs +9 -0
  50. package/dist/witness/space/inner-space/inner-space-v1.respec.mjs.map +1 -1
  51. package/dist/witness/space/space-helper.d.mts.map +1 -1
  52. package/dist/witness/space/space-helper.mjs +2 -1
  53. package/dist/witness/space/space-helper.mjs.map +1 -1
  54. package/package.json +2 -1
  55. package/src/common/meta-stone/meta-stone-helper.mts +25 -11
  56. package/src/common/meta-stone/meta-stone-types.mts +5 -2
  57. package/src/sync/README.md +4 -4
  58. package/src/sync/docs/architecture.md +6 -6
  59. package/src/sync/strategies/conflict-optimistic.mts +41 -4
  60. package/src/sync/sync-conflict.respec.mts +5 -5
  61. package/src/sync/sync-helpers.mts +13 -9
  62. package/src/sync/sync-innerspace-constants.respec.mts +39 -39
  63. package/src/sync/sync-innerspace-deep-updates.respec.mts +5 -5
  64. package/src/sync/sync-innerspace-dest-ahead.respec.mts +73 -9
  65. package/src/sync/sync-innerspace.respec.mts +17 -16
  66. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +23 -60
  67. package/src/sync/sync-peer/sync-peer-v1.mts +2 -2
  68. package/src/sync/sync-saga-coordinator.mts +231 -173
  69. package/src/sync/sync-saga-message/sync-saga-message-types.mts +3 -3
  70. package/src/sync/sync-types.mts +19 -26
  71. package/src/timeline/timeline-api.mts +51 -11
  72. package/src/witness/space/inner-space/inner-space-v1.mts +191 -29
  73. package/src/witness/space/inner-space/inner-space-v1.respec.mts +13 -0
  74. package/src/witness/space/space-helper.mts +3 -2
  75. package/test_output.log +0 -0
  76. 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 { getExecutionContext, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
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
- // const logalot = GLOBAL_LOG_A_LOT || true;
62
- const logalot = true;
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
- if (logalot) { console.log(`${lc} Handler returned null (Saga End). (I: faae22abc818ba9b28ac6d2881cd7826)`); }
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 Vector for specific domain ibGibs or TJPs.
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 getKnowledgeVector({
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.getKnowledgeVector.name}]`;
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 KV.`);
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 Vector of the Local Space.
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 vector with tjp -> latest addr/tip in timeline
692
- const knowledgeVector: { [tjp: string]: IbGibAddr } = {};
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
- knowledgeVector[tjp] = getIbGibAddr({ ibGib: tip });
695
+ knowledgeMap[tjp] = getIbGibAddr({ ibGib: tip });
697
696
  });
698
697
  const initData: SyncSagaMessageInitData_V1 = {
699
698
  sagaId,
700
699
  stage: SyncStage.init,
701
- knowledgeVector,
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 {@link executeSagaLoop} which
820
- * initiates and drives the sync.
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 by the receiving endpoint. That
825
- * endpoint's job is basically to get these things collocated and prepared
826
- * to make this call.
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
- * This is a one-off on the receiver.
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
- srcGraph,
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
- nextFrameInfo = await this.handleCommitFrame({ sagaIbGib, metaspace, mySpace: mySpace, myTempSpace: myTempSpace, identity, });
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 Vector (in `sagaIbGib`) vs Receiver's Local KV.
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.knowledgeVector) {
985
- throw new Error(`${lc} Invalid init frame: missing knowledgeVector (E: ed02c869e028d2d06841b9c7f80f2826)`);
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 remoteKV = initData.knowledgeVector;
1019
- if (logalot) { console.log(`${lc} remoteKV: ${pretty(remoteKV)} (I: 9f957862356dfeae183c200854e86e26)`); }
1020
- const remoteTjps = Object.keys(remoteKV);
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] localKV: ${JSON.stringify(localLatestAddrsMap)}`);
1036
- if (logalot) { console.log(`${lc} localKV: ${pretty(localLatestAddrsMap)} (I: 980975642cbccd8018cf0cd808d30826)`); }
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 = remoteKV[tjp];
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
- if (!localTip) { throw new Error(`${lc} Failed to load local tip for conflict resolution. (E: c39448ad6b3a72af78339ad877a56826)`); }
1154
-
1155
- const timelineAddrs = [...(localTip.rel8ns?.past ?? []), localAddr];
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 Abort.
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: SyncIbGib_V1;
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 (!deltaFrame.data) { throw new Error(`(UNEXPECTED) deltaFrame.data falsy? (E: a8be68d48668d93d992d793834823826)`); }
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.forEach(x => {
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
- const resGetAllTransferred =
1920
- await getFromSpace({ addrs: allPayloadAddrsDomainTransferred, space: localTempSpace });
1921
- if (resGetAllTransferred.success && resGetAllTransferred.ibGibs && resGetAllTransferred.ibGibs.length === allPayloadAddrsDomainTransferred.length) {
1922
- allPayloadIbGibsDomainTransferred = resGetAllTransferred.ibGibs.concat();
1923
- } else {
1924
- // errored out, gather info
1925
- if (!resGetAllTransferred.rawResultIbGib) { throw new Error(`(UNEXPECTED) !resGetAllTransferred.rawResultIbGib falsy? (E: dc6cf8729668f4fbe8c024f887d97a26)`); }
1926
- const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data as IbGibSpaceResultData;
1927
- 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)`);
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
- const { payload_Dnas, payload_NonDnas } =
1933
- await putInSpace_dnasThenNonDnas({
1934
- ibGibs: allPayloadIbGibsDomainTransferred,
1935
- space: localSpace
1936
- });
1937
-
1938
- const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } =
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
- // next register each timeline in order...
1981
+ const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } =
1982
+ splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
1951
1983
 
1952
- // ...first the ones without dna...
1953
- const timelinesByTjpAddr_NoDna =
1954
- getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
1955
- const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
1956
- for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
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
- // ...then the ones WITH dna.
1967
- const timelinesByTjpAddr_YesDna =
1968
- getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_YesDna) });
1969
- const tjpAddrs_YesDna = Object.keys(timelinesByTjpAddr_YesDna);
1970
- for (const tjpAddr_YesDna of tjpAddrs_YesDna) {
1971
- const timelineIbGibs = timelinesByTjpAddr_YesDna[tjpAddr_YesDna];
1972
- for (const ibGib of timelineIbGibs) {
1973
- await metaspace.registerNewIbGib({
1974
- ibGib,
1975
- space: localSpace,
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
- let resNextSagaFrameInfo: NextSagaFrameInfo;
2114
+ if (!sagaIbGib.data) { throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: cbc31dbb7d28b5b8c8cddb510d7d2826)`); }
2063
2115
 
2064
- // Sender Logic (Finalizing):
2065
- // If we are here, we received a Commit frame from the Peer.
2066
- // This implies the Peer has successfully committed.
2067
- // We should now:
2068
- // 1. Validate (implicitly done by receiving valid frame)
2069
- // 2. Perform our own cleanup (Temp -> Dest, if applicable)
2070
- // 3. Return saga completion.
2071
-
2072
- // one last validate entire history?
2073
- const history = await getFullSyncSagaHistory({
2074
- sagaIbGib,
2075
- space: mySpace,
2076
- });
2077
- const validationErrors = await validateFullSyncSagaHistory({
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
- metaspace,
2084
- mySpace,
2085
- identity,
2086
- errors: validationErrors,
2132
+ space: mySpace,
2087
2133
  });
2088
- return { frame: errorCommitFrame, }; /* <<<< returns early */
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
- await this.executeLocalCommit({
2092
- deltaFrame: sagaIbGib,
2093
- sagaHistory: history,
2094
- localSpace: mySpace,
2095
- localTempSpace: myTempSpace,
2096
- metaspace,
2097
- });
2148
+ await this.executeLocalCommit({
2149
+ commitFrame: sagaIbGib,
2150
+ sagaHistory: history,
2151
+ localSpace: mySpace,
2152
+ localTempSpace: myTempSpace,
2153
+ metaspace,
2154
+ });
2098
2155
 
2099
- // todo: implement explicit cleanup logic here and in peer
2100
- console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
2101
- if (logalot) { console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`); }
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
- // the holy grail!
2104
- return { sagaComplete: true };
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);