@ibgib/core-gib 0.1.29 → 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 (64) 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 +11 -5
  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-innerspace-deep-updates.respec.mjs +2 -2
  14. package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
  15. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +62 -9
  16. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
  17. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +2 -2
  18. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
  19. package/dist/sync/sync-innerspace-partial-update.respec.mjs +3 -3
  20. package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
  21. package/dist/sync/sync-innerspace.respec.mjs +4 -4
  22. package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
  23. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  24. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +12 -1
  25. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  26. package/dist/sync/sync-saga-coordinator.d.mts +15 -10
  27. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  28. package/dist/sync/sync-saga-coordinator.mjs +44 -46
  29. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  30. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +3 -3
  31. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  32. package/dist/timeline/timeline-api.d.mts +12 -0
  33. package/dist/timeline/timeline-api.d.mts.map +1 -1
  34. package/dist/timeline/timeline-api.mjs +26 -0
  35. package/dist/timeline/timeline-api.mjs.map +1 -1
  36. package/dist/witness/space/inner-space/inner-space-v1.d.mts +19 -0
  37. package/dist/witness/space/inner-space/inner-space-v1.d.mts.map +1 -1
  38. package/dist/witness/space/inner-space/inner-space-v1.mjs +189 -30
  39. package/dist/witness/space/inner-space/inner-space-v1.mjs.map +1 -1
  40. package/dist/witness/space/inner-space/inner-space-v1.respec.mjs +9 -0
  41. package/dist/witness/space/inner-space/inner-space-v1.respec.mjs.map +1 -1
  42. package/dist/witness/space/space-helper.d.mts.map +1 -1
  43. package/dist/witness/space/space-helper.mjs +2 -1
  44. package/dist/witness/space/space-helper.mjs.map +1 -1
  45. package/package.json +2 -1
  46. package/src/common/meta-stone/meta-stone-helper.mts +8 -4
  47. package/src/common/meta-stone/meta-stone-types.mts +5 -2
  48. package/src/sync/README.md +4 -4
  49. package/src/sync/docs/architecture.md +6 -6
  50. package/src/sync/strategies/conflict-optimistic.mts +41 -4
  51. package/src/sync/sync-conflict.respec.mts +5 -5
  52. package/src/sync/sync-innerspace-deep-updates.respec.mts +1 -1
  53. package/src/sync/sync-innerspace-dest-ahead.respec.mts +73 -9
  54. package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
  55. package/src/sync/sync-innerspace-partial-update.respec.mts +2 -2
  56. package/src/sync/sync-innerspace.respec.mts +3 -3
  57. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +12 -2
  58. package/src/sync/sync-saga-coordinator.mts +42 -48
  59. package/src/sync/sync-saga-message/sync-saga-message-types.mts +3 -3
  60. package/src/timeline/timeline-api.mts +51 -11
  61. package/src/witness/space/inner-space/inner-space-v1.mts +191 -29
  62. package/src/witness/space/inner-space/inner-space-v1.respec.mts +13 -0
  63. package/src/witness/space/space-helper.mts +3 -2
  64. package/test_output.log +0 -0
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @module conflict-optimistic
3
- *
3
+ *
4
4
  * Implements the Optimistic Conflict Resolution Strategy.
5
- *
5
+ *
6
6
  * Logic:
7
7
  * 1. findLCA: Traverses `past` to find common ancestor.
8
8
  * 2. mergeDivergentTimelines: Replays DNA to create a merged tip.
@@ -10,11 +10,12 @@
10
10
 
