@ibgib/core-gib 0.1.26 → 0.1.27
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/sync/sync-helpers.d.mts +16 -1
- package/dist/sync/sync-helpers.d.mts.map +1 -1
- package/dist/sync/sync-helpers.mjs +101 -4
- package/dist/sync/sync-helpers.mjs.map +1 -1
- 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 +30 -9
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +1 -0
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +17 -3
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +8 -0
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +29 -16
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +378 -392
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
- package/dist/sync/sync-types.d.mts +30 -1
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/dist/sync/sync-types.mjs +32 -0
- package/dist/sync/sync-types.mjs.map +1 -1
- package/package.json +2 -2
- package/src/sync/sync-helpers.mts +92 -4
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +30 -8
- package/src/sync/sync-peer/sync-peer-v1.mts +2 -0
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +14 -2
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +13 -5
- package/src/sync/sync-saga-coordinator.mts +408 -432
- package/src/sync/sync-saga-message/sync-saga-message-types.mts +18 -18
- package/src/sync/sync-types.mts +38 -1
|
@@ -19,21 +19,25 @@ import { putInSpace, getLatestAddrs, getFromSpace } from "../witness/space/space
|
|
|
19
19
|
import { KeystoneIbGib_V1 } from "../keystone/keystone-types.mjs";
|
|
20
20
|
import { KeystoneService_V1 } from "../keystone/keystone-service-v1.mjs";
|
|
21
21
|
import { MetaspaceService } from "../witness/space/metaspace/metaspace-types.mjs";
|
|
22
|
-
import {
|
|
23
|
-
|
|
22
|
+
import {
|
|
23
|
+
SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN,
|
|
24
|
+
} from "./sync-constants.mjs";
|
|
25
|
+
import {
|
|
26
|
+
appendToTimeline, createTimeline, Rel8nInfo, Rel8nRemovalInfo
|
|
27
|
+
} from "../timeline/timeline-api.mjs";
|
|
24
28
|
import {
|
|
25
29
|
SyncData_V1, SyncIbGib_V1, SyncConflictStrategy, SyncMode, SyncOptions,
|
|
26
30
|
SyncRel8ns_V1, DomainIbGibAnalysisInfo, NextSagaFrameInfo,
|
|
27
|
-
SYNC_CONFLICT_STRATEGY_VALID_VALUES,
|
|
28
|
-
|
|
31
|
+
SYNC_CONFLICT_STRATEGY_VALID_VALUES, HandleSagaResponseContextResult,
|
|
32
|
+
SyncExecutionContext,
|
|
33
|
+
SYNC_EXECUTION_CONTEXT_VALID_VALUES,
|
|
29
34
|
} from "./sync-types.mjs";
|
|
30
|
-
import { getSyncIb, getTempSpaceName, isPastFrame } from "./sync-helpers.mjs";
|
|
35
|
+
import { getExecutionContext, getSyncIb, getTempSpaceName, isPastFrame } from "./sync-helpers.mjs";
|
|
31
36
|
import { getDeltaDependencyGraph, getDependencyGraph, toFlatGraph } from "../common/other/graph-helper.mjs";
|
|
32
37
|
import {
|
|
33
38
|
SyncSagaMessageData_V1, SyncSagaMessageInitData_V1,
|
|
34
39
|
SyncSagaMessageAckData_V1, SyncSagaMessageDeltaData_V1,
|
|
35
|
-
SyncSagaMessageCommitData_V1, SyncSagaConflictInfo,
|
|
36
|
-
SyncSagaPushOfferInfo,
|
|
40
|
+
SyncSagaMessageCommitData_V1, SyncSagaConflictInfo, SyncSagaPushOfferInfo,
|
|
37
41
|
SyncSagaRequestAddrInfo,
|
|
38
42
|
} from "./sync-saga-message/sync-saga-message-types.mjs";
|
|
39
43
|
import { getSyncSagaMessageIb } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
@@ -49,14 +53,12 @@ import { mergeDivergentTimelines } from "./strategies/conflict-optimistic.mjs";
|
|
|
49
53
|
import { getSyncSagaMessageFromFrame } from "./sync-saga-message/sync-saga-message-helpers.mjs";
|
|
50
54
|
import { fnObs } from "../common/pubsub/observer/observer-helper.mjs";
|
|
51
55
|
import { ErrorIbGib_V1 } from "../common/error/error-types.mjs";
|
|
52
|
-
import {
|
|
53
|
-
IbGibSpaceResultData, IbGibSpaceResultIbGib, IbGibSpaceResultRel8ns
|
|
54
|
-
} from "../witness/space/space-types.mjs";
|
|
56
|
+
import { IbGibSpaceResultData, IbGibSpaceResultIbGib, IbGibSpaceResultRel8ns } from "../witness/space/space-types.mjs";
|
|
55
57
|
import { FlatIbGibGraph } from "../common/other/graph-types.mjs";
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
// const logalot = GLOBAL_LOG_A_LOT || true;
|
|
59
|
-
const logalot =
|
|
61
|
+
const logalot = true;
|
|
60
62
|
const logalotControlDomain = true;
|
|
61
63
|
const lcControlDomain = '[ControlDomain]';
|
|
62
64
|
|
|
@@ -202,7 +204,7 @@ export class SyncSagaCoordinator {
|
|
|
202
204
|
* @returns next context result if another round, else if commit returns
|
|
203
205
|
* null
|
|
204
206
|
*/
|
|
205
|
-
public async
|
|
207
|
+
public async continueSync({
|
|
206
208
|
sagaContext,
|
|
207
209
|
mySpace,
|
|
208
210
|
myTempSpace,
|
|
@@ -223,7 +225,7 @@ export class SyncSagaCoordinator {
|
|
|
223
225
|
identitySecret?: string,
|
|
224
226
|
metaspace: MetaspaceService,
|
|
225
227
|
}): Promise<SyncSagaContextIbGib_V1 | null> {
|
|
226
|
-
const lc = `${this.lc}[${this.
|
|
228
|
+
const lc = `${this.lc}[${this.continueSync.name}]`;
|
|
227
229
|
try {
|
|
228
230
|
if (logalot) { console.log(`${lc} starting... (I: f64e08bf77d1425378601f380384ec26)`); }
|
|
229
231
|
|
|
@@ -720,7 +722,7 @@ export class SyncSagaCoordinator {
|
|
|
720
722
|
localSpace,
|
|
721
723
|
});
|
|
722
724
|
|
|
723
|
-
|
|
725
|
+
if (logalot) { console.log(`${lc} sagaFrame (init): ${pretty(sagaFrame)} (I: b3d6a8be69248f18713cc3073cb08626)`); }
|
|
724
726
|
|
|
725
727
|
return { initFrame: sagaFrame, initDomainGraph: fullGraph };
|
|
726
728
|
} catch (error) {
|
|
@@ -860,7 +862,7 @@ export class SyncSagaCoordinator {
|
|
|
860
862
|
if (logalot) { console.log(`${lc} sagaIbGib: ${pretty(sagaIbGib)} (I: 1b99d87d262e9d18d8a607a80b1a0126)`); }
|
|
861
863
|
|
|
862
864
|
// Get Stage from Stone (or Frame for Init fallback)
|
|
863
|
-
const { stage, messageData } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space:
|
|
865
|
+
const { stage, messageData } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space: mySpace });
|
|
864
866
|
|
|
865
867
|
if (logalot) { console.log(`${lc} handling frame stage: ${stage}`); }
|
|
866
868
|
|
|
@@ -875,39 +877,44 @@ export class SyncSagaCoordinator {
|
|
|
875
877
|
nextFrameInfo = await this.handleInitFrame({
|
|
876
878
|
sagaIbGib,
|
|
877
879
|
messageData: messageData as SyncSagaMessageInitData_V1,
|
|
878
|
-
metaspace,
|
|
879
|
-
|
|
880
|
-
myTempSpace: myTempSpace,
|
|
881
|
-
identity,
|
|
882
|
-
identitySecret
|
|
880
|
+
metaspace, mySpace, myTempSpace,
|
|
881
|
+
identity, identitySecret
|
|
883
882
|
});
|
|
884
883
|
break;
|
|
885
884
|
|
|
886
885
|
case SyncStage.ack:
|
|
887
886
|
if (!initDomainGraph) { throw new Error(`(UNEXPECTED) initDomainGraph falsy on the sender? (E: a3d758ad954829aba88663188eafc826)`); }
|
|
888
887
|
nextFrameInfo = await this.handleAckFrame({
|
|
888
|
+
sagaContext,
|
|
889
889
|
sagaIbGib,
|
|
890
|
-
srcGraph,
|
|
891
890
|
initDomainGraph,
|
|
892
|
-
metaspace,
|
|
893
|
-
destSpace: mySpace,
|
|
894
|
-
tempSpace: myTempSpace,
|
|
891
|
+
metaspace, mySpace, myTempSpace,
|
|
895
892
|
identity,
|
|
896
893
|
});
|
|
897
894
|
break;
|
|
898
895
|
|
|
899
896
|
case SyncStage.delta:
|
|
900
|
-
nextFrameInfo = await this.handleDeltaFrame({
|
|
897
|
+
nextFrameInfo = await this.handleDeltaFrame({
|
|
898
|
+
sagaContext,
|
|
899
|
+
sagaIbGib,
|
|
900
|
+
srcGraph,
|
|
901
|
+
metaspace,
|
|
902
|
+
mySpace,
|
|
903
|
+
myTempSpace,
|
|
904
|
+
identity,
|
|
905
|
+
});
|
|
901
906
|
break;
|
|
902
907
|
|
|
903
908
|
case SyncStage.commit:
|
|
904
|
-
nextFrameInfo = await this.handleCommitFrame({ sagaIbGib, metaspace,
|
|
909
|
+
nextFrameInfo = await this.handleCommitFrame({ sagaIbGib, metaspace, mySpace: mySpace, myTempSpace: myTempSpace, identity, });
|
|
905
910
|
break;
|
|
906
911
|
|
|
907
912
|
default:
|
|
908
913
|
throw new Error(`${lc} (UNEXPECTED) Unknown sync stage: ${stage} (E: 9c2b4c8a6d34469f8263544710183355)`);
|
|
909
914
|
}
|
|
910
915
|
|
|
916
|
+
if (logalot) { console.log(`${lc} nextFrameInfo: ${nextFrameInfo ? pretty(nextFrameInfo) : 'undefined'} (I: a8ad281ca8e89385686d18327a105726)`); }
|
|
917
|
+
|
|
911
918
|
return { errorMsg: undefined, nextFrameInfo, }
|
|
912
919
|
|
|
913
920
|
} catch (error) {
|
|
@@ -930,7 +937,7 @@ export class SyncSagaCoordinator {
|
|
|
930
937
|
* The Receiver performs Gap Analysis here:
|
|
931
938
|
* 1. Compares Sender's Knowledge Vector (in `sagaIbGib`) vs Receiver's Local KV.
|
|
932
939
|
* 2. Identifies what Sender needs (`pushOfferAddrs`).
|
|
933
|
-
* 3. Identifies what Receiver needs (`
|
|
940
|
+
* 3. Identifies what Receiver needs (`deltaRequestAddrInfos`).
|
|
934
941
|
* 4. Returns an `Ack` frame containing these lists.
|
|
935
942
|
*/
|
|
936
943
|
protected async handleInitFrame({
|
|
@@ -1183,7 +1190,7 @@ export class SyncSagaCoordinator {
|
|
|
1183
1190
|
|
|
1184
1191
|
const ackStone = await this.createSyncMsgStone({
|
|
1185
1192
|
data: ackData,
|
|
1186
|
-
localSpace:
|
|
1193
|
+
localSpace: mySpace,
|
|
1187
1194
|
metaspace,
|
|
1188
1195
|
});
|
|
1189
1196
|
if (logalot) { console.log(`${lc} ackStone created: ${pretty(ackStone)} (I: 313708132dd53ff946befb7833657826)`); }
|
|
@@ -1274,22 +1281,29 @@ export class SyncSagaCoordinator {
|
|
|
1274
1281
|
* **Execution Context**: **Sender (Local)**.
|
|
1275
1282
|
*
|
|
1276
1283
|
* The Sender reacts to the Receiver's requirements:
|
|
1277
|
-
* 1.
|
|
1278
|
-
*
|
|
1284
|
+
* 1. `deltaRequestAddrInfos`: Receiver wants this data. Sender takes this
|
|
1285
|
+
* into account, plus gathers it from `initDomainGraph` and puts them in
|
|
1286
|
+
* `payloadIbGibs` (for next frame).
|
|
1287
|
+
* 2. `pushOfferAddrs`: Receiver has newer data. these should have been
|
|
1288
|
+
* included in the incoming context from the receiver..
|
|
1279
1289
|
*
|
|
1280
1290
|
* Returns a `Delta` frame.
|
|
1281
1291
|
*/
|
|
1282
1292
|
protected async handleAckFrame({
|
|
1293
|
+
sagaContext,
|
|
1283
1294
|
sagaIbGib,
|
|
1284
|
-
srcGraph,
|
|
1285
1295
|
initDomainGraph,
|
|
1286
|
-
|
|
1287
|
-
tempSpace,
|
|
1288
|
-
metaspace,
|
|
1296
|
+
mySpace, myTempSpace, metaspace,
|
|
1289
1297
|
identity,
|
|
1290
1298
|
}: {
|
|
1299
|
+
/**
|
|
1300
|
+
* todo: figure out if we need to do something about incoming push offer payload domain ibgibs
|
|
1301
|
+
* I'm adding this because we should be checking incoming payloads
|
|
1302
|
+
* right? for push offers? This is when the receiver had new ibgibs.
|
|
1303
|
+
* Not sure if I need to put this here though...
|
|
1304
|
+
*/
|
|
1305
|
+
sagaContext: SyncSagaContextIbGib_V1,
|
|
1291
1306
|
sagaIbGib: SyncIbGib_V1,
|
|
1292
|
-
srcGraph: { [addr: string]: IbGib_V1 },
|
|
1293
1307
|
/**
|
|
1294
1308
|
* This is the initial dependency graph of all domain ibgibs passed in
|
|
1295
1309
|
* to the original {@link sync} call.
|
|
@@ -1297,8 +1311,8 @@ export class SyncSagaCoordinator {
|
|
|
1297
1311
|
* if we're executing on the sender, this will be populated
|
|
1298
1312
|
*/
|
|
1299
1313
|
initDomainGraph: FlatIbGibGraph,
|
|
1300
|
-
|
|
1301
|
-
|
|
1314
|
+
mySpace: IbGibSpaceAny,
|
|
1315
|
+
myTempSpace: IbGibSpaceAny,
|
|
1302
1316
|
metaspace: MetaspaceService,
|
|
1303
1317
|
identity?: KeystoneIbGib_V1,
|
|
1304
1318
|
}): Promise<NextSagaFrameInfo> {
|
|
@@ -1306,9 +1320,10 @@ export class SyncSagaCoordinator {
|
|
|
1306
1320
|
try {
|
|
1307
1321
|
if (logalot) { console.log(`${lc} starting... (I: 605b6860e898267a5b50c6d85704be26)`); }
|
|
1308
1322
|
|
|
1309
|
-
const { messageData, } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space:
|
|
1323
|
+
const { messageData, } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space: mySpace });
|
|
1310
1324
|
const ackData = messageData as SyncSagaMessageAckData_V1;
|
|
1311
1325
|
|
|
1326
|
+
// #region sanity/validation
|
|
1312
1327
|
if (!ackData) {
|
|
1313
1328
|
throw new Error(`${lc} ackData falsy (E: 3b8415edc876084c88a25b98e2d55826)`);
|
|
1314
1329
|
}
|
|
@@ -1316,6 +1331,8 @@ export class SyncSagaCoordinator {
|
|
|
1316
1331
|
throw new Error(`${lc} Invalid ack frame: ackData.stage !== SyncStage.ack (E: 2e8b0a94b5954a66a6a1a7a0b3f5b7a1)`);
|
|
1317
1332
|
}
|
|
1318
1333
|
if (logalot) { console.log(`${lc} ackData: ${pretty(ackData)} (I: 7f8e9d0a1b2c3d4e5f6g7h8i9j0k)`); }
|
|
1334
|
+
if (!sagaIbGib.data) { throw new Error(`(UNEXPECTED) sagaIbGib.data falsy? (E: 385e389610282aa9c5dbe4083adbde26)`); }
|
|
1335
|
+
// #region sanity/validation
|
|
1319
1336
|
|
|
1320
1337
|
// 1. Check for Conflicts
|
|
1321
1338
|
const conflicts = ackData.conflicts || [];
|
|
@@ -1334,7 +1351,12 @@ export class SyncSagaCoordinator {
|
|
|
1334
1351
|
|
|
1335
1352
|
// at this point, if we have conflicts, they are non-terminal
|
|
1336
1353
|
|
|
1337
|
-
|
|
1354
|
+
/**
|
|
1355
|
+
* at this point, we only request ibgibs for conflicted timelines.
|
|
1356
|
+
* If the receiver had known of any ibgibs this sender needed, it
|
|
1357
|
+
* would have been in the push offer.
|
|
1358
|
+
*/
|
|
1359
|
+
const outgoingDeltaAddrRequestInfos: SyncSagaRequestAddrInfo[] = []; // Additional requests for merging
|
|
1338
1360
|
|
|
1339
1361
|
if (conflicts.length > 0) {
|
|
1340
1362
|
console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
|
|
@@ -1346,8 +1368,8 @@ export class SyncSagaCoordinator {
|
|
|
1346
1368
|
// 4. (Later in Delta Phase) Perform Merge.
|
|
1347
1369
|
|
|
1348
1370
|
// BUT: The Delta Phase is usually generic "Send me these Addrs".
|
|
1349
|
-
// If we just add to `
|
|
1350
|
-
// wait. `ackData.
|
|
1371
|
+
// If we just add to `deltaRequestAddrInfos` (which are requests for Sender to send to Receiver?),
|
|
1372
|
+
// wait. `ackData.deltaRequestAddrInfos` are what RECEIVER wants from SENDER.
|
|
1351
1373
|
|
|
1352
1374
|
// We (Sender) are processing the Ack.
|
|
1353
1375
|
// We need to request data FROM Receiver.
|
|
@@ -1375,6 +1397,7 @@ export class SyncSagaCoordinator {
|
|
|
1375
1397
|
|
|
1376
1398
|
throw new Error(`conflicts not (re)implemented yet (E: 3b7d0819f83842a6de3ae988819bc826)`);
|
|
1377
1399
|
|
|
1400
|
+
|
|
1378
1401
|
// const { timelineAddrs, localAddr: receiverTip, remoteAddr: senderTip } = conflict;
|
|
1379
1402
|
|
|
1380
1403
|
// // Sender History
|
|
@@ -1432,8 +1455,8 @@ export class SyncSagaCoordinator {
|
|
|
1432
1455
|
// // For each receiver-only frame, get its DELTA dependency graph (minus LCA deps)
|
|
1433
1456
|
// for (const addr of receiverOnlyAddrs) {
|
|
1434
1457
|
// // Add the frame itself first
|
|
1435
|
-
// if (!
|
|
1436
|
-
//
|
|
1458
|
+
// if (!outgoingDeltaAddrRequestInfos.includes(addr)) {
|
|
1459
|
+
// outgoingDeltaAddrRequestInfos.push(addr);
|
|
1437
1460
|
// }
|
|
1438
1461
|
|
|
1439
1462
|
// // Get the frame's delta dependencies (skip LCA's deps)
|
|
@@ -1452,8 +1475,8 @@ export class SyncSagaCoordinator {
|
|
|
1452
1475
|
// if (frameDeltaDeps) {
|
|
1453
1476
|
// // Add all delta dependencies (Object.keys gives us the addresses)
|
|
1454
1477
|
// Object.keys(frameDeltaDeps).forEach(depAddr => {
|
|
1455
|
-
// if (!
|
|
1456
|
-
//
|
|
1478
|
+
// if (!outgoingDeltaAddrRequestInfos.includes(depAddr) && !skipAddrsSet.has(depAddr)) {
|
|
1479
|
+
// outgoingDeltaAddrRequestInfos.push(depAddr);
|
|
1457
1480
|
// }
|
|
1458
1481
|
// });
|
|
1459
1482
|
// }
|
|
@@ -1463,119 +1486,59 @@ export class SyncSagaCoordinator {
|
|
|
1463
1486
|
// }
|
|
1464
1487
|
// }
|
|
1465
1488
|
|
|
1466
|
-
// console.log(`${lc} [CONFLICT DEBUG] Total merge requests (frames + delta deps): ${
|
|
1489
|
+
// console.log(`${lc} [CONFLICT DEBUG] Total merge requests (frames + delta deps): ${outgoingDeltaAddrRequestInfos.length}`);
|
|
1467
1490
|
// } else {
|
|
1468
1491
|
// console.log(`${lc} [CONFLICT DEBUG] No receiver-only frames found for this conflict`);
|
|
1469
1492
|
// }
|
|
1470
1493
|
}
|
|
1471
1494
|
|
|
1472
|
-
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts.
|
|
1495
|
+
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingDeltaAddrRequestInfos: ${outgoingDeltaAddrRequestInfos.length}`);
|
|
1473
1496
|
} else {
|
|
1474
1497
|
console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`);
|
|
1475
1498
|
}
|
|
1476
1499
|
|
|
1477
1500
|
// 2. Prepare Delta Payload (What Receiver Requesting + Our Conflict Logic)
|
|
1478
1501
|
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
// 2. Process Delta Requests (Push Payload)
|
|
1492
|
-
// [NEW] Smart Diff: Use knowledgeVector to skip dependencies
|
|
1493
|
-
// const useThisFunction = getDeltaDependencyGraph({ ibGibAddr: '', latestCommonFrameAddr: '', space: })
|
|
1494
|
-
const skipAddrs = new Set<string>();
|
|
1495
|
-
if (ackData.knowledgeVector) {
|
|
1496
|
-
Object.values(ackData.knowledgeVector).forEach(addrs => {
|
|
1497
|
-
// addrs.forEach(a => skipAddrs.add(a));
|
|
1498
|
-
});
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
const payloadIbGibs: IbGib_V1[] = [];
|
|
1502
|
-
// Gather all tips to sync first
|
|
1503
|
-
const tipsToSync: IbGib_V1[] = [];
|
|
1504
|
-
for (const addr of deltaReqAddrs) {
|
|
1505
|
-
// let ibGib = srcGraph[addr];
|
|
1506
|
-
// if (!ibGib) {
|
|
1507
|
-
// const res = await getFromSpace({ addr, space: destSpace });
|
|
1508
|
-
// if (res.ibGibs && res.ibGibs.length > 0) {
|
|
1509
|
-
// ibGib = res.ibGibs[0];
|
|
1510
|
-
// }
|
|
1511
|
-
// }
|
|
1512
|
-
// if (ibGib) {
|
|
1513
|
-
// tipsToSync.push(ibGib);
|
|
1514
|
-
// } else {
|
|
1515
|
-
// throw new Error(`${lc} Requested addr not found: ${addr} (E: d41d59cff4a887f6414c3e92eabd8e26)`);
|
|
1516
|
-
// }
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
// Calculate Dependency Graph for ALL tips, effectively utilizing common history
|
|
1520
|
-
// Pass skipAddrs to `getDependencyGraph` or gather manually.
|
|
1521
|
-
// `getDependencyGraph` takes a single ibGib.
|
|
1522
|
-
// We can optimize by doing it for each tip and unioning the result?
|
|
1523
|
-
// Or `graph-helper` could support `ibGibs: []`. It currently takes `ibGib`.
|
|
1524
|
-
// We will loop.
|
|
1525
|
-
|
|
1526
|
-
const allDepsSet = new Set<string>();
|
|
1527
|
-
|
|
1528
|
-
for (const tip of tipsToSync) {
|
|
1529
|
-
// Always include the tip itself
|
|
1530
|
-
const tipAddr = getIbGibAddr({ ibGib: tip });
|
|
1531
|
-
// Only process if not skipped (though deltaReq implies they barely just asked for it)
|
|
1532
|
-
// But detailed deps might be skipped.
|
|
1533
|
-
|
|
1534
|
-
// Get Graph with Skips
|
|
1535
|
-
// Logic: "Give me everything related to Tip, EXCEPT X, Y, Z"
|
|
1536
|
-
const deps = await getDependencyGraph({
|
|
1537
|
-
ibGib: tip,
|
|
1538
|
-
space: destSpace,
|
|
1539
|
-
skipAddrs: Array.from(skipAddrs)
|
|
1540
|
-
});
|
|
1541
|
-
|
|
1542
|
-
// [FIX] Ensure Tip is included if not in deps (e.g. constant with no rel8ns)
|
|
1543
|
-
let tipIncluded = false;
|
|
1544
|
-
|
|
1545
|
-
if (deps) {
|
|
1546
|
-
Object.values(deps).forEach(d => {
|
|
1547
|
-
const dAddr = getIbGibAddr({ ibGib: d });
|
|
1548
|
-
if (!allDepsSet.has(dAddr)) {
|
|
1549
|
-
allDepsSet.add(dAddr);
|
|
1550
|
-
payloadIbGibs.push(d);
|
|
1551
|
-
}
|
|
1552
|
-
if (dAddr === tipAddr) { tipIncluded = true; }
|
|
1553
|
-
});
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
if (!tipIncluded && !skipAddrs.has(tipAddr)) {
|
|
1557
|
-
if (logalot) { console.log(`${lc} Tip not in deps, adding explicitly: ${tipAddr}`); }
|
|
1558
|
-
if (!allDepsSet.has(tipAddr)) {
|
|
1559
|
-
allDepsSet.add(tipAddr);
|
|
1560
|
-
payloadIbGibs.push(tip);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1502
|
+
/**
|
|
1503
|
+
* these were requested addrs on the INCOMING frame (the ack data).
|
|
1504
|
+
*
|
|
1505
|
+
* This is in contrast to any OUTGOING requests we make in this
|
|
1506
|
+
* method.
|
|
1507
|
+
*/
|
|
1508
|
+
const payloadIbGibsDomain = await this.getPayloadsForRequestedInfos({
|
|
1509
|
+
deltaRequestAddrInfos: ackData.deltaRequestAddrInfos || [],
|
|
1510
|
+
mySpace,
|
|
1511
|
+
});
|
|
1564
1512
|
|
|
1565
1513
|
// 3. Create Delta Frame
|
|
1566
|
-
const sagaId = ackData.sagaId;
|
|
1567
1514
|
const deltaData: SyncSagaMessageDeltaData_V1 = {
|
|
1568
|
-
sagaId: sagaIbGib.data
|
|
1515
|
+
sagaId: sagaIbGib.data.uuid,
|
|
1569
1516
|
stage: SyncStage.delta,
|
|
1570
|
-
|
|
1571
|
-
|
|
1517
|
+
/**
|
|
1518
|
+
* we're sending these domain ibgibs as payload (they were
|
|
1519
|
+
* requested by receiver)
|
|
1520
|
+
*/
|
|
1521
|
+
payloadAddrsDomain: payloadIbGibsDomain.length > 0 ?
|
|
1522
|
+
payloadIbGibsDomain.map(x => getIbGibAddr({ ibGib: x })) :
|
|
1523
|
+
undefined,
|
|
1524
|
+
/**
|
|
1525
|
+
* we're asking for these addrs
|
|
1526
|
+
*/
|
|
1527
|
+
deltaRequestAddrInfos: outgoingDeltaAddrRequestInfos.length > 0 ?
|
|
1528
|
+
outgoingDeltaAddrRequestInfos :
|
|
1529
|
+
undefined,
|
|
1530
|
+
/**
|
|
1531
|
+
* if we have no changes and request none, propose commit to
|
|
1532
|
+
* finish the sync transaction.
|
|
1533
|
+
*/
|
|
1534
|
+
proposeCommit: payloadIbGibsDomain.length === 0 && outgoingDeltaAddrRequestInfos.length === 0,
|
|
1572
1535
|
};
|
|
1573
1536
|
|
|
1574
1537
|
if (logalot) { console.log(`${lc} Creating Delta Stone. Data stage: ${deltaData.stage}`); }
|
|
1575
1538
|
|
|
1576
1539
|
const deltaStone = await this.createSyncMsgStone({
|
|
1577
1540
|
data: deltaData,
|
|
1578
|
-
localSpace:
|
|
1541
|
+
localSpace: mySpace,
|
|
1579
1542
|
metaspace,
|
|
1580
1543
|
});
|
|
1581
1544
|
|
|
@@ -1583,7 +1546,7 @@ export class SyncSagaCoordinator {
|
|
|
1583
1546
|
prevSagaIbGib: sagaIbGib,
|
|
1584
1547
|
msgStones: [deltaStone],
|
|
1585
1548
|
sessionIdentity: identity,
|
|
1586
|
-
localSpace:
|
|
1549
|
+
localSpace: mySpace,
|
|
1587
1550
|
metaspace,
|
|
1588
1551
|
});
|
|
1589
1552
|
|
|
@@ -1593,9 +1556,71 @@ export class SyncSagaCoordinator {
|
|
|
1593
1556
|
const payloadIbGibsControl: IbGib_V1[] = [deltaFrame, deltaStone];
|
|
1594
1557
|
if (identity) { payloadIbGibsControl.push(identity); }
|
|
1595
1558
|
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1559
|
+
return { frame: deltaFrame, payloadIbGibsDomain, };
|
|
1560
|
+
} catch (error) {
|
|
1561
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1562
|
+
throw error;
|
|
1563
|
+
} finally {
|
|
1564
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
private async getPayloadsForRequestedInfos({
|
|
1569
|
+
deltaRequestAddrInfos,
|
|
1570
|
+
mySpace,
|
|
1571
|
+
}: {
|
|
1572
|
+
deltaRequestAddrInfos: SyncSagaRequestAddrInfo[];
|
|
1573
|
+
mySpace: IbGibSpaceAny;
|
|
1574
|
+
}): Promise<IbGib_V1[]> {
|
|
1575
|
+
const lc = `${this.lc}[${this.getPayloadsForRequestedInfos.name}]`;
|
|
1576
|
+
try {
|
|
1577
|
+
if (logalot) { console.log(`${lc} starting... (I: 4fe13d0d80050f20a8b74ba80cee5826)`); }
|
|
1578
|
+
/**
|
|
1579
|
+
* graph of ibgibs we will send to the receiver. addr-based, so will
|
|
1580
|
+
* already be unique (no need to call `unique` on the domains
|
|
1581
|
+
* ibgibs)
|
|
1582
|
+
*/
|
|
1583
|
+
const outgoingPayloadIbGibsDomainGraph: FlatIbGibGraph = {};
|
|
1584
|
+
for (const { addr, latestAddrAlreadyHave } of deltaRequestAddrInfos) {
|
|
1585
|
+
let deltaDepGraph: FlatIbGibGraph;
|
|
1586
|
+
if (latestAddrAlreadyHave) {
|
|
1587
|
+
// already has some, so only get the delta
|
|
1588
|
+
// remember: if we didn't have the other's latest addr, then
|
|
1589
|
+
// this would be in the conflicts not requested addrs
|
|
1590
|
+
deltaDepGraph = await getDeltaDependencyGraph({
|
|
1591
|
+
ibGibAddr: addr,
|
|
1592
|
+
latestCommonFrameAddr: latestAddrAlreadyHave,
|
|
1593
|
+
space: mySpace,
|
|
1594
|
+
live: true,
|
|
1595
|
+
});
|
|
1596
|
+
} else {
|
|
1597
|
+
// doesn't have anything, so get the entire dependency graph
|
|
1598
|
+
// INEFFICIENT: we've already gotten all of the domain
|
|
1599
|
+
// dependencies in initDomainGraph, but getDependencyGraph
|
|
1600
|
+
// only works against a space so we are going to rerun this.
|
|
1601
|
+
// an optimization would be to adapt/create a new
|
|
1602
|
+
// getDependencyGraph to work against an existing flat ibgib
|
|
1603
|
+
// map.
|
|
1604
|
+
deltaDepGraph = await getDependencyGraph({
|
|
1605
|
+
ibGibAddr: addr,
|
|
1606
|
+
space: mySpace,
|
|
1607
|
+
live: true,
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
const depGraphSize = Object.keys(deltaDepGraph).length;
|
|
1612
|
+
if (depGraphSize === 0) {
|
|
1613
|
+
throw new Error(`(UNEXPECTED) couldn't get requested addrs in mySpace (${mySpace.ib})? How did the receiver know to ask for these addrs if they weren't in our original graph? (E: 281eaebcdf77dd73e8245b2872100826)`);
|
|
1614
|
+
} else {
|
|
1615
|
+
// we have dependencies!
|
|
1616
|
+
Object.values(deltaDepGraph).forEach(x => {
|
|
1617
|
+
outgoingPayloadIbGibsDomainGraph[getIbGibAddr({ ibGib: x })] = x;
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
const result = Object.values(outgoingPayloadIbGibsDomainGraph);
|
|
1623
|
+
return result;
|
|
1599
1624
|
} catch (error) {
|
|
1600
1625
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1601
1626
|
throw error;
|
|
@@ -1615,313 +1640,192 @@ export class SyncSagaCoordinator {
|
|
|
1615
1640
|
* 3. **Completion**: If no more requests, transitions to `Commit`.
|
|
1616
1641
|
*/
|
|
1617
1642
|
protected async handleDeltaFrame({
|
|
1643
|
+
sagaContext,
|
|
1618
1644
|
sagaIbGib,
|
|
1619
1645
|
srcGraph,
|
|
1620
|
-
|
|
1621
|
-
|
|
1646
|
+
mySpace,
|
|
1647
|
+
myTempSpace,
|
|
1622
1648
|
metaspace,
|
|
1623
1649
|
identity,
|
|
1624
1650
|
}: {
|
|
1651
|
+
sagaContext: SyncSagaContextIbGib_V1,
|
|
1625
1652
|
sagaIbGib: SyncIbGib_V1,
|
|
1626
1653
|
srcGraph: { [addr: string]: IbGib_V1 },
|
|
1627
|
-
|
|
1628
|
-
|
|
1654
|
+
mySpace: IbGibSpaceAny,
|
|
1655
|
+
myTempSpace: IbGibSpaceAny,
|
|
1629
1656
|
metaspace: MetaspaceService,
|
|
1630
1657
|
identity?: KeystoneIbGib_V1,
|
|
1631
1658
|
}): Promise<NextSagaFrameInfo> {
|
|
1632
1659
|
const lc = `${this.lc}[${this.handleDeltaFrame.name}]`;
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
const { messageData } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space: tempSpace });
|
|
1636
|
-
const deltaData = messageData as SyncSagaMessageDeltaData_V1;
|
|
1637
|
-
|
|
1638
|
-
if (!deltaData) {
|
|
1639
|
-
throw new Error(`${lc} deltaData falsy (E: 7c28c8d8f08a4421b8344e6727271421)`);
|
|
1640
|
-
}
|
|
1641
|
-
if (deltaData.stage !== SyncStage.delta) {
|
|
1642
|
-
throw new Error(`${lc} Invalid delta frame: deltaData.stage !== SyncStage.delta (E: 0c28c8d8f08a4421b8344e6727271421)`);
|
|
1643
|
-
}
|
|
1644
|
-
if (logalot) { console.log(`${lc} deltaData: ${pretty(deltaData)} (I: a76008681df458cfbcdc4848f825a826)`); }
|
|
1645
|
-
|
|
1646
|
-
console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`);
|
|
1647
|
-
|
|
1648
|
-
const payloadAddrs = deltaData.payloadAddrs || [];
|
|
1649
|
-
const peerRequests = deltaData.requests || [];
|
|
1650
|
-
const peerProposesCommit = deltaData.proposeCommit || false;
|
|
1651
|
-
|
|
1652
|
-
// 1. Process Received Payload (Ingest)
|
|
1653
|
-
const receivedPayloadIbGibs: IbGib_V1[] = [];
|
|
1654
|
-
if (payloadAddrs.length > 0) {
|
|
1655
|
-
// We use `payloadAddrs` as the manifest.
|
|
1656
|
-
// The ACTUAL collection of ibGibs should be available via `getFromSpace`
|
|
1657
|
-
// assuming the "Transport" layer put them there implicitly?
|
|
1658
|
-
// OR, if we are local-only, we just get them.
|
|
1659
|
-
// The `handleDeltaFrame` contract assumes data is reachable in `space`.
|
|
1660
|
-
|
|
1661
|
-
const res = await getFromSpace({
|
|
1662
|
-
addrs: payloadAddrs,
|
|
1663
|
-
space: tempSpace, // Incoming data is in tempSpace
|
|
1664
|
-
});
|
|
1665
|
-
if (res.ibGibs) {
|
|
1666
|
-
receivedPayloadIbGibs.push(...res.ibGibs);
|
|
1667
|
-
// Also put them? `getFromSpace` retrieves. If they are in space, they are persisted.
|
|
1668
|
-
// If this is a Temp Space, they are safe.
|
|
1669
|
-
} else {
|
|
1670
|
-
console.warn(`${lc} Failed to retrieve payloads listed in delta: ${payloadAddrs.join(', ')}`);
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1660
|
+
try {
|
|
1661
|
+
if (logalot) { console.log(`${lc} starting... (I: a1d0a85eb4189466f86dfd61e3df2626)`); }
|
|
1673
1662
|
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
const outgoingAddrsSet = new Set<string>(); // Track what we've added
|
|
1663
|
+
const { messageData } = await this.getStageAndPayloadFromFrame({ sagaFrame: sagaIbGib, space: mySpace });
|
|
1664
|
+
const deltaData = messageData as SyncSagaMessageDeltaData_V1;
|
|
1677
1665
|
|
|
1678
|
-
|
|
1666
|
+
// #region validate/sanity
|
|
1667
|
+
if (!deltaData) { throw new Error(`${lc} deltaData falsy (E: 7c28c8d8f08a4421b8344e6727271421)`); }
|
|
1668
|
+
if (deltaData.stage !== SyncStage.delta) { throw new Error(`${lc} Invalid delta frame: deltaData.stage !== SyncStage.delta (E: 0c28c8d8f08a4421b8344e6727271421)`); }
|
|
1669
|
+
if (logalot) { console.log(`${lc} deltaData: ${pretty(deltaData)} (I: a76008681df458cfbcdc4848f825a826)`); }
|
|
1670
|
+
// #endregion validate/sanity
|
|
1679
1671
|
|
|
1680
|
-
|
|
1681
|
-
// Get the requested ibGib
|
|
1682
|
-
let ibGib = srcGraph[addr];
|
|
1683
|
-
if (!ibGib) {
|
|
1684
|
-
const res = await getFromSpace({ addr, space: destSpace }); // Query from destSpace
|
|
1685
|
-
if (res.ibGibs && res.ibGibs.length > 0) {
|
|
1686
|
-
ibGib = res.ibGibs[0];
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1672
|
+
console.log(`${lc} [CONFLICT DEBUG] deltaData.payloadAddrs count: ${deltaData.payloadAddrs?.length || 0}`);
|
|
1689
1673
|
|
|
1690
|
-
|
|
1691
|
-
// Add the requested ibGib itself
|
|
1692
|
-
const ibGibAddr = getIbGibAddr({ ibGib });
|
|
1693
|
-
if (!outgoingAddrsSet.has(ibGibAddr)) {
|
|
1694
|
-
outgoingPayload.push(ibGib);
|
|
1695
|
-
outgoingAddrsSet.add(ibGibAddr);
|
|
1696
|
-
}
|
|
1674
|
+
const peerProposesCommit = deltaData.proposeCommit || false;
|
|
1697
1675
|
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
ibGib,
|
|
1703
|
-
space: destSpace,
|
|
1704
|
-
});
|
|
1676
|
+
/**
|
|
1677
|
+
* these are already in the local temp space
|
|
1678
|
+
*/
|
|
1679
|
+
const receivedPayloadIbGibs: IbGib_V1[] = sagaContext.payloadIbGibsDomain ?? [];
|
|
1705
1680
|
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1681
|
+
// 2. Fulfill Peer Requests (Outgoing Payload with Delta Dependencies)
|
|
1682
|
+
console.log(`${lc} [CONFLICT DEBUG] Fulfilling ${(deltaData.deltaRequestAddrInfos || []).length} peer requests`);
|
|
1683
|
+
const outgoingPayload = await this.getPayloadsForRequestedInfos({
|
|
1684
|
+
deltaRequestAddrInfos: deltaData.deltaRequestAddrInfos || [],
|
|
1685
|
+
mySpace,
|
|
1686
|
+
});
|
|
1687
|
+
console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`);
|
|
1688
|
+
|
|
1689
|
+
// 3. Execute Merges (If applicable)
|
|
1690
|
+
// Check if we have pending conflicts that we CAN resolve now that we have data.
|
|
1691
|
+
// We look at the Saga History (Ack Frame) to find conflicts.
|
|
1692
|
+
// Optimization: Do this only if we received payloads.
|
|
1693
|
+
const mergeResultIbGibs: IbGib_V1[] = [];
|
|
1694
|
+
|
|
1695
|
+
console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`);
|
|
1696
|
+
|
|
1697
|
+
if (receivedPayloadIbGibs.length > 0) {
|
|
1698
|
+
console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`);
|
|
1699
|
+
// Find the Ack frame in history to get conflicts
|
|
1700
|
+
// Optimization: Batch fetch history from `sagaIbGib.rel8ns.past`
|
|
1701
|
+
// V1 timelines carry full history in `past`.
|
|
1702
|
+
const pastAddrs = sagaIbGib.rel8ns?.past || [];
|
|
1703
|
+
console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`);
|
|
1704
|
+
let ackData: SyncSagaMessageAckData_V1 | undefined;
|
|
1705
|
+
|
|
1706
|
+
if (pastAddrs.length > 0) {
|
|
1707
|
+
// Batch fetch all past frames
|
|
1708
|
+
const resPast = await getFromSpace({ addrs: pastAddrs, space: myTempSpace });
|
|
1709
|
+
if (resPast.success && resPast.ibGibs) {
|
|
1710
|
+
// Iterate backwards (most recent first) to find the latest Ack
|
|
1711
|
+
for (let i = resPast.ibGibs.length - 1; i >= 0; i--) {
|
|
1712
|
+
const pastFrame = resPast.ibGibs[i];
|
|
1713
|
+
const messageStone = await getSyncSagaMessageFromFrame({
|
|
1714
|
+
frameIbGib: pastFrame,
|
|
1715
|
+
space: myTempSpace
|
|
1716
|
+
});
|
|
1717
|
+
if (messageStone?.data?.stage === SyncStage.ack) {
|
|
1718
|
+
ackData = messageStone.data as SyncSagaMessageAckData_V1;
|
|
1719
|
+
console.log(`${lc} [TEST DEBUG] Found Ack Frame. Conflicts: ${ackData.conflicts?.length || 0}`);
|
|
1720
|
+
break;
|
|
1712
1721
|
}
|
|
1713
|
-
});
|
|
1714
|
-
}
|
|
1715
|
-
} catch (depError) {
|
|
1716
|
-
console.warn(`${lc} [CONFLICT DEBUG] Error expanding deps for ${addr}: ${extractErrorMsg(depError)}`);
|
|
1717
|
-
}
|
|
1718
|
-
} else {
|
|
1719
|
-
console.warn(`${lc} Requested addr not found during delta fulfillment: ${addr}`);
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
console.log(`${lc} [CONFLICT DEBUG] Outgoing payload size (with deps): ${outgoingPayload.length}`);
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
// 3. Execute Merges (If applicable)
|
|
1727
|
-
// Check if we have pending conflicts that we CAN resolve now that we have data.
|
|
1728
|
-
// We look at the Saga History (Ack Frame) to find conflicts.
|
|
1729
|
-
// Optimization: Do this only if we received payloads.
|
|
1730
|
-
const mergeResultIbGibs: IbGib_V1[] = [];
|
|
1731
|
-
|
|
1732
|
-
console.log(`${lc} [CONFLICT DEBUG] Checking for merge. receivedPayloadIbGibs.length: ${receivedPayloadIbGibs.length}`);
|
|
1733
|
-
|
|
1734
|
-
if (receivedPayloadIbGibs.length > 0) {
|
|
1735
|
-
console.log(`${lc} [TEST DEBUG] Received Payloads (${receivedPayloadIbGibs.length}). Checking for conflicts/merges...`);
|
|
1736
|
-
// Find the Ack frame in history to get conflicts
|
|
1737
|
-
// Optimization: Batch fetch history from `sagaIbGib.rel8ns.past`
|
|
1738
|
-
// V1 timelines carry full history in `past`.
|
|
1739
|
-
const pastAddrs = sagaIbGib.rel8ns?.past || [];
|
|
1740
|
-
console.log(`${lc} [TEST DEBUG] pastAddrs count: ${pastAddrs.length}`);
|
|
1741
|
-
let ackData: SyncSagaMessageAckData_V1 | undefined;
|
|
1742
|
-
|
|
1743
|
-
if (pastAddrs.length > 0) {
|
|
1744
|
-
// Batch fetch all past frames
|
|
1745
|
-
const resPast = await getFromSpace({ addrs: pastAddrs, space: tempSpace });
|
|
1746
|
-
if (resPast.success && resPast.ibGibs) {
|
|
1747
|
-
// Iterate backwards (most recent first) to find the latest Ack
|
|
1748
|
-
for (let i = resPast.ibGibs.length - 1; i >= 0; i--) {
|
|
1749
|
-
const pastFrame = resPast.ibGibs[i];
|
|
1750
|
-
const messageStone = await getSyncSagaMessageFromFrame({
|
|
1751
|
-
frameIbGib: pastFrame,
|
|
1752
|
-
space: tempSpace
|
|
1753
|
-
});
|
|
1754
|
-
if (messageStone?.data?.stage === SyncStage.ack) {
|
|
1755
|
-
ackData = messageStone.data as SyncSagaMessageAckData_V1;
|
|
1756
|
-
console.log(`${lc} [TEST DEBUG] Found Ack Frame. Conflicts: ${ackData.conflicts?.length || 0}`);
|
|
1757
|
-
break;
|
|
1758
1722
|
}
|
|
1759
1723
|
}
|
|
1760
1724
|
}
|
|
1761
|
-
}
|
|
1762
1725
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1726
|
+
if (ackData && ackData.conflicts) {
|
|
1727
|
+
const optimisticConflicts = ackData.conflicts.filter(c => !c.terminal);
|
|
1728
|
+
for (const conflict of optimisticConflicts) {
|
|
1729
|
+
const { timelineAddrs, localAddr: receiverTip, remoteAddr: senderTip } = conflict;
|
|
1730
|
+
// We are Sender (usually) here if we are merging.
|
|
1731
|
+
// Check if we have the history needed (timelineAddrs).
|
|
1732
|
+
// Specifically, we needed the `receiverOnly` parts.
|
|
1733
|
+
|
|
1734
|
+
// We blindly attempt merge if we have both tips accessible?
|
|
1735
|
+
// We need `receiverTip` (localAddr in Ack) and `senderTip` (remoteAddr).
|
|
1736
|
+
|
|
1737
|
+
// Check if we have receiverTip in space
|
|
1738
|
+
console.log(`${lc} [CONFLICT DEBUG] Attempting merge for conflict. ReceiverTip: ${receiverTip}, SenderTip: ${senderTip}`);
|
|
1739
|
+
const resRecTip = await getFromSpace({ addr: receiverTip, space: myTempSpace }); // Check myTempSpace for incoming data
|
|
1740
|
+
console.log(`${lc} [CONFLICT DEBUG] ReceiverTip found in myTempSpace: ${!!resRecTip.ibGibs?.[0]}`);
|
|
1741
|
+
if (resRecTip.success && resRecTip.ibGibs?.[0]) {
|
|
1742
|
+
// We have the tip!
|
|
1743
|
+
// Do we have the full history?
|
|
1744
|
+
// `mergeDivergentTimelines` in `conflict-optimistic` will attempt to fetch history.
|
|
1745
|
+
// If we just ingested the missing pieces, `getFromSpace` inside `merge` should succeed.
|
|
1746
|
+
|
|
1747
|
+
// Perform Merge!
|
|
1748
|
+
try {
|
|
1749
|
+
const mergeResult = await mergeDivergentTimelines({
|
|
1750
|
+
tipA: (await getFromSpace({ addr: senderTip, space: mySpace })).ibGibs![0], // Our tip from destSpace
|
|
1751
|
+
tipB: resRecTip.ibGibs[0], // Their tip (from myTempSpace)
|
|
1752
|
+
space: myTempSpace, // Merge uses myTempSpace
|
|
1753
|
+
metaspace,
|
|
1754
|
+
});
|
|
1755
|
+
if (mergeResult) {
|
|
1756
|
+
console.log(`${lc} [TEST DEBUG] Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`);
|
|
1757
|
+
if (logalot) { console.log(`${lc} Merge success! New Tip: ${getIbGibAddr({ ibGib: mergeResult })}`); }
|
|
1758
|
+
mergeResultIbGibs.push(mergeResult);
|
|
1759
|
+
outgoingPayload.push(mergeResult); // Send result to peer
|
|
1760
|
+
}
|
|
1761
|
+
} catch (e) {
|
|
1762
|
+
console.error(`${lc} Merge failed: ${e}`);
|
|
1763
|
+
// If merge fails, we might Abort or just continue?
|
|
1797
1764
|
}
|
|
1798
|
-
} catch (e) {
|
|
1799
|
-
console.error(`${lc} Merge failed: ${e}`);
|
|
1800
|
-
// If merge fails, we might Abort or just continue?
|
|
1801
1765
|
}
|
|
1802
1766
|
}
|
|
1803
1767
|
}
|
|
1804
1768
|
}
|
|
1805
|
-
}
|
|
1806
1769
|
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1770
|
+
// 4. Determine Next Action
|
|
1771
|
+
// We have `outgoingPayload` (Requests + Merge Results).
|
|
1772
|
+
// Does Peer have outstanding requests? No, we fulfilled `peerRequests`.
|
|
1773
|
+
// Do WE have outstanding requests?
|
|
1774
|
+
// We might if `mergeResult` requires further sync? Usually no, result is complete.
|
|
1812
1775
|
|
|
1813
|
-
|
|
1776
|
+
const myRequests: string[] = []; // If we had more needs (e.g. partial payload), we'd add here.
|
|
1814
1777
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
if (hasOutgoing || hasMyRequests) {
|
|
1819
|
-
// We have business to attend to -> Send Delta
|
|
1820
|
-
const responseDeltaData: SyncSagaMessageDeltaData_V1 = {
|
|
1821
|
-
sagaId: deltaData.sagaId,
|
|
1822
|
-
stage: SyncStage.delta,
|
|
1823
|
-
payloadAddrs: outgoingPayload.map(p => getIbGibAddr({ ibGib: p })),
|
|
1824
|
-
requests: hasMyRequests ? myRequests : undefined,
|
|
1825
|
-
proposeCommit: !hasMyRequests // If we are sending data but have no requests, we VALIDATE PROPOSAL?
|
|
1826
|
-
// Wait. If we send data, we are NOT committing yet.
|
|
1827
|
-
// We are sending data. The OTHER side must ingest it.
|
|
1828
|
-
// So proposeCommit = true?
|
|
1829
|
-
// "Here is the data. I'm done. If you are good, let's commit."
|
|
1830
|
-
// Yes.
|
|
1831
|
-
};
|
|
1778
|
+
const hasOutgoing = outgoingPayload.length > 0;
|
|
1779
|
+
const hasMyRequests = myRequests.length > 0;
|
|
1832
1780
|
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
// So yes, proposeCommit = true.
|
|
1837
|
-
responseDeltaData.proposeCommit = true;
|
|
1838
|
-
|
|
1839
|
-
const deltaStone = await this.createSyncMsgStone({
|
|
1840
|
-
data: responseDeltaData,
|
|
1841
|
-
localSpace: tempSpace,
|
|
1842
|
-
metaspace
|
|
1843
|
-
});
|
|
1844
|
-
|
|
1845
|
-
const deltaFrame = await this.evolveSyncSagaIbGib({
|
|
1846
|
-
prevSagaIbGib: sagaIbGib,
|
|
1847
|
-
msgStones: [deltaStone],
|
|
1848
|
-
sessionIdentity: identity,
|
|
1849
|
-
localSpace: tempSpace,
|
|
1850
|
-
metaspace
|
|
1851
|
-
});
|
|
1852
|
-
|
|
1853
|
-
// Build control payloads: frame + its dependencies (msg stone, identity)
|
|
1854
|
-
const payloadIbGibsControl: IbGib_V1[] = [deltaFrame, deltaStone];
|
|
1855
|
-
if (identity) { payloadIbGibsControl.push(identity); }
|
|
1856
|
-
|
|
1857
|
-
// return { frame: deltaFrame, payloadIbGibsControl, payloadIbGibsDomain: outgoingPayload };
|
|
1858
|
-
// return { frame: deltaFrame, payloadIbGibsDomain: outgoingPayload };
|
|
1859
|
-
throw new Error(`not implemented (E: 2b38a8afb6d84efcee5ab51673387826)`);
|
|
1860
|
-
|
|
1861
|
-
} else {
|
|
1862
|
-
// We have nothing to send.
|
|
1863
|
-
|
|
1864
|
-
if (peerProposesCommit) {
|
|
1865
|
-
// Peer is done. We are done. -> Commit.
|
|
1866
|
-
const commitData: SyncSagaMessageCommitData_V1 = {
|
|
1867
|
-
sagaId: deltaData.sagaId,
|
|
1868
|
-
stage: SyncStage.commit,
|
|
1869
|
-
success: true,
|
|
1870
|
-
};
|
|
1871
|
-
|
|
1872
|
-
const commitStone = await this.createSyncMsgStone({
|
|
1873
|
-
data: commitData,
|
|
1874
|
-
localSpace: tempSpace,
|
|
1875
|
-
metaspace
|
|
1876
|
-
});
|
|
1877
|
-
|
|
1878
|
-
const commitFrame = await this.evolveSyncSagaIbGib({
|
|
1879
|
-
prevSagaIbGib: sagaIbGib,
|
|
1880
|
-
msgStones: [commitStone],
|
|
1881
|
-
sessionIdentity: identity,
|
|
1882
|
-
localSpace: tempSpace,
|
|
1883
|
-
metaspace
|
|
1884
|
-
});
|
|
1885
|
-
|
|
1886
|
-
// Build control payloads for commit
|
|
1887
|
-
const commitCtrlPayloads: IbGib_V1[] = [commitFrame, commitStone];
|
|
1888
|
-
if (identity) { commitCtrlPayloads.push(identity); }
|
|
1889
|
-
|
|
1890
|
-
// return { frame: commitFrame, payloadIbGibsControl: commitCtrlPayloads };
|
|
1891
|
-
// return { frame: commitFrame, };
|
|
1892
|
-
throw new Error(`not implemented (E: dda1ddc63fdcadff06653298e0d04826)`);
|
|
1893
|
-
|
|
1894
|
-
} else {
|
|
1895
|
-
// peer did NOT propose commit (maybe they just sent data/requests and didn't ready flag).
|
|
1896
|
-
// But we are empty.
|
|
1897
|
-
// So WE propose commit.
|
|
1781
|
+
if (hasOutgoing || hasMyRequests) {
|
|
1782
|
+
// We have business to attend to -> Send Delta
|
|
1898
1783
|
const responseDeltaData: SyncSagaMessageDeltaData_V1 = {
|
|
1899
1784
|
sagaId: deltaData.sagaId,
|
|
1900
1785
|
stage: SyncStage.delta,
|
|
1901
|
-
|
|
1902
|
-
|
|
1786
|
+
payloadAddrs: outgoingPayload.map(p => getIbGibAddr({ ibGib: p })),
|
|
1787
|
+
requests: hasMyRequests ? myRequests : undefined,
|
|
1788
|
+
proposeCommit: !hasMyRequests // If we are sending data but have no requests, we VALIDATE PROPOSAL?
|
|
1789
|
+
// Wait. If we send data, we are NOT committing yet.
|
|
1790
|
+
// We are sending data. The OTHER side must ingest it.
|
|
1791
|
+
// So proposeCommit = true?
|
|
1792
|
+
// "Here is the data. I'm done. If you are good, let's commit."
|
|
1793
|
+
// Yes.
|
|
1903
1794
|
};
|
|
1904
1795
|
|
|
1796
|
+
// BUT if `peerProposesCommit` was true, and we are sending data, we are effectively rejecting/delaying it.
|
|
1797
|
+
// We just send the Delta. Peer receives it, ingests, sees ProposeCommit=True (from us), and then Commits.
|
|
1798
|
+
|
|
1799
|
+
// So yes, proposeCommit = true.
|
|
1800
|
+
responseDeltaData.proposeCommit = true;
|
|
1801
|
+
|
|
1905
1802
|
const deltaStone = await this.createSyncMsgStone({
|
|
1906
1803
|
data: responseDeltaData,
|
|
1907
|
-
localSpace:
|
|
1908
|
-
metaspace
|
|
1804
|
+
localSpace: mySpace,
|
|
1805
|
+
metaspace,
|
|
1909
1806
|
});
|
|
1910
1807
|
|
|
1911
1808
|
const deltaFrame = await this.evolveSyncSagaIbGib({
|
|
1912
1809
|
prevSagaIbGib: sagaIbGib,
|
|
1913
1810
|
msgStones: [deltaStone],
|
|
1914
1811
|
sessionIdentity: identity,
|
|
1915
|
-
localSpace:
|
|
1916
|
-
metaspace
|
|
1812
|
+
localSpace: mySpace,
|
|
1813
|
+
metaspace,
|
|
1917
1814
|
});
|
|
1918
1815
|
|
|
1919
|
-
//
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1816
|
+
// Build control payloads: frame + its dependencies (msg stone, identity)
|
|
1817
|
+
const payloadIbGibsControl: IbGib_V1[] = [deltaFrame, deltaStone];
|
|
1818
|
+
if (identity) { payloadIbGibsControl.push(identity); }
|
|
1819
|
+
|
|
1820
|
+
// return { frame: deltaFrame, payloadIbGibsControl, payloadIbGibsDomain: outgoingPayload };
|
|
1821
|
+
return { frame: deltaFrame, payloadIbGibsDomain: outgoingPayload };
|
|
1822
|
+
// throw new Error(`not implemented (E: 2b38a8afb6d84efcee5ab51673387826)`);
|
|
1924
1823
|
|
|
1824
|
+
} else {
|
|
1825
|
+
// We have nothing to send.
|
|
1826
|
+
|
|
1827
|
+
if (peerProposesCommit) {
|
|
1828
|
+
// Peer is done. We are done. -> Commit.
|
|
1925
1829
|
const commitData: SyncSagaMessageCommitData_V1 = {
|
|
1926
1830
|
sagaId: deltaData.sagaId,
|
|
1927
1831
|
stage: SyncStage.commit,
|
|
@@ -1930,68 +1834,136 @@ export class SyncSagaCoordinator {
|
|
|
1930
1834
|
|
|
1931
1835
|
const commitStone = await this.createSyncMsgStone({
|
|
1932
1836
|
data: commitData,
|
|
1933
|
-
localSpace:
|
|
1837
|
+
localSpace: mySpace,
|
|
1934
1838
|
metaspace
|
|
1935
1839
|
});
|
|
1936
1840
|
|
|
1937
1841
|
const commitFrame = await this.evolveSyncSagaIbGib({
|
|
1938
|
-
prevSagaIbGib:
|
|
1842
|
+
prevSagaIbGib: sagaIbGib,
|
|
1939
1843
|
msgStones: [commitStone],
|
|
1940
1844
|
sessionIdentity: identity,
|
|
1941
|
-
localSpace:
|
|
1845
|
+
localSpace: mySpace,
|
|
1942
1846
|
metaspace
|
|
1943
1847
|
});
|
|
1944
1848
|
|
|
1945
1849
|
// Build control payloads for commit
|
|
1946
|
-
const
|
|
1947
|
-
if (identity) {
|
|
1850
|
+
const commitCtrlPayloads: IbGib_V1[] = [commitFrame, commitStone];
|
|
1851
|
+
if (identity) { commitCtrlPayloads.push(identity); }
|
|
1948
1852
|
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1853
|
+
return { frame: commitFrame, };
|
|
1854
|
+
|
|
1855
|
+
} else {
|
|
1856
|
+
// peer did NOT propose commit (maybe they just sent data/requests and didn't ready flag).
|
|
1857
|
+
// But we are empty.
|
|
1858
|
+
// So WE propose commit.
|
|
1859
|
+
const responseDeltaData: SyncSagaMessageDeltaData_V1 = {
|
|
1860
|
+
sagaId: deltaData.sagaId,
|
|
1861
|
+
stage: SyncStage.delta,
|
|
1862
|
+
proposeCommit: true,
|
|
1863
|
+
};
|
|
1864
|
+
|
|
1865
|
+
const deltaStone = await this.createSyncMsgStone({
|
|
1866
|
+
data: responseDeltaData,
|
|
1867
|
+
localSpace: mySpace,
|
|
1868
|
+
metaspace
|
|
1869
|
+
});
|
|
1870
|
+
|
|
1871
|
+
const deltaFrame = await this.evolveSyncSagaIbGib({
|
|
1872
|
+
prevSagaIbGib: sagaIbGib,
|
|
1873
|
+
msgStones: [deltaStone],
|
|
1874
|
+
sessionIdentity: identity,
|
|
1875
|
+
localSpace: mySpace,
|
|
1876
|
+
metaspace
|
|
1877
|
+
});
|
|
1878
|
+
|
|
1879
|
+
// Check if PEER proposed commit
|
|
1880
|
+
if (deltaData.proposeCommit) {
|
|
1881
|
+
if (logalot) { console.log(`${lc} Peer proposed commit. Accepting & Committing.`); }
|
|
1882
|
+
// Peer wants to commit and has no more requests.
|
|
1883
|
+
// We should Commit.
|
|
1884
|
+
|
|
1885
|
+
const commitData: SyncSagaMessageCommitData_V1 = {
|
|
1886
|
+
sagaId: deltaData.sagaId,
|
|
1887
|
+
stage: SyncStage.commit,
|
|
1888
|
+
success: true,
|
|
1889
|
+
};
|
|
1890
|
+
|
|
1891
|
+
const commitStone = await this.createSyncMsgStone({
|
|
1892
|
+
data: commitData,
|
|
1893
|
+
localSpace: mySpace,
|
|
1894
|
+
metaspace
|
|
1895
|
+
});
|
|
1896
|
+
|
|
1897
|
+
const commitFrame = await this.evolveSyncSagaIbGib({
|
|
1898
|
+
prevSagaIbGib: deltaFrame, // Build on top of the Delta we just created/persisted
|
|
1899
|
+
msgStones: [commitStone],
|
|
1900
|
+
sessionIdentity: identity,
|
|
1901
|
+
localSpace: mySpace,
|
|
1902
|
+
metaspace
|
|
1903
|
+
});
|
|
1904
|
+
|
|
1905
|
+
// Build control payloads for commit
|
|
1906
|
+
const commitCtrlPayloads2: IbGib_V1[] = [commitFrame, commitStone];
|
|
1907
|
+
if (identity) { commitCtrlPayloads2.push(identity); }
|
|
1908
|
+
|
|
1909
|
+
return { frame: commitFrame, };
|
|
1910
|
+
}
|
|
1953
1911
|
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1912
|
+
// Build control payloads for delta propose
|
|
1913
|
+
const deltaCtrlPayloads: IbGib_V1[] = [deltaFrame, deltaStone];
|
|
1914
|
+
if (identity) { deltaCtrlPayloads.push(identity); }
|
|
1957
1915
|
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
throw new Error(`not implemented (E: ff35584696b6fcb3ad6dd7c5cade2f26)`);
|
|
1916
|
+
return { frame: deltaFrame, payloadIbGibsDomain: outgoingPayload };
|
|
1917
|
+
}
|
|
1961
1918
|
}
|
|
1919
|
+
} catch (error) {
|
|
1920
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1921
|
+
throw error;
|
|
1922
|
+
} finally {
|
|
1923
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1962
1924
|
}
|
|
1925
|
+
|
|
1963
1926
|
}
|
|
1964
1927
|
|
|
1965
1928
|
|
|
1966
1929
|
protected async handleCommitFrame({
|
|
1967
1930
|
sagaIbGib,
|
|
1968
|
-
|
|
1969
|
-
|
|
1931
|
+
mySpace,
|
|
1932
|
+
myTempSpace,
|
|
1970
1933
|
metaspace,
|
|
1971
1934
|
identity,
|
|
1972
1935
|
}: {
|
|
1973
1936
|
sagaIbGib: SyncIbGib_V1,
|
|
1974
|
-
|
|
1975
|
-
|
|
1937
|
+
mySpace: IbGibSpaceAny,
|
|
1938
|
+
myTempSpace: IbGibSpaceAny,
|
|
1976
1939
|
metaspace: MetaspaceService,
|
|
1977
1940
|
identity?: KeystoneIbGib_V1,
|
|
1978
1941
|
}): Promise<NextSagaFrameInfo> {
|
|
1979
1942
|
const lc = `${this.lc}[${this.handleCommitFrame.name}]`;
|
|
1980
|
-
|
|
1943
|
+
try {
|
|
1944
|
+
if (logalot) { console.log(`${lc} starting... (I: e179573bdd881202f8ba3168da1c3826)`); }
|
|
1945
|
+
|
|
1946
|
+
|
|
1981
1947
|
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1948
|
+
// Sender Logic (Finalizing):
|
|
1949
|
+
// If we are here, we received a Commit frame from the Peer.
|
|
1950
|
+
// This implies the Peer has successfully committed.
|
|
1951
|
+
// We should now:
|
|
1952
|
+
// 1. Validate (implicitly done by receiving valid frame)
|
|
1953
|
+
// 2. Perform our own cleanup (Temp -> Dest, if applicable)
|
|
1954
|
+
// 3. Return null to signal saga completion.
|
|
1989
1955
|
|
|
1990
|
-
|
|
1956
|
+
// Note: Currently we don't have explicit cleanup logic implemented here yet (TODO).
|
|
1957
|
+
if (logalot) { console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`); }
|
|
1958
|
+
|
|
1959
|
+
return { responseWasNull: true };
|
|
1960
|
+
} catch (error) {
|
|
1961
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1962
|
+
throw error;
|
|
1963
|
+
} finally {
|
|
1964
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1965
|
+
}
|
|
1991
1966
|
|
|
1992
|
-
if (logalot) { console.log(`${lc} Peer committed. Finalizing saga locally. Saga Complete.`); }
|
|
1993
|
-
// return { responseWasNull: true };
|
|
1994
|
-
throw new Error(`not implemented (E: 4d7f878bcc45ad3dd9c4b8573f3aa826)`);
|
|
1995
1967
|
}
|
|
1996
1968
|
|
|
1997
1969
|
// #endregion Handlers
|
|
@@ -2045,6 +2017,10 @@ export class SyncSagaCoordinator {
|
|
|
2045
2017
|
msgStones: IbGib_V1[],
|
|
2046
2018
|
localSpace: IbGibSpaceAny,
|
|
2047
2019
|
metaspace: MetaspaceService,
|
|
2020
|
+
/**
|
|
2021
|
+
* does NOT evolve the keystone. this should be done by the caller.
|
|
2022
|
+
* (NOT IMPLEMENTED YET ANYWAY)
|
|
2023
|
+
*/
|
|
2048
2024
|
sessionIdentity?: KeystoneIbGib_V1,
|
|
2049
2025
|
}): Promise<SyncIbGib_V1> {
|
|
2050
2026
|
const lc = `${this.lc}[${this.evolveSyncSagaIbGib.name}]`;
|