@ibgib/core-gib 0.1.28 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/meta-stone/meta-stone-helper.d.mts.map +1 -1
- package/dist/common/meta-stone/meta-stone-helper.mjs +19 -7
- package/dist/common/meta-stone/meta-stone-helper.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 +5 -3
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +2 -2
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-partial-update.respec.mjs +3 -3
- package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace.respec.mjs +49 -20
- 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 +13 -42
- 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.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +261 -118
- package/dist/sync/sync-saga-coordinator.mjs.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/package.json +1 -1
- package/src/common/meta-stone/meta-stone-helper.mts +17 -7
- 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 +6 -6
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
- package/src/sync/sync-innerspace-partial-update.respec.mts +2 -2
- package/src/sync/sync-innerspace.respec.mts +20 -19
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +11 -58
- package/src/sync/sync-peer/sync-peer-v1.mts +2 -2
- package/src/sync/sync-saga-coordinator.mts +190 -126
- package/src/sync/sync-types.mts +19 -26
- package/test_output.log +0 -0
- package/tmp.md +170 -62
|
@@ -2,11 +2,12 @@ import { extractErrorMsg, getUUID, // so our timestamp in ticks as a string are
|
|
|
2
2
|
pretty, delay, } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
|
|
3
3
|
import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
4
4
|
import { Factory_V1 } from "@ibgib/ts-gib/dist/V1/factory.mjs";
|
|
5
|
+
import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
|
|
5
6
|
import { putInSpace, getLatestAddrs, getFromSpace } from "../witness/space/space-helper.mjs";
|
|
6
7
|
import { SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN, } from "./sync-constants.mjs";
|
|
7
8
|
import { appendToTimeline, createTimeline } from "../timeline/timeline-api.mjs";
|
|
8
9
|
import { SyncConflictStrategy, SyncMode, SYNC_CONFLICT_STRATEGY_VALID_VALUES, } from "./sync-types.mjs";
|
|
9
|
-
import { getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
|
|
10
|
+
import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory } from "./sync-helpers.mjs";
|
|
10
11
|
import { getDeltaDependencyGraph, getDependencyGraph, toFlatGraph } from "../common/other/graph-helper.mjs";
|
|
11
12
|
import { getSyncSagaMessageIb } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
12
13
|
import { SYNC_SAGA_MSG_ATOM } from "./sync-saga-message/sync-saga-message-constants.mjs";
|
|
@@ -16,9 +17,8 @@ import { newupSubject, } from "../common/pubsub/subject/subject-helper.mjs";
|
|
|
16
17
|
import { mergeDivergentTimelines } from "./strategies/conflict-optimistic.mjs";
|
|
17
18
|
import { getSyncSagaMessageFromFrame } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
18
19
|
import { fnObs } from "../common/pubsub/observer/observer-helper.mjs";
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const logalotControlDomain = true;
|
|
20
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
21
|
+
const logalotControlDomain = false;
|
|
22
22
|
const lcControlDomain = '[ControlDomain]';
|
|
23
23
|
/**
|
|
24
24
|
* Orchestrates the synchronization process between two spaces (Source and Destination).
|
|
@@ -407,8 +407,13 @@ export class SyncSagaCoordinator {
|
|
|
407
407
|
metaspace,
|
|
408
408
|
});
|
|
409
409
|
if (!contextResult) {
|
|
410
|
+
// should this ever hit?
|
|
411
|
+
console.error(`${lc} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
410
415
|
if (logalot) {
|
|
411
|
-
console.log(`${lc} Handler returned null (Saga End). (I:
|
|
416
|
+
console.log(`${lc} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
|
|
412
417
|
}
|
|
413
418
|
break;
|
|
414
419
|
}
|
|
@@ -419,9 +424,6 @@ export class SyncSagaCoordinator {
|
|
|
419
424
|
else if (!contextResult.nextFrameInfo) {
|
|
420
425
|
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
|
|
421
426
|
}
|
|
422
|
-
else if (contextResult.nextFrameInfo?.sagaComplete) {
|
|
423
|
-
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo.sagaComplete? logic flow should not have gotten here. (E: 104a32381db816b7183435e805b3d626)`);
|
|
424
|
-
}
|
|
425
427
|
// #endregion error conditions throw
|
|
426
428
|
// we have another frame to process and send out, with possibly
|
|
427
429
|
// payload domain ibgibs as well
|
|
@@ -730,14 +732,19 @@ export class SyncSagaCoordinator {
|
|
|
730
732
|
sagaContext,
|
|
731
733
|
sagaIbGib,
|
|
732
734
|
srcGraph,
|
|
733
|
-
metaspace,
|
|
734
|
-
mySpace,
|
|
735
|
-
myTempSpace,
|
|
735
|
+
metaspace, mySpace, myTempSpace,
|
|
736
736
|
identity,
|
|
737
737
|
});
|
|
738
738
|
break;
|
|
739
739
|
case SyncStage.commit:
|
|
740
|
-
|
|
740
|
+
if (logalot) {
|
|
741
|
+
console.log(`${lc}[${getSyncSagaFrameOrigin({ sagaFrame: sagaIbGib })}] mySpace.ib: ${mySpace.ib} (I: 5b270996d848907238d817fffa64a126)`);
|
|
742
|
+
}
|
|
743
|
+
nextFrameInfo = await this.handleCommitFrame({
|
|
744
|
+
sagaIbGib,
|
|
745
|
+
metaspace, mySpace, myTempSpace,
|
|
746
|
+
identity,
|
|
747
|
+
});
|
|
741
748
|
break;
|
|
742
749
|
default:
|
|
743
750
|
throw new Error(`${lc} (UNEXPECTED) Unknown sync stage: ${stage} (E: 9c2b4c8a6d34469f8263544710183355)`);
|
|
@@ -779,7 +786,9 @@ export class SyncSagaCoordinator {
|
|
|
779
786
|
if (logalot) {
|
|
780
787
|
console.log(`${lc} starting... (I: 9d88dcad0408c029e898a4bcf3b08426)`);
|
|
781
788
|
}
|
|
782
|
-
|
|
789
|
+
if (logalot) {
|
|
790
|
+
console.log(`${lc} [TEST DEBUG] Receiver mySpace: ${mySpace.ib}`);
|
|
791
|
+
}
|
|
783
792
|
// Extract Init Data
|
|
784
793
|
const initData = messageData; // Using renamed variable for clarity
|
|
785
794
|
if (initData.stage !== SyncStage.init) {
|
|
@@ -827,7 +836,9 @@ export class SyncSagaCoordinator {
|
|
|
827
836
|
console.log(`${lc} remoteKV: ${pretty(remoteKV)} (I: 9f957862356dfeae183c200854e86e26)`);
|
|
828
837
|
}
|
|
829
838
|
const remoteTjps = Object.keys(remoteKV);
|
|
830
|
-
|
|
839
|
+
if (logalot) {
|
|
840
|
+
console.log(`${lc} [TEST DEBUG] remoteTjps: ${JSON.stringify(remoteTjps)}`);
|
|
841
|
+
}
|
|
831
842
|
if (logalot) {
|
|
832
843
|
console.log(`${lc} remoteTjps: ${pretty(remoteTjps)} (I: 86ea4c53db0dc184c8b253386c402126)`);
|
|
833
844
|
}
|
|
@@ -846,7 +857,9 @@ export class SyncSagaCoordinator {
|
|
|
846
857
|
throw new Error(`(UNEXPECTED) resGetLatestAddrs.data.latestAddrsMap falsy? (E: 16bc386dd51d0ff53a49620b1e641826)`);
|
|
847
858
|
}
|
|
848
859
|
localLatestAddrsMap = resGetLatestAddrs.data.latestAddrsMap;
|
|
849
|
-
|
|
860
|
+
if (logalot) {
|
|
861
|
+
console.log(`${lc} [TEST DEBUG] localKV: ${JSON.stringify(localLatestAddrsMap)}`);
|
|
862
|
+
}
|
|
850
863
|
if (logalot) {
|
|
851
864
|
console.log(`${lc} localKV: ${pretty(localLatestAddrsMap)} (I: 980975642cbccd8018cf0cd808d30826)`);
|
|
852
865
|
}
|
|
@@ -857,7 +870,9 @@ export class SyncSagaCoordinator {
|
|
|
857
870
|
const localAddr = localLatestAddrsMap[tjp];
|
|
858
871
|
if (!localAddr) {
|
|
859
872
|
// We (Receiver) don't have this timeline at all. Request it.
|
|
860
|
-
|
|
873
|
+
if (logalot) {
|
|
874
|
+
console.log(`${lc} [TEST DEBUG] Missing local timeline for TJP: ${tjp}. Requesting remoteAddr: ${remoteAddr}`);
|
|
875
|
+
}
|
|
861
876
|
deltaRequestAddrInfos.push({
|
|
862
877
|
addr: remoteAddr,
|
|
863
878
|
tjpAddr: tjp,
|
|
@@ -869,10 +884,14 @@ export class SyncSagaCoordinator {
|
|
|
869
884
|
// we do have this timeline...
|
|
870
885
|
if (localAddr === remoteAddr) {
|
|
871
886
|
// ...already synced
|
|
872
|
-
|
|
887
|
+
if (logalot) {
|
|
888
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Synced (localAddr === remoteAddr)`);
|
|
889
|
+
}
|
|
873
890
|
continue;
|
|
874
891
|
}
|
|
875
|
-
|
|
892
|
+
if (logalot) {
|
|
893
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: localAddr=${localAddr}, remoteAddr=${remoteAddr} - checking for divergence...`);
|
|
894
|
+
}
|
|
876
895
|
// we have this timeline but it's not synced...
|
|
877
896
|
// We're executing on receiver. Check if Remote (Sender) is in
|
|
878
897
|
// our past, and if so, we are ahead and need to push the delta
|
|
@@ -885,7 +904,9 @@ export class SyncSagaCoordinator {
|
|
|
885
904
|
if (remoteIsInPast) {
|
|
886
905
|
// we're ahead, so push the delta of what the sender doesn't
|
|
887
906
|
// have (we have full knowledge)
|
|
888
|
-
|
|
907
|
+
if (logalot) {
|
|
908
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Remote (sender) is in past - offering push`);
|
|
909
|
+
}
|
|
889
910
|
const deltaGraph = await getDeltaDependencyGraph({
|
|
890
911
|
ibGibAddr: localAddr,
|
|
891
912
|
live: false, // always live: false right?
|
|
@@ -921,7 +942,9 @@ export class SyncSagaCoordinator {
|
|
|
921
942
|
}
|
|
922
943
|
if (localIsInPast) {
|
|
923
944
|
// Fast-Forward: We update to remote's tip.
|
|
924
|
-
|
|
945
|
+
if (logalot) {
|
|
946
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: Local is in past - requesting delta`);
|
|
947
|
+
}
|
|
925
948
|
deltaRequestAddrInfos.push({
|
|
926
949
|
addr: remoteAddr,
|
|
927
950
|
tjpAddr: tjp,
|
|
@@ -930,7 +953,9 @@ export class SyncSagaCoordinator {
|
|
|
930
953
|
}
|
|
931
954
|
else {
|
|
932
955
|
// DIVERGENCE: Both have changes the other doesn't know about.
|
|
933
|
-
|
|
956
|
+
if (logalot) {
|
|
957
|
+
console.log(`${lc} [TEST DEBUG] TJP ${tjp}: DIVERGENCE DETECTED! conflictStrategy=${conflictStrategy}`);
|
|
958
|
+
}
|
|
934
959
|
if (conflictStrategy === 'abort') {
|
|
935
960
|
// Abort Strategy: We will treat this as terminal.
|
|
936
961
|
// But for Unified Ack, we just mark it terminal in the list?
|
|
@@ -1134,13 +1159,17 @@ export class SyncSagaCoordinator {
|
|
|
1134
1159
|
// #region sanity/validation
|
|
1135
1160
|
// 1. Check for Conflicts
|
|
1136
1161
|
const conflicts = ackData.conflicts || [];
|
|
1137
|
-
|
|
1138
|
-
|
|
1162
|
+
if (logalot) {
|
|
1163
|
+
console.log(`${lc} [CONFLICT DEBUG] Received conflicts from Ack: ${conflicts.length}`);
|
|
1164
|
+
}
|
|
1165
|
+
if (logalot && conflicts.length > 0) {
|
|
1139
1166
|
console.log(`${lc} [CONFLICT DEBUG] Conflicts detail: ${JSON.stringify(conflicts, null, 2)}`);
|
|
1140
1167
|
}
|
|
1141
1168
|
const terminalConflicts = conflicts.filter(c => c.terminal);
|
|
1142
1169
|
if (terminalConflicts.length > 0) {
|
|
1143
|
-
|
|
1170
|
+
if (logalot) {
|
|
1171
|
+
console.warn(`${lc} Received terminal conflicts from Ack: ${JSON.stringify(terminalConflicts)}`);
|
|
1172
|
+
}
|
|
1144
1173
|
// Terminal failure. Sender should probably Commit(Fail) or just Abort.
|
|
1145
1174
|
// For now, throw to trigger abort.
|
|
1146
1175
|
throw new Error(`${lc} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
|
|
@@ -1153,7 +1182,9 @@ export class SyncSagaCoordinator {
|
|
|
1153
1182
|
*/
|
|
1154
1183
|
const outgoingDeltaAddrRequestInfos = []; // Additional requests for merging
|
|
1155
1184
|
if (conflicts.length > 0) {
|
|
1156
|
-
|
|
1185
|
+
if (logalot) {
|
|
1186
|
+
console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
|
|
1187
|
+
}
|
|
1157
1188
|
// We need to resolve these.
|
|
1158
1189
|
// Strategy:
|
|
1159
1190
|
// 1. Analyze Divergence (Sender vs Receiver)
|
|
@@ -1261,10 +1292,14 @@ export class SyncSagaCoordinator {
|
|
|
1261
1292
|
// console.log(`${lc} [CONFLICT DEBUG] No receiver-only frames found for this conflict`);
|
|
1262
1293
|
// }
|
|
1263
1294
|
}
|
|
1264
|
-
|
|
1295
|
+
if (logalot) {
|
|
1296
|
+
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingDeltaAddrRequestInfos: ${outgoingDeltaAddrRequestInfos.length}`);
|
|
1297
|
+
}
|
|
1265
1298
|
}
|
|
1266
1299
|
else {
|
|
1267
|
-
|
|
1300
|
+
if (logalot) {
|
|
1301
|
+
console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`);
|
|
1302
|
+
}
|
|
1268
1303
|
}
|
|
1269
1304
|
// 2. Prepare Delta Payload (What Receiver Requesting + Our Conflict Logic)
|
|
1270
1305
|
/**
|
|
@@ -1364,32 +1399,44 @@ export class SyncSagaCoordinator {
|
|
|
1364
1399
|
console.log(`${lc} deltaData: ${pretty(deltaData)} (I: a76008681df458cfbcdc4848f825a826)`);
|
|
1365
1400
|
}
|
|
1366
1401
|
// #endregion validate/sanity
|
|
1367
|
-
|
|
1402
|
+
if (logalot) {
|
|
1403
|
+
console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`);
|
|
1404
|
+
}
|
|
1368
1405
|
const peerProposesCommit = deltaData.proposeCommit || false;
|
|
1369
1406
|
/**
|
|
1370
1407
|
* these are already in the local temp space
|
|
1371
1408
|
*/
|
|
1372
1409
|
const receivedPayloadIbGibs = sagaContext.payloadIbGibsDomain ?? [];
|
|
1373
1410
|
// 2. Fulfill Peer Requests (Outgoing Payload with Delta Dependencies)
|
|
1374
|
-
|
|
1411
|
+
if (logalot) {
|
|
1412
|
+
console.log(`${lc} [CONFLICT DEBUG] Fulfilling ${(deltaData.deltaRequestAddrInfos || []).length} peer requests`);
|
|
1413
|
+
}
|
|
1375
1414
|
const outgoingPayload = await this.getPayloadsForRequestedInfos({
|
|
1376
1415
|
deltaRequestAddrInfos: deltaData.deltaRequestAddrInfos || [],
|
|
1377
1416
|
mySpace,
|
|
1378
1417
|
});
|
|
1379
|
-
|
|
1418
|
+
if (logalot) {
|
|
1419
|
+
console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`);
|
|
1420
|
+
}
|
|
1380
1421
|
// 3. Execute Merges (If applicable)
|
|
1381
1422
|
// Check if we have pending conflicts that we CAN resolve now that we have data.
|
|
1382
1423
|
// We look at the Saga History (Ack Frame) to find conflicts.
|
|
1383
1424
|
// Optimization: Do this only if we received payloads.
|
|
1384
1425
|
const mergeResultIbGibs = [];
|
|
1385
|
-
|
|
1426
|
+
if (logalot) {
|
|
1427
|
+
console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`);
|
|
1428
|
+
}
|
|
1386
1429
|
if (receivedPayloadIbGibs.length > 0) {
|
|
1387
|
-
|
|
1430
|
+
if (logalot) {
|
|
1431
|
+
console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`);
|
|
1432
|
+
}
|
|
1388
1433
|
// Find the Ack frame in history to get conflicts
|
|
1389
1434
|
// Optimization: Batch fetch history from `sagaIbGib.rel8ns.past`
|
|
1390
1435
|
// V1 timelines carry full history in `past`.
|
|
1391
1436
|
const pastAddrs = sagaIbGib.rel8ns?.past || [];
|
|
1392
|
-
|
|
1437
|
+
if (logalot) {
|
|
1438
|
+
console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`);
|
|
1439
|
+
}
|
|
1393
1440
|
const sagaHistory = await getFullSyncSagaHistory({
|
|
1394
1441
|
sagaIbGib,
|
|
1395
1442
|
space: mySpace,
|
|
@@ -1428,9 +1475,13 @@ export class SyncSagaCoordinator {
|
|
|
1428
1475
|
// We blindly attempt merge if we have both tips accessible?
|
|
1429
1476
|
// We need `receiverTip` (localAddr in Ack) and `senderTip` (remoteAddr).
|
|
1430
1477
|
// Check if we have receiverTip in space
|
|
1431
|
-
|
|
1478
|
+
if (logalot) {
|
|
1479
|
+
console.log(`${lc} [CONFLICT DEBUG] Attempting merge for conflict. ReceiverTip: ${receiverTip}, SenderTip: ${senderTip}`);
|
|
1480
|
+
}
|
|
1432
1481
|
const resRecTip = await getFromSpace({ addr: receiverTip, space: myTempSpace }); // Check myTempSpace for incoming data
|
|
1433
|
-
|
|
1482
|
+
if (logalot) {
|
|
1483
|
+
console.log(`${lc} [CONFLICT DEBUG] ReceiverTip found in myTempSpace: ${!!resRecTip.ibGibs?.[0]}`);
|
|
1484
|
+
}
|
|
1434
1485
|
if (resRecTip.success && resRecTip.ibGibs?.[0]) {
|
|
1435
1486
|
// We have the tip!
|
|
1436
1487
|
// Do we have the full history?
|
|
@@ -1445,7 +1496,9 @@ export class SyncSagaCoordinator {
|
|
|
1445
1496
|
metaspace,
|
|
1446
1497
|
});
|
|
1447
1498
|
if (mergeResult) {
|
|
1448
|
-
|
|
1499
|
+
if (logalot) {
|
|
1500
|
+
console.log(`${lc} [TEST DEBUG] Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1501
|
+
}
|
|
1449
1502
|
if (logalot) {
|
|
1450
1503
|
console.log(`${lc} Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1451
1504
|
}
|
|
@@ -1454,7 +1507,7 @@ export class SyncSagaCoordinator {
|
|
|
1454
1507
|
}
|
|
1455
1508
|
}
|
|
1456
1509
|
catch (e) {
|
|
1457
|
-
console.error(`${lc} Merge failed: ${e}`);
|
|
1510
|
+
console.error(`${lc} (NOT THROWN) Merge failed: ${e} (E: 491b464fc6f4857f52ff3df213105826)`);
|
|
1458
1511
|
// If merge fails, we might Abort or just continue?
|
|
1459
1512
|
}
|
|
1460
1513
|
}
|
|
@@ -1602,15 +1655,47 @@ export class SyncSagaCoordinator {
|
|
|
1602
1655
|
/**
|
|
1603
1656
|
* should throw if fails
|
|
1604
1657
|
*/
|
|
1605
|
-
async executeLocalCommit({ deltaFrame, sagaHistory, metaspace, localSpace, localTempSpace, identity, }) {
|
|
1658
|
+
async executeLocalCommit({ deltaFrame, commitFrame, sagaHistory, metaspace, localSpace, localTempSpace, identity, }) {
|
|
1606
1659
|
const lc = `${this.lc}[${this.executeLocalCommit.name}]`;
|
|
1607
1660
|
try {
|
|
1608
1661
|
if (logalot) {
|
|
1609
1662
|
console.log(`${lc} starting... (I: 6734980446b86a63c1af6e2e206de826)`);
|
|
1610
1663
|
}
|
|
1664
|
+
if (!deltaFrame && !commitFrame) {
|
|
1665
|
+
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)`);
|
|
1666
|
+
}
|
|
1667
|
+
else if (deltaFrame && commitFrame) {
|
|
1668
|
+
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)`);
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* Sync has a two-stage commit. The first is from a delta frame with
|
|
1672
|
+
* `proposeCommit: true`. That produces a commit frame, which on the
|
|
1673
|
+
* other end triggers the second leg.
|
|
1674
|
+
*/
|
|
1675
|
+
const isFirstCommitLeg = !!deltaFrame;
|
|
1676
|
+
const currentFrame = isFirstCommitLeg ? deltaFrame : commitFrame;
|
|
1677
|
+
if (!currentFrame) {
|
|
1678
|
+
throw new Error(`(UNEXPECTED) !currentFrame? something wrong with my logic. (E: 4ec0ce6625cc1d677bc902c839ca1a26)`);
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* we only want to register new ibgibs from the other end, so we
|
|
1682
|
+
* will compare the history payloads/push offers with the context
|
|
1683
|
+
* that provided those payloads.
|
|
1684
|
+
*
|
|
1685
|
+
* So we will filter out the history that we produced, which should
|
|
1686
|
+
* leave us only with externally created payload addrs.
|
|
1687
|
+
*
|
|
1688
|
+
* NOTE: I have this at the beginning of the function PURELY to get
|
|
1689
|
+
* a log value in to understand the context of this function's
|
|
1690
|
+
* output.
|
|
1691
|
+
*/
|
|
1692
|
+
const currentFrameOrigin = getSyncSagaFrameOrigin({ sagaFrame: currentFrame });
|
|
1693
|
+
if (logalot) {
|
|
1694
|
+
console.log(`${lc} currentFrameOrigin: ${currentFrameOrigin} (I: 3add8f8390c89743ae554bd3cc60b826)`);
|
|
1695
|
+
}
|
|
1611
1696
|
// #region validate/sanity
|
|
1612
|
-
if (!
|
|
1613
|
-
throw new Error(`(UNEXPECTED)
|
|
1697
|
+
if (!currentFrame.data) {
|
|
1698
|
+
throw new Error(`(UNEXPECTED) currentFrame.data falsy? (E: a8be68d48668d93d992d793834823826)`);
|
|
1614
1699
|
}
|
|
1615
1700
|
// #endregion validate/sanity
|
|
1616
1701
|
// * move all payload addrs from temp space to local space
|
|
@@ -1622,10 +1707,16 @@ export class SyncSagaCoordinator {
|
|
|
1622
1707
|
allPayloadAddrsDomainTransferred.push(addr);
|
|
1623
1708
|
}
|
|
1624
1709
|
};
|
|
1625
|
-
sagaHistory.
|
|
1710
|
+
sagaHistory.filter(x => {
|
|
1711
|
+
const frameExecutionContext = getSyncSagaFrameOrigin({ sagaFrame: x.sagaIbGib });
|
|
1712
|
+
return currentFrameOrigin === frameExecutionContext;
|
|
1713
|
+
}).forEach(x => {
|
|
1626
1714
|
if (!x.sagaIbGib.data) {
|
|
1627
1715
|
throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: 34d7f8cdee14717ce828878d98f89826)`);
|
|
1628
1716
|
}
|
|
1717
|
+
if (logalot) {
|
|
1718
|
+
console.log(`${lc}[${currentFrameOrigin}] history slice: ${pretty(x)} (I: e5a9436fb66b0df3183bd6d81be2ca26)`);
|
|
1719
|
+
}
|
|
1629
1720
|
x.msgStones.forEach(msgStone => {
|
|
1630
1721
|
if (!msgStone.data) {
|
|
1631
1722
|
throw new Error(`(UNEXPECTED) msgStone.data falsy? (E: 21406101f91847514cc759c8a7382f26)`);
|
|
@@ -1646,58 +1737,101 @@ export class SyncSagaCoordinator {
|
|
|
1646
1737
|
}
|
|
1647
1738
|
});
|
|
1648
1739
|
});
|
|
1740
|
+
if (logalot) {
|
|
1741
|
+
console.log(`${lc}[${currentFrameOrigin}] allPayloadAddrsDomainTransferred: ${allPayloadAddrsDomainTransferred.length > 0 ? allPayloadAddrsDomainTransferred.join(', ') : 'none'} (I: a1950eb3ca95bdc9ec18a4b8823e9826)`);
|
|
1742
|
+
}
|
|
1649
1743
|
// at this point, we have a list of ALL payload addrs retrieved.
|
|
1650
1744
|
let allPayloadIbGibsDomainTransferred = [];
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1745
|
+
if (allPayloadAddrsDomainTransferred.length > 0) {
|
|
1746
|
+
const resGetAllTransferred = await getFromSpace({ addrs: allPayloadAddrsDomainTransferred, space: localTempSpace });
|
|
1747
|
+
if (resGetAllTransferred.success && resGetAllTransferred.ibGibs && resGetAllTransferred.ibGibs.length === allPayloadAddrsDomainTransferred.length) {
|
|
1748
|
+
allPayloadIbGibsDomainTransferred = resGetAllTransferred.ibGibs.concat();
|
|
1749
|
+
}
|
|
1750
|
+
else {
|
|
1751
|
+
// errored out, gather info
|
|
1752
|
+
if (!resGetAllTransferred.rawResultIbGib) {
|
|
1753
|
+
throw new Error(`(UNEXPECTED) !resGetAllTransferred.rawResultIbGib falsy? (E: dc6cf8729668f4fbe8c024f887d97a26)`);
|
|
1754
|
+
}
|
|
1755
|
+
const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data;
|
|
1756
|
+
throw new Error(`(UNEXPECTED) we couldn't get all addrs transferred throughout the saga from the tempspace (${localTempSpace.ib})? addrsNotFound: ${addrsNotFound ?? []}. addrsErrored: ${addrsErrored ?? []}. errors: ${errors ?? []}(E: 222e341e634862b4d88ae7282584d826)`);
|
|
1659
1757
|
}
|
|
1660
|
-
const { addrsNotFound, addrsErrored, errors } = resGetAllTransferred.rawResultIbGib.data;
|
|
1661
|
-
throw new Error(`(UNEXPECTED) we couldn't get all addrs transferred throughout the saga from the tempspace (${localTempSpace.ib})? addrsNotFound: ${addrsNotFound ?? []}. addrsErrored: ${addrsErrored ?? []}. errors: ${errors ?? []}(E: 222e341e634862b4d88ae7282584d826)`);
|
|
1662
1758
|
}
|
|
1663
1759
|
// now we have all ibgibs transferred, first put them all the local space
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } = splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1669
|
-
// first register all non-tjp stones
|
|
1670
|
-
const nontjps = Object.values(mapWithoutTjps);
|
|
1671
|
-
for (const nontjp of nontjps) {
|
|
1672
|
-
await metaspace.registerNewIbGib({
|
|
1673
|
-
ibGib: nontjp,
|
|
1674
|
-
space: localSpace,
|
|
1675
|
-
});
|
|
1676
|
-
}
|
|
1677
|
-
// next register each timeline in order...
|
|
1678
|
-
// ...first the ones without dna...
|
|
1679
|
-
const timelinesByTjpAddr_NoDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
|
|
1680
|
-
const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
|
|
1681
|
-
for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
|
|
1682
|
-
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
1683
|
-
for (const ibGib of timelineIbGibs) {
|
|
1684
|
-
await metaspace.registerNewIbGib({
|
|
1685
|
-
ibGib,
|
|
1686
|
-
space: localSpace,
|
|
1687
|
-
});
|
|
1760
|
+
if (allPayloadIbGibsDomainTransferred.length === 0) {
|
|
1761
|
+
// nothing was synced
|
|
1762
|
+
if (logalot) {
|
|
1763
|
+
console.log(`${lc}[${currentFrameOrigin}] no changes on this end (I: fa30d18e83a87ee9e8487fbb5d632b26)`);
|
|
1688
1764
|
}
|
|
1689
1765
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1766
|
+
else {
|
|
1767
|
+
if (logalot) {
|
|
1768
|
+
console.log(`${lc}[${currentFrameOrigin}] ${allPayloadIbGibsDomainTransferred.length} changes detected (I: fa30d18e83a87ee9e8487fbb5d632b26)`);
|
|
1769
|
+
}
|
|
1770
|
+
if (logalot) {
|
|
1771
|
+
console.log(`${lc} put all into localSpace (${localSpace.ib}) starting... (I: d5e0d9870e380b61e80c729660058826)`);
|
|
1772
|
+
}
|
|
1773
|
+
const { payload_Dnas, payload_NonDnas } = await putInSpace_dnasThenNonDnas({
|
|
1774
|
+
ibGibs: allPayloadIbGibsDomainTransferred,
|
|
1775
|
+
space: localSpace
|
|
1776
|
+
});
|
|
1777
|
+
if (logalot) {
|
|
1778
|
+
console.log(`${lc} put all into localSpace (${localSpace.ib}) complete. (I: d5e0d9870e380b61e80c729660058826)`);
|
|
1779
|
+
}
|
|
1780
|
+
const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } = splitPerTjpAndOrDna({ ibGibs: payload_NonDnas, filterPrimitives: true });
|
|
1781
|
+
// first register all non-tjp stones
|
|
1782
|
+
if (logalot) {
|
|
1783
|
+
console.log(`${lc} register mapWithoutTjps starting... (I: 2b84d8f8dda85adde88696d8419bf726)`);
|
|
1784
|
+
}
|
|
1785
|
+
const nontjps = Object.values(mapWithoutTjps);
|
|
1786
|
+
for (const nontjp of nontjps) {
|
|
1787
|
+
if (logalot) {
|
|
1788
|
+
console.log(`${lc} registering ${getIbGibAddr({ ibGib: nontjp })} (I: 4647b4f42d27cffe0fbfce8846755826)`);
|
|
1789
|
+
}
|
|
1696
1790
|
await metaspace.registerNewIbGib({
|
|
1697
|
-
ibGib,
|
|
1791
|
+
ibGib: nontjp,
|
|
1698
1792
|
space: localSpace,
|
|
1699
1793
|
});
|
|
1700
1794
|
}
|
|
1795
|
+
if (logalot) {
|
|
1796
|
+
console.log(`${lc} mapWithoutTjps complete. (I: 2b84d8f8dda85adde88696d8419bf726)`);
|
|
1797
|
+
}
|
|
1798
|
+
// next register each timeline in order...
|
|
1799
|
+
// ...first the ones without dna...
|
|
1800
|
+
if (logalot) {
|
|
1801
|
+
console.log(`${lc} register mapWithTjp_NoDna starting... (I: 96e648e4db382499b8bfaa1b37c24826)`);
|
|
1802
|
+
}
|
|
1803
|
+
const timelinesByTjpAddr_NoDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_NoDna) });
|
|
1804
|
+
const tjpAddrs_NoDna = Object.keys(timelinesByTjpAddr_NoDna);
|
|
1805
|
+
for (const tjpAddr_NoDna of tjpAddrs_NoDna) {
|
|
1806
|
+
const timelineIbGibs = timelinesByTjpAddr_NoDna[tjpAddr_NoDna];
|
|
1807
|
+
for (const ibGib of timelineIbGibs) {
|
|
1808
|
+
await metaspace.registerNewIbGib({
|
|
1809
|
+
ibGib,
|
|
1810
|
+
space: localSpace,
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
if (logalot) {
|
|
1815
|
+
console.log(`${lc} register mapWithTjp_NoDna complete. (I: 96e648e4db382499b8bfaa1b37c24826)`);
|
|
1816
|
+
}
|
|
1817
|
+
// ...then the ones WITH dna.
|
|
1818
|
+
if (logalot) {
|
|
1819
|
+
console.log(`${lc} register mapWithTjp_YesDna starting... (I: d54a820e9442dee4681f6228a6795926)`);
|
|
1820
|
+
}
|
|
1821
|
+
const timelinesByTjpAddr_YesDna = getTimelinesGroupedByTjp({ ibGibs: Object.values(mapWithTjp_YesDna) });
|
|
1822
|
+
const tjpAddrs_YesDna = Object.keys(timelinesByTjpAddr_YesDna);
|
|
1823
|
+
for (const tjpAddr_YesDna of tjpAddrs_YesDna) {
|
|
1824
|
+
const timelineIbGibs = timelinesByTjpAddr_YesDna[tjpAddr_YesDna];
|
|
1825
|
+
for (const ibGib of timelineIbGibs) {
|
|
1826
|
+
await metaspace.registerNewIbGib({
|
|
1827
|
+
ibGib,
|
|
1828
|
+
space: localSpace,
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (logalot) {
|
|
1833
|
+
console.log(`${lc} register mapWithTjp_YesDna complete. (I: d54a820e9442dee4681f6228a6795926)`);
|
|
1834
|
+
}
|
|
1701
1835
|
}
|
|
1702
1836
|
}
|
|
1703
1837
|
catch (error) {
|
|
@@ -1760,46 +1894,55 @@ export class SyncSagaCoordinator {
|
|
|
1760
1894
|
if (logalot) {
|
|
1761
1895
|
console.log(`${lc} starting... (I: e179573bdd881202f8ba3168da1c3826)`);
|
|
1762
1896
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
const
|
|
1897
|
+
if (!sagaIbGib.data) {
|
|
1898
|
+
throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: cbc31dbb7d28b5b8c8cddb510d7d2826)`);
|
|
1899
|
+
}
|
|
1900
|
+
if (sagaIbGib.data.errors && sagaIbGib.data.errors.length > 0) {
|
|
1901
|
+
// our saga errored out but we already committed the darn
|
|
1902
|
+
// changes previously
|
|
1903
|
+
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)`);
|
|
1904
|
+
}
|
|
1905
|
+
else {
|
|
1906
|
+
// Sender Logic (Finalizing):
|
|
1907
|
+
// If we are here, we received a Commit frame from the Peer.
|
|
1908
|
+
// This implies the Peer has successfully committed.
|
|
1909
|
+
// We should now:
|
|
1910
|
+
// 1. Validate (implicitly done by receiving valid frame)
|
|
1911
|
+
// 2. Perform our own cleanup (Temp -> Dest, if applicable)
|
|
1912
|
+
// 3. Return saga completion.
|
|
1913
|
+
// one last validate entire history ?
|
|
1914
|
+
const history = await getFullSyncSagaHistory({
|
|
1781
1915
|
sagaIbGib,
|
|
1916
|
+
space: mySpace,
|
|
1917
|
+
});
|
|
1918
|
+
const validationErrors = await validateFullSyncSagaHistory({
|
|
1919
|
+
history,
|
|
1920
|
+
});
|
|
1921
|
+
if (validationErrors.length > 0) {
|
|
1922
|
+
const errorCommitFrame = await this.createCommitFrame({
|
|
1923
|
+
sagaIbGib,
|
|
1924
|
+
metaspace,
|
|
1925
|
+
mySpace,
|
|
1926
|
+
identity,
|
|
1927
|
+
errors: validationErrors,
|
|
1928
|
+
});
|
|
1929
|
+
return { frame: errorCommitFrame, }; /* <<<< returns early */
|
|
1930
|
+
}
|
|
1931
|
+
await this.executeLocalCommit({
|
|
1932
|
+
commitFrame: sagaIbGib,
|
|
1933
|
+
sagaHistory: history,
|
|
1934
|
+
localSpace: mySpace,
|
|
1935
|
+
localTempSpace: myTempSpace,
|
|
1782
1936
|
metaspace,
|
|
1783
|
-
mySpace,
|
|
1784
|
-
identity,
|
|
1785
|
-
errors: validationErrors,
|
|
1786
1937
|
});
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
metaspace,
|
|
1795
|
-
});
|
|
1796
|
-
// todo: implement explicit cleanup logic here and in peer
|
|
1797
|
-
console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
|
|
1798
|
-
if (logalot) {
|
|
1799
|
-
console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`);
|
|
1938
|
+
// todo: implement explicit cleanup logic here and in peer
|
|
1939
|
+
console.error(`${lc} NAG ERROR (NOT THROWN): implement cleanup logic, including add a cleanup method to the peer (E: 3a9a24befb98a981a88fbdbf52920e26)`);
|
|
1940
|
+
if (logalot) {
|
|
1941
|
+
console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`);
|
|
1942
|
+
}
|
|
1943
|
+
// the holy grail!
|
|
1944
|
+
return { sagaComplete: true };
|
|
1800
1945
|
}
|
|
1801
|
-
// the holy grail!
|
|
1802
|
-
return { sagaComplete: true };
|
|
1803
1946
|
}
|
|
1804
1947
|
catch (error) {
|
|
1805
1948
|
const emsg = `${lc} ${extractErrorMsg(error)}`;
|