11
11
  import { IbGib_V1, IbGibRel8ns_V1, IbGibData_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
12
12
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
13
+
13
14
  import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
14
15
  import { getFromSpace, putInSpace } from '../../witness/space/space-helper.mjs';
15
16
  import { mut8Timeline } from '../../timeline/timeline-api.mjs';
16
17
 
17
- const lc = `[conflict-optimistic]`;
18
+ const logalot = GLOBAL_LOG_A_LOT || true;
18
19
 
19
20
  export interface LCAResult {
20
21
  lcaAddr: string;
@@ -22,9 +23,42 @@ export interface LCAResult {
22
23
  branchB: IbGib_V1[]; // Path from LCA to Tip B (exclusive of LCA)
23
24
  }
24
25
 
26
+ export interface TimelinesAnalysis {
27
+ latestCommonAddr: IbGibAddr;
28
+ uniqueBranchA
29
+ }
30
+
31
+ /**
32
+ * gets a quick analysis comparing/contrasting two timeline addrs.
33
+ *
34
+ * This does not do in-depth analysis that would involve retrieving ibgibs
35
+ from
36
+ * any spaces.
37
+ */
38
+ export function analyzeTimelinesShallow({
39
+ a,
40
+ b,
41
+ }: {
42
+ a: IbGibAddr[],
43
+ b: IbGibAddr[],
44
+ }
45
+ ): IbGibAddr {
46
+ const lc = `[${analyzeTimelinesShallow.name}]`;
47
+ try {
48
+ if (logalot) { console.log(`${lc} starting... (I: 1f65b883a2089948842c927c6a08c826)`); }
49
+
50
+ throw new Error(`not implemented (E: eab7ac95806ff9c60dafa22eb59cb926)`);
51
+ } catch (error) {
52
+ console.error(`${lc} ${extractErrorMsg(error)}`);
53
+ throw error;
54
+ } finally {
55
+ if (logalot) { console.log(`${lc} complete.`); }
56
+ }
57
+ }
58
+
25
59
  /**
26
60
  * Finds the Last Common Ancestor (LCA) between two divergent timelines.
27
- *
61
+ *
28
62
  * Note: simplistic implementation assuming simple linear divergence.
29
63
  * Complex DAGs might require more robust graph traversal.
30
64
  */
@@ -114,6 +148,9 @@ export async function findLCA({
114
148
  }
115
149
 
116
150
  import { graftTimelines, mergeTextLCS } from '../graft-info/graft-info-helpers.mjs';
151
+ import { IbGibAddr } from '@ibgib/ts-gib';
152
+ import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
153
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
117
154
 
118
155
  /**
119
156
  * Optimistically grafts two divergent timelines by inspecting DNA and replaying transforms.
@@ -166,7 +166,7 @@ await respecfully(sir, `Sync Conflict Resolution`, async () => {
166
166
  // This ensures the conflict precondition exists.
167
167
  await ifWe(sir, 'verify receiver KV pre-sync', async () => {
168
168
  try {
169
- const destKV = await receiverCoordinator.getKnowledgeVector({
169
+ const destKV = await receiverCoordinator.getKnowledgeMap({
170
170
  space: destSpace,
171
171
  metaspace,
172
172
  domainIbGibs: [v1_Dest]
@@ -186,7 +186,7 @@ await respecfully(sir, `Sync Conflict Resolution`, async () => {
186
186
 
187
187
  } catch (error) {
188
188
  console.error(`${lc} ${extractErrorMsg(error)}`);
189
- iReckon(sir, true).asTo('getKnowledgeVector errored out').isGonnaBeFalse();
189
+ iReckon(sir, true).asTo('getKnowledgeMap errored out').isGonnaBeFalse();
190
190
  }
191
191
  });
192
192
 
@@ -251,7 +251,7 @@ await respecfully(sir, `Sync Conflict Resolution`, async () => {
251
251
 
252
252
  try {
253
253
  // Get the KV for the Source Space
254
- const sourceKV = await senderCoordinator.getKnowledgeVector({
254
+ const sourceKV = await senderCoordinator.getKnowledgeMap({
255
255
  space: sourceSpace,
256
256
  metaspace,
257
257
  domainIbGibs: [testRoot] // We want to know the tip of this timeline
@@ -260,7 +260,7 @@ await respecfully(sir, `Sync Conflict Resolution`, async () => {
260
260
  getTjpAddr({ ibGib: testRoot, defaultIfNone: 'incomingAddr' }) ??
261
261
  getIbGibAddr({ ibGib: testRoot });
262
262
 
263
- if (logalot) { console.log(`${lc} getKnowledgeVector returned. sourceKV: ${pretty(sourceKV)} (I: e8780cda37c8b2a46eeb85786874e926)`); }
263
+ if (logalot) { console.log(`${lc} getKnowledgeMap returned. sourceKV: ${pretty(sourceKV)} (I: e8780cda37c8b2a46eeb85786874e926)`); }
264
264
 
265
265
  const sourceTipAddr = sourceKV[tjpAddr];
266
266
  if (!sourceTipAddr) {
@@ -319,7 +319,7 @@ await respecfully(sir, `Sync Conflict Resolution`, async () => {
319
319
  }
320
320
  } catch (error) {
321
321
  console.error(`${lc} ${extractErrorMsg(error)}`);
322
- iReckon(sir, true).asTo('getKnowledgeVector errored out').isGonnaBeFalse();
322
+ iReckon(sir, true).asTo('getKnowledgeMap errored out').isGonnaBeFalse();
323
323
  }
324
324
 
325
325
  });
@@ -128,7 +128,7 @@ await respecfully(sir, `Sync InnerSpaces (Deep Updates)`, async () => {
128
128
  // 5. Verify Dest
129
129
  console.log(`${lc} Verifying Destination...`);
130
130
 
131
- await ifWeMight(sir, `verify deep timeline present`, async () => {
131
+ await ifWe(sir, `verify deep timeline present`, async () => {
132
132
  // Verify Tip (V2)
133
133
  const getV2 = await getFromSpace({ space: destSpace, addr: addrV2 });
134
134
  iReckon(sir, getV2.success).asTo('Tip V2 present').isGonnaBeTrue();
@@ -11,10 +11,10 @@ import {
11
11
  const maam = `[${import.meta.url}]`, sir = maam;
12
12
  import { clone, delay, extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
13
13
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
14
- import { getDependencyGraph } from '../common/other/graph-helper.mjs';
14
+ import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
15
15
 
16
16
  import { SyncSagaCoordinator } from './sync-saga-coordinator.mjs';
17
- import { putInSpace, getFromSpace } from '../witness/space/space-helper.mjs';
17
+ import { putInSpace, getFromSpace, registerNewIbGib } from '../witness/space/space-helper.mjs';
18
18
  import { Metaspace_Innerspace } from '../witness/space/metaspace/metaspace-innerspace/metaspace-innerspace.mjs';
19
19
  import { InnerSpace_V1 } from '../witness/space/inner-space/inner-space-v1.mjs';
20
20
  import { createTimelineRootHelper, getTestKeystoneServiceHelper } from '../agent-helpers.mjs';
@@ -23,6 +23,8 @@ import { DEFAULT_INNER_SPACE_DATA_V1 } from '../witness/space/inner-space/inner-
23
23
  import { toDto } from '../common/other/ibgib-helper.mjs';
24
24
  import { SyncPeerInnerspace_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
25
25
  import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
26
+ import { GetIbGibResult } from '../common/other/other-types.mjs';
27
+ import { IbGibSpaceAny } from '../witness/space/space-base-v1.mjs';
26
28
 
27
29
  const logalot = true;
28
30
  const lc = `[sync-innerspace-dest-ahead.respec]`;
@@ -73,22 +75,43 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
73
75
  // Root -> V1 (Shared) -> V2 (Dest has New)
74
76
  // Source only has V1.
75
77
 
76
- const root = await createTimelineRootHelper<TestData>({
78
+ const v0 = await createTimelineRootHelper<TestData>({
77
79
  ib: 'timeline_root_ff',
78
80
  data: { type: 'root', label: 'Root' },
79
81
  space: sourceSpace,
80
82
  });
83
+ const addrV0 = getIbGibAddr({ ibGib: v0 });
84
+ console.log(pretty(v0));
85
+
86
+ console.log('0000000000000')
87
+ console.log('0000000000000')
88
+ console.log('0000000000000')
89
+ console.log('0000000000000')
90
+ console.log('0000000000000')
81
91
 
82
92
  // V1 (Both have it, but we create in source and copy to dest)
83
93
  const v1 = await mut8Timeline<TestData>({
84
- timeline: root,
94
+ timeline: v0,
85
95
  mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1' } },
86
96
  metaspace,
87
97
  space: sourceSpace,
88
98
  });
99
+ const addrV1 = getIbGibAddr({ ibGib: v1 });
100
+ console.log(pretty(v1));
101
+
89
102
 
90
103
  // Transfer Root & V1 to Dest
91
- await putInSpace({ space: destSpace, ibGibs: [root, v1] }); // Naive seeding
104
+ await putInSpace({ space: destSpace, ibGibs: [v0, v1] }); // Naive seeding
105
+ await registerNewIbGib({ space: destSpace, ibGib: v0 });
106
+ await registerNewIbGib({ space: destSpace, ibGib: v1 });
107
+
108
+ console.log('1111111111111111111111111111111')
109
+ console.log('1111111111111111111111111111111')
110
+ console.log('1111111111111111111111111111111')
111
+ console.log('1111111111111111111111111111111')
112
+ console.log('1111111111111111111111111111111')
113
+ console.log('1111111111111111111111111111111')
114
+ console.log('1111111111111111111111111111111')
92
115
 
93
116
  // V2 (Created in Dest ONLY)
94
117
  const v2 = await mut8Timeline<TestData>({
@@ -98,12 +121,31 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
98
121
  space: destSpace, // Mutate in Dest
99
122
  });
100
123
  const addrV2 = getIbGibAddr({ ibGib: v2 });
124
+ console.log(pretty(v2));
125
+
126
+ const fnAddrExistsInSpace = async (addr: IbGibAddr, space: IbGibSpaceAny) => {
127
+ const resGet = await getFromSpace({ addr, space });
128
+ return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
129
+ }
130
+
131
+ console.log('22222222222')
132
+ console.log('22222222222')
133
+ console.log('22222222222')
134
+ console.log('22222222222')
135
+ console.log('22222222222')
136
+ console.log('22222222222')
137
+ console.log('22222222222')
138
+
101
139
 
102
140
  await ifWeMight(sir, 'verify setup', async () => {
103
141
  // Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
104
142
  // Ensure Source does NOT have V2
105
- const checkV2InSource = await getFromSpace({ space: sourceSpace, addr: addrV2 });
106
- iReckon(sir, checkV2InSource.success && !!checkV2InSource.ibGibs?.length).asTo('Source has V2').isGonnaBeFalse();
143
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
144
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, sourceSpace)).asTo('source has V1').isGonnaBeTrue();
145
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, sourceSpace)).asTo('source has V2').isGonnaBeFalse();
146
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, destSpace)).asTo('dest has V0').isGonnaBeTrue();
147
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, destSpace)).asTo('dest has V1').isGonnaBeTrue();
148
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, destSpace)).asTo('dest has V2').isGonnaBeTrue();
107
149
  });
108
150
 
109
151
  // 3. Setup Sync
@@ -119,6 +161,14 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
119
161
  receiverCoordinator,
120
162
  receiverMetaspace: metaspace,
121
163
  });
164
+ console.log('333333333')
165
+ console.log('333333333')
166
+ console.log('333333333')
167
+ console.log('333333333')
168
+ console.log('333333333')
169
+ console.log('333333333')
170
+ console.log('333333333')
171
+
122
172
 
123
173
  // 4. Run Sync (Source Pushes V1)
124
174
  console.log(`${lc} Running Sync...`);
@@ -132,13 +182,27 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
132
182
 
133
183
  await resSync.done;
134
184
 
135
- // 5. Verify Dest (Should still have V2 as latest)
185
+ console.log('444444444')
186
+ console.log('444444444')
187
+ console.log('444444444')
188
+ console.log('444444444')
189
+ console.log('444444444')
190
+ console.log('444444444')
191
+ console.log('444444444')
192
+
193
+ // 5. Verify Sync (v2 should be in both source and dest now)
136
194
  console.log(`${lc} Verifying Destination...`);
137
195
 
138
196
  await ifWeMight(sir, `verify dest stays ahead`, async () => {
139
197
  // Verify Tip (V2)
140
198
  const getV2 = await getFromSpace({ space: destSpace, addr: addrV2 });
141
- iReckon(sir, getV2.success).asTo('V2 still present in Dest').isGonnaBeTrue();
199
+
200
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
201
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, sourceSpace)).asTo('source has V1').isGonnaBeTrue();
202
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, sourceSpace)).asTo('source has V2').isGonnaBeTrue();
203
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, destSpace)).asTo('dest has V0').isGonnaBeTrue();
204
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, destSpace)).asTo('dest has V1').isGonnaBeTrue();
205
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, destSpace)).asTo('dest has V2').isGonnaBeTrue();
142
206
 
143
207
  // Verify V2 points to V1
144
208
  const v2IbGib = getV2.ibGibs![0];
@@ -130,7 +130,7 @@ await respecfully(sir, `Sync InnerSpaces (Multiple Timelines)`, async () => {
130
130
  // 5. Verify Dest
131
131
  console.log(`${lc} Verifying Destination...`);
132
132
 
133
- await ifWeMight(sir, `verify timelines present`, async () => {
133
+ await ifWe(sir, `verify timelines present`, async () => {
134
134
  // Verify A
135
135
  const getA = await getFromSpace({ space: destSpace, addr: addrA });
136
136
  iReckon(sir, getA.success).asTo('Timeline A present').isGonnaBeTrue();
@@ -98,7 +98,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
98
98
  // Transfer Root & V1 to Dest (Simulate previous sync)
99
99
  await putInSpace({ space: destSpace, ibGibs: [root, v1] });
100
100
 
101
- await ifWeMight(sir, 'verify setup', async () => {
101
+ await ifWe(sir, 'verify setup', async () => {
102
102
  // Verify Dest has V1
103
103
  const checkV1 = await getFromSpace({ space: destSpace, addr: getIbGibAddr({ ibGib: v1 }) });
104
104
  iReckon(sir, checkV1.success).asTo('Dest has V1').isGonnaBeTrue();
@@ -137,7 +137,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
137
137
  // 5. Verify Dest (Should now have V2)
138
138
  console.log(`${lc} Verifying Destination...`);
139
139
 
140
- await ifWeMight(sir, `verify dest updated`, async () => {
140
+ await ifWe(sir, `verify dest updated`, async () => {
141
141
  // Verify Tip (V2)
142
142
  const getV2 = await getFromSpace({ space: destSpace, addr: addrV2 });
143
143
  iReckon(sir, getV2.success).asTo('V2 present in Dest').isGonnaBeTrue();
@@ -154,18 +154,18 @@ await respecfully(sir, `Sync InnerSpaces`, async () => {
154
154
  try {
155
155
  const getChildInDest = await getFromSpace({ space: destSpace, addr: childAddr });
156
156
 
157
- await ifWeMight(sir, `verify success getChildInDest`, async () => {
157
+ await ifWe(sir, `verify success getChildInDest`, async () => {
158
158
  iReckon(sir, getChildInDest.success).asTo('Child present in Dest').isGonnaBeTrue();
159
159
  });
160
160
 
161
- await ifWeMight(sir, `verify getChildInDest.ibGibs`, async () => {
161
+ await ifWe(sir, `verify getChildInDest.ibGibs`, async () => {
162
162
  const firstChild = getChildInDest.ibGibs?.[0];
163
163
  if (logalot) { console.log(`${lc} firstChild: ${pretty(firstChild)}`); }
164
164
  iReckon(sir, firstChild?.data?.n).asTo('Child content matches').isGonnaBe(2);
165
165
  });
166
166
 
167
167
  } catch (error) {
168
- await ifWeMight(sir, `doh`, async () => {
168
+ await ifWe(sir, `doh`, async () => {
169
169
  // hack here I'm getting tired...
170
170
  iReckon(sir, true).asTo(`error: ${extractErrorMsg(error)}`).isGonnaBeFalse();
171
171
  });
@@ -245,6 +245,17 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<InitializeSyncPeerInnersp
245
245
  }
246
246
 
247
247
  // spin off the payloads, as that may take a long time
248
+ if (responseCtx.payloadIbGibsDomain?.length ?? 0 > 0) {
249
+ // i guess this only will hit once we have conflicts, because
250
+ // it's the return trip, i.e., from the receiver. The initial
251
+ // ack frame does it through push offers?
252
+ await delay(2000);
253
+ console.warn(`${lc} this delay does hit (W: 3940d47d2a7433833837af4cef171126)`)
254
+ for (let i = 0; i < 100; i++) {
255
+ const element = 100;
256
+ console.log(`THIS HITS`)
257
+ }
258
+ }
248
259
  const payloadIbGibsDomain_response = responseCtx.payloadIbGibsDomain;
249
260
  if (payloadIbGibsDomain_response) {
250
261
  new Promise<void>(async (resolve, reject) => {
@@ -253,13 +264,12 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<InitializeSyncPeerInnersp
253
264
  if (logalot) { console.log(`${lcPut} starting... (I: 4133e736b4c80d2cf94448b87b206826)`); }
254
265
 
255
266
  // 2 seconds...i want to see huge blocks of logs entries for this to see this happening
256
- const delayMs = 200;
267
+ const delayMs = 2000;
257
268
  for (let i = 0; i < 10; i++) {
258
269
  console.warn(`${lc} ARTIFICIALLY DELAYING PAYLOADS TO MIMIC TRANSFER LATENCY. REMOVE THIS DELAY!! (W: 5e7b28f1daa82d955897e9d8cdb16f26)`)
259
270
  await delay(delayMs);
260
271
  }
261
272
 
262
-
263
273
  await putInSpace_dnasThenNonDnas({
264
274
  ibGibs: payloadIbGibsDomain_response,
265
275
  space: senderTempSpace,
@@ -23,7 +23,7 @@ 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,
@@ -536,10 +536,10 @@ export class SyncSagaCoordinator {
536
536
  }
537
537
 
538
538
  /**
539
- * Helper to get Knowledge Vector for specific domain ibGibs or TJPs.
539
+ * Helper to get Knowledge Map for specific domain ibGibs or TJPs.
540
540
  * Useful for testing and external validation.
541
541
  */
542
- public async getKnowledgeVector({
542
+ public async getKnowledgeMap({
543
543
  space,
544
544
  metaspace,
545
545
  domainIbGibs,
@@ -550,7 +550,7 @@ export class SyncSagaCoordinator {
550
550
  domainIbGibs?: IbGib_V1[],
551
551
  tjpAddrs?: string[],
552
552
  }): Promise<{ [tjp: string]: string | null }> {
553
- const lc = `${this.lc}[${this.getKnowledgeVector.name}]`;
553
+ const lc = `${this.lc}[${this.getKnowledgeMap.name}]`;
554
554
  try {
555
555
  if (logalot) { console.log(`${lc} starting... (I: e184f8a7818666febfbbd2d841ed3826)`); }
556
556
  // console.dir(space);
@@ -588,7 +588,7 @@ export class SyncSagaCoordinator {
588
588
  } else {
589
589
  // No info provided. Return empty? Or throw?
590
590
  // User test context implied "everything", but implementation requires scope.
591
- console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty KV.`);
591
+ console.warn(`${lc} No domainIbGibs or tjpAddrs provided. Returning empty Knowledge.`);
592
592
  return {};
593
593
  }
594
594
 
@@ -655,7 +655,7 @@ export class SyncSagaCoordinator {
655
655
  * @remarks
656
656
  * **Execution Context**: **Sender (Local)**.
657
657
  *
658
- * 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.
659
659
  * This is sent to the Receiver to begin Gap Analysis.
660
660
  */
661
661
  private async createInitFrame({
@@ -687,17 +687,17 @@ export class SyncSagaCoordinator {
687
687
  // we need to store the fullGraph in our tempSpace for later...
688
688
  await putInSpace({ ibGibs: Object.values(fullGraph), space: tempSpace });
689
689
 
690
- // populate our knowledge vector with tjp -> latest addr/tip in timeline
691
- const knowledgeVector: { [tjp: string]: IbGibAddr } = {};
690
+ // populate our knowledge map with tjp -> latest addr/tip in timeline
691
+ const knowledgeMap: { [tjp: string]: IbGibAddr } = {};
692
692
  Object.keys(srcTimelinesMap).forEach(tjp => {
693
693
  const timeline = srcTimelinesMap[tjp];
694
694
  const tip = timeline.at(-1)!;
695
- knowledgeVector[tjp] = getIbGibAddr({ ibGib: tip });
695
+ knowledgeMap[tjp] = getIbGibAddr({ ibGib: tip });
696
696
  });
697
697
  const initData: SyncSagaMessageInitData_V1 = {
698
698
  sagaId,
699
699
  stage: SyncStage.init,
700
- knowledgeVector,
700
+ knowledgeMap: knowledgeMap,
701
701
  identity: sessionIdentity, // KeystoneIbGib is already public data
702
702
  mode: SyncMode.sync,
703
703
  stones: srcStones.map(s => getIbGibAddr({ ibGib: s })),
@@ -815,16 +815,21 @@ export class SyncSagaCoordinator {
815
815
  *
816
816
  * ## 1. Sender
817
817
  *
818
- * On the sender, this is called within the {@link executeSagaLoop} which
819
- * 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.
820
822
  *
821
823
  * ## 2. Receiver
822
824
  *
823
- * On the receiver, this is called directly by the receiving endpoint. That
824
- * endpoint's job is basically to get these things collocated and prepared
825
- * 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.
826
829
  *
827
- * 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.
828
833
  */
829
834
  private async handleResponseSagaContext({
830
835
  sagaContext,
@@ -868,11 +873,6 @@ export class SyncSagaCoordinator {
868
873
 
869
874
  if (logalot) { console.log(`${lc} handling frame stage: ${stage}`); }
870
875
 
871
- /**
872
- * don't like this name, need to refactor
873
- */
874
- const srcGraph = toFlatGraph({ ibGibs: sagaContext.payloadIbGibsDomain }) ?? {};
875
-
876
876
  let nextFrameInfo: NextSagaFrameInfo;
877
877
  switch (stage) {
878
878
  case SyncStage.init:
@@ -899,7 +899,6 @@ export class SyncSagaCoordinator {
899
899
  nextFrameInfo = await this.handleDeltaFrame({
900
900
  sagaContext,
901
901
  sagaIbGib,
902
- srcGraph,
903
902
  metaspace, mySpace, myTempSpace,
904
903
  identity,
905
904
  });
@@ -940,7 +939,7 @@ export class SyncSagaCoordinator {
940
939
  * **Execution Context**: **Receiver (Remote)**.
941
940
  *
942
941
  * The Receiver performs Gap Analysis here:
943
- * 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.
944
943
  * 2. Identifies what Sender needs (`pushOfferAddrs`).
945
944
  * 3. Identifies what Receiver needs (`deltaRequestAddrInfos`).
946
945
  * 4. Returns an `Ack` frame containing these lists.
@@ -983,8 +982,8 @@ export class SyncSagaCoordinator {
983
982
  throw new Error(`${lc} Invalid init frame: initData.stage !== SyncStage.init (E: c91be82970e4decc58f56bf8fc1ffc26)`);
984
983
  }
985
984
  // if (logalot) { console.log(`${lc} initData: ${pretty(initData)} (I: 46b0f8441b96ad7a388f1ce3239dd826)`); }
986
- if (!initData || !initData.knowledgeVector) {
987
- 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)`);
988
987
  }
989
988
 
990
989
  // Determine Strategy from Saga Data (since V1 stores it in root)
@@ -1017,9 +1016,9 @@ export class SyncSagaCoordinator {
1017
1016
  /**
1018
1017
  * "remote" is sender in this case
1019
1018
  */
1020
- const remoteKV = initData.knowledgeVector;
1021
- if (logalot) { console.log(`${lc} remoteKV: ${pretty(remoteKV)} (I: 9f957862356dfeae183c200854e86e26)`); }
1022
- const remoteTjps = Object.keys(remoteKV);
1019
+ const remoteKnowledge = initData.knowledgeMap;
1020
+ if (logalot) { console.log(`${lc} remoteKnowledge: ${pretty(remoteKnowledge)} (I: 9f957862356dfeae183c200854e86e26)`); }
1021
+ const remoteTjps = Object.keys(remoteKnowledge);
1023
1022
  if (logalot) { console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`); }
1024
1023
  if (logalot) { console.log(`${lc} remoteTjps: ${pretty(remoteTjps)} (I: 86ea4c53db0dc184c8b253386c402126)`); }
1025
1024
 
@@ -1034,13 +1033,13 @@ export class SyncSagaCoordinator {
1034
1033
  if (!resGetLatestAddrs.data) { throw new Error(`(UNEXPECTED) resGetLatestAddrs.data falsy? (E: b180d813c088042b38e1e02e06a16926)`); }
1035
1034
  if (!resGetLatestAddrs.data.latestAddrsMap) { throw new Error(`(UNEXPECTED) resGetLatestAddrs.data.latestAddrsMap falsy? (E: 16bc386dd51d0ff53a49620b1e641826)`); }
1036
1035
  localLatestAddrsMap = resGetLatestAddrs.data.latestAddrsMap;
1037
- if (logalot) { console.log(`${lc} [TEST DEBUG] localKV: ${JSON.stringify(localLatestAddrsMap)}`); }
1038
- 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)`); }
1039
1038
  }
1040
1039
 
1041
1040
  // 2. Gap Analysis
1042
1041
  for (const tjp of remoteTjps) {
1043
- const remoteAddr = remoteKV[tjp];
1042
+ const remoteAddr = remoteKnowledge[tjp];
1044
1043
  const localAddr = localLatestAddrsMap[tjp];
1045
1044
 
1046
1045
  if (!localAddr) {
@@ -1099,7 +1098,6 @@ export class SyncSagaCoordinator {
1099
1098
  */
1100
1099
  let localIsInPast = false;
1101
1100
  try {
1102
- // we could
1103
1101
  localIsInPast = await isPastFrame({
1104
1102
  olderAddr: localAddr,
1105
1103
  newerAddr: remoteAddr,
@@ -1135,27 +1133,23 @@ export class SyncSagaCoordinator {
1135
1133
  reason: 'divergence',
1136
1134
  terminal: true
1137
1135
  });
1136
+ // todo: create error saga frame for when aborting or other terminal error
1138
1137
  } else if (conflictStrategy === 'optimistic') {
1139
1138
  // Optimistic: We want resolve this.
1140
1139
  // We need to send our history to the Sender so they can Merge.
1141
1140
 
1142
1141
  // Fetch Full History for Local Timeline
1143
- // Note: We might optimize this to only send "recent" history if we had a KV?
1144
- // But for now, get full past.
1145
- // Optimization: localKV might not have full history.
1146
- // We need to inspect the 'past' of the local tip.
1147
-
1148
- // We need the ACTUAL object to get the past.
1149
- // We have localAddr.
1150
1142
  const resLocalTip = await getFromSpace({ space: mySpace, addr: localAddr });
1151
1143
  if (!resLocalTip.success || resLocalTip.ibGibs?.length !== 1) {
1152
- 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)`);
1153
1145
  }
1154
1146
  const localTip = resLocalTip.ibGibs[0];
1155
- if (!localTip) { throw new Error(`${lc} Failed to load local tip for conflict resolution. (E: c39448ad6b3a72af78339ad877a56826)`); }
1156
-
1157
- const timelineAddrs = [...(localTip.rel8ns?.past ?? []), localAddr];
1158
-
1147
+ const pastAddrs = await getHistoryAddrs({
1148
+ timeline: localTip,
1149
+ space: mySpace,
1150
+ metaspace,
1151
+ });
1152
+ const timelineAddrs = [...pastAddrs, localAddr];
1159
1153
  conflicts.push({
1160
1154
  tjpAddr: tjp,
1161
1155
  localAddr,
@@ -1349,8 +1343,10 @@ export class SyncSagaCoordinator {
1349
1343
  const terminalConflicts = conflicts.filter(c => c.terminal);
1350
1344
  if (terminalConflicts.length > 0) {
1351
1345
  if (logalot) { console.warn(`${lc} Received terminal conflicts from Ack: ${JSON.stringify(terminalConflicts)}`); }
1352
- // Terminal failure. Sender should probably Commit(Fail) or just Abort.
1353
- // For now, throw to trigger abort.
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.
1354
1350
  throw new Error(`${lc} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
1355
1351
  }
1356
1352
 
@@ -1583,7 +1579,6 @@ export class SyncSagaCoordinator {
1583
1579
  private async handleDeltaFrame({
1584
1580
  sagaContext,
1585
1581
  sagaIbGib,
1586
- srcGraph,
1587
1582
  mySpace,
1588
1583
  myTempSpace,
1589
1584
  metaspace,
@@ -1591,7 +1586,6 @@ export class SyncSagaCoordinator {
1591
1586
  }: {
1592
1587
  sagaContext: SyncSagaContextIbGib_V1,
1593
1588
  sagaIbGib: SyncIbGib_V1,
1594
- srcGraph: { [addr: string]: IbGib_V1 },
1595
1589
  mySpace: IbGibSpaceAny,
1596
1590
  myTempSpace: IbGibSpaceAny,
1597
1591
  metaspace: MetaspaceService,
@@ -40,7 +40,7 @@ export interface SyncSagaMessageIbGib_V1 extends IbGib_V1<SyncSagaMessageData_V1
40
40
  /**
41
41
  * The "Hello" of the sync protocol.
42
42
  *
43
- * Exchanges knowledge vectors (what I have) and identity (who I am).
43
+ * Exchanges knowledge maps (what I have) and identity (who I am).
44
44
  */
45
45
  export interface SyncSagaMessageInitData_V1 extends SyncSagaMessageData_V1 {
46
46
  stage: typeof SyncStage.init;
@@ -51,7 +51,7 @@ export interface SyncSagaMessageInitData_V1 extends SyncSagaMessageData_V1 {
51
51
  *
52
52
  * IOW, this is a map of the starting and end points of an ibGib's timeline.
53
53
  */
54
- knowledgeVector: { [tjp: string]: IbGibAddr };
54
+ knowledgeMap: { [tjp: string]: IbGibAddr };
55
55
 
56
56
  /**
57
57
  * The Keystone Identity of the sender.
@@ -149,7 +149,7 @@ export interface SyncSagaMessageAckData_V1 extends SyncSagaMessageData_V1 {
149
149
  /**
150
150
  * Infos regarding ibgibs that the receiver (generator of this ack)
151
151
  * knows/believes that the sender does NOT have (after looking at knowledge
152
- * vector of sender).
152
+ * map of sender).
153
153
  *
154
154
  * This includes addrs that will correspond to the context.payloadAddrsDomain
155
155
  *