@ibgib/core-gib 0.1.25 → 0.1.26
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/other/ibgib-helper.d.mts +1 -1
- package/dist/common/other/ibgib-helper.d.mts.map +1 -1
- package/dist/common/other/ibgib-helper.mjs.map +1 -1
- package/dist/sync/sync-constants.d.mts +1 -0
- package/dist/sync/sync-constants.d.mts.map +1 -1
- package/dist/sync/sync-constants.mjs +1 -0
- package/dist/sync/sync-constants.mjs.map +1 -1
- package/dist/sync/sync-helpers.d.mts +5 -0
- package/dist/sync/sync-helpers.d.mts.map +1 -1
- package/dist/sync/sync-helpers.mjs +37 -1
- package/dist/sync/sync-helpers.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +0 -2
- 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 +148 -62
- 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 +13 -29
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +17 -57
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +15 -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 +60 -4
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +49 -3
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +180 -101
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-types.d.mts +1 -3
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/package.json +1 -1
- package/src/common/other/ibgib-helper.mts +1 -1
- package/src/sync/sync-constants.mts +1 -0
- package/src/sync/sync-helpers.mts +41 -1
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +147 -47
- package/src/sync/sync-peer/sync-peer-v1.mts +31 -74
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +55 -7
- package/src/sync/sync-saga-coordinator.mts +232 -110
- package/src/sync/sync-types.mts +2 -2
|
@@ -142,6 +142,75 @@ export class SyncSagaCoordinator {
|
|
|
142
142
|
done
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* This is what the receiving side of the sync calls to drive the FSM to the
|
|
147
|
+
* next stage.
|
|
148
|
+
*
|
|
149
|
+
* So whereas the sender executes a saga loop and drives the entire process,
|
|
150
|
+
* this is a reactive one-off that drives just the single step that the
|
|
151
|
+
* receiver does in that saga.
|
|
152
|
+
*
|
|
153
|
+
* @returns next context result if another round, else if commit returns
|
|
154
|
+
* null
|
|
155
|
+
*/
|
|
156
|
+
async receiverContinueSync({ sagaContext, mySpace, myTempSpace, identity, identitySecret, metaspace, }) {
|
|
157
|
+
const lc = `${this.lc}[${this.receiverContinueSync.name}]`;
|
|
158
|
+
try {
|
|
159
|
+
if (logalot) {
|
|
160
|
+
console.log(`${lc} starting... (I: f64e08bf77d1425378601f380384ec26)`);
|
|
161
|
+
}
|
|
162
|
+
const contextResult = await this.handleResponseSagaContext({
|
|
163
|
+
sagaContext,
|
|
164
|
+
mySpace,
|
|
165
|
+
myTempSpace,
|
|
166
|
+
identity,
|
|
167
|
+
identitySecret,
|
|
168
|
+
metaspace,
|
|
169
|
+
});
|
|
170
|
+
if (!contextResult) {
|
|
171
|
+
if (logalot) {
|
|
172
|
+
console.log(`${lc} Handler returned null (Saga End). (I: 43da8bb6c846b1fe7766332643be0e26)`);
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
// #region error conditions throw
|
|
177
|
+
if (contextResult.errorMsg) {
|
|
178
|
+
throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: 7b41a183cf3cb58a5859c803800cf826)`);
|
|
179
|
+
}
|
|
180
|
+
else if (!contextResult.nextFrameInfo) {
|
|
181
|
+
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: 5740542f5eb8ccb41dfec188d87c1e26)`);
|
|
182
|
+
}
|
|
183
|
+
else if (contextResult.nextFrameInfo?.responseWasNull) {
|
|
184
|
+
throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo.responseWasNull? logic flow should not have gotten here. (E: ae06748d8c0c5e70c92322c8fb0cb426)`);
|
|
185
|
+
}
|
|
186
|
+
// #endregion error conditions throw
|
|
187
|
+
// create the return context
|
|
188
|
+
const { frame, payloadIbGibsDomain } = contextResult.nextFrameInfo;
|
|
189
|
+
const responseCtx = await createSyncSagaContext({
|
|
190
|
+
sagaFrame: frame,
|
|
191
|
+
localSpace: mySpace,
|
|
192
|
+
payloadIbGibsDomain,
|
|
193
|
+
// todo: we need to thoroughly go through the identity per each step after getting basic merging
|
|
194
|
+
sessionKeystones: identity ? [identity] : undefined, // ??
|
|
195
|
+
});
|
|
196
|
+
const immediateValidationErrors = await validateContextAndSagaFrame({
|
|
197
|
+
context: responseCtx,
|
|
198
|
+
});
|
|
199
|
+
if (immediateValidationErrors.length > 0) {
|
|
200
|
+
throw new Error(`(UNEXPECTED) just created sync saga context () and there were immediateValidationErrors? immediateValidationErrors: ${immediateValidationErrors} (E: c120e8e0aa98673d685267a8a36e5826)`);
|
|
201
|
+
}
|
|
202
|
+
return responseCtx;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
if (logalot) {
|
|
210
|
+
console.log(`${lc} complete.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
145
214
|
async getSessionIdentity({ sagaId, metaspace, tempSpace, }) {
|
|
146
215
|
const lc = `${this.lc}[${this.getSessionIdentity.name}]`;
|
|
147
216
|
try {
|
|
@@ -292,8 +361,12 @@ export class SyncSagaCoordinator {
|
|
|
292
361
|
throw new Error(`(UNEXPECTED) responseCtx.data falsy? (E: a969992bae53ab18a827ec58aec15826)`);
|
|
293
362
|
}
|
|
294
363
|
updates$.next(responseCtx); // spins off for saga UI updating
|
|
295
|
-
// validate context
|
|
296
|
-
|
|
364
|
+
// immediately validate context/saga frame (but not payloads because
|
|
365
|
+
// we may not have those yet)
|
|
366
|
+
const contextAndSagaFrameValidationErrors = await validateContextAndSagaFrame({ context: responseCtx });
|
|
367
|
+
if (contextAndSagaFrameValidationErrors.length > 0) {
|
|
368
|
+
throw new Error(`contextAndSagaFrameValidationErrors: ${contextAndSagaFrameValidationErrors} (E: 6eebe8e7fa437c00a8cde3ada3c66826)`);
|
|
369
|
+
}
|
|
297
370
|
// Extract expected domain addresses from response context
|
|
298
371
|
const responsePayloadAddrsDomain = responseCtx.data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] || [];
|
|
299
372
|
// Poll for them if needed. see above jsdocs for domainPayloadsMap
|
|
@@ -326,6 +399,7 @@ export class SyncSagaCoordinator {
|
|
|
326
399
|
// finished/errored out.
|
|
327
400
|
const contextResult = await this.handleResponseSagaContext({
|
|
328
401
|
sagaContext: responseCtx,
|
|
402
|
+
initDomainGraph,
|
|
329
403
|
mySpace: localSpace,
|
|
330
404
|
myTempSpace: tempSpace,
|
|
331
405
|
metaspace,
|
|
@@ -584,6 +658,7 @@ export class SyncSagaCoordinator {
|
|
|
584
658
|
}
|
|
585
659
|
/**
|
|
586
660
|
* This is the heart of the "ping pong" transaction, where we send a context
|
|
661
|
+
*
|
|
587
662
|
* and receive a context. IOW, this drives the FSM of the sync saga ibgib as
|
|
588
663
|
* a whole.
|
|
589
664
|
*
|
|
@@ -602,7 +677,7 @@ export class SyncSagaCoordinator {
|
|
|
602
677
|
*
|
|
603
678
|
* This is a one-off on the receiver.
|
|
604
679
|
*/
|
|
605
|
-
async handleResponseSagaContext({ sagaContext, mySpace, myTempSpace, identity, identitySecret, metaspace, }) {
|
|
680
|
+
async handleResponseSagaContext({ sagaContext, initDomainGraph, mySpace, myTempSpace, identity, identitySecret, metaspace, }) {
|
|
606
681
|
const lc = `${this.lc}[${this.handleResponseSagaContext.name}]`;
|
|
607
682
|
try {
|
|
608
683
|
if (logalot) {
|
|
@@ -638,7 +713,18 @@ export class SyncSagaCoordinator {
|
|
|
638
713
|
});
|
|
639
714
|
break;
|
|
640
715
|
case SyncStage.ack:
|
|
641
|
-
|
|
716
|
+
if (!initDomainGraph) {
|
|
717
|
+
throw new Error(`(UNEXPECTED) initDomainGraph falsy on the sender? (E: a3d758ad954829aba88663188eafc826)`);
|
|
718
|
+
}
|
|
719
|
+
nextFrameInfo = await this.handleAckFrame({
|
|
720
|
+
sagaIbGib,
|
|
721
|
+
srcGraph,
|
|
722
|
+
initDomainGraph,
|
|
723
|
+
metaspace,
|
|
724
|
+
destSpace: mySpace,
|
|
725
|
+
tempSpace: myTempSpace,
|
|
726
|
+
identity,
|
|
727
|
+
});
|
|
642
728
|
break;
|
|
643
729
|
case SyncStage.delta:
|
|
644
730
|
nextFrameInfo = await this.handleDeltaFrame({ sagaIbGib, srcGraph, metaspace, destSpace: mySpace, tempSpace: myTempSpace, identity, });
|
|
@@ -928,7 +1014,6 @@ export class SyncSagaCoordinator {
|
|
|
928
1014
|
* we want to push ibgibs to the remote/sender if we have push
|
|
929
1015
|
* offers. an ack frame's payloads, if any, are those push offers
|
|
930
1016
|
*/
|
|
931
|
-
// let payloadIbGibsDomain: IbGib_V1[] | undefined = await getPushOffers
|
|
932
1017
|
let payloadIbGibsDomain;
|
|
933
1018
|
if (pushOfferInfos.length > 0) {
|
|
934
1019
|
const searchSecondSpaceAddrs = [];
|
|
@@ -985,12 +1070,10 @@ export class SyncSagaCoordinator {
|
|
|
985
1070
|
}
|
|
986
1071
|
// we have now populated payloadIbGibsDomain
|
|
987
1072
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
// payloadIbGibsDomain,
|
|
993
|
-
// };
|
|
1073
|
+
return {
|
|
1074
|
+
frame: ackFrame,
|
|
1075
|
+
payloadIbGibsDomain,
|
|
1076
|
+
};
|
|
994
1077
|
}
|
|
995
1078
|
catch (error) {
|
|
996
1079
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
@@ -1014,7 +1097,7 @@ export class SyncSagaCoordinator {
|
|
|
1014
1097
|
*
|
|
1015
1098
|
* Returns a `Delta` frame.
|
|
1016
1099
|
*/
|
|
1017
|
-
async handleAckFrame({ sagaIbGib, srcGraph, destSpace, tempSpace, metaspace, identity, }) {
|
|
1100
|
+
async handleAckFrame({ sagaIbGib, srcGraph, initDomainGraph, destSpace, tempSpace, metaspace, identity, }) {
|
|
1018
1101
|
const lc = `${this.lc}[${this.handleAckFrame.name}]`;
|
|
1019
1102
|
try {
|
|
1020
1103
|
if (logalot) {
|
|
@@ -1044,10 +1127,10 @@ export class SyncSagaCoordinator {
|
|
|
1044
1127
|
// For now, throw to trigger abort.
|
|
1045
1128
|
throw new Error(`${lc} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
|
|
1046
1129
|
}
|
|
1047
|
-
|
|
1130
|
+
// at this point, if we have conflicts, they are non-terminal
|
|
1048
1131
|
const mergeDeltaReqs = []; // Additional requests for merging
|
|
1049
|
-
if (
|
|
1050
|
-
console.log(`${lc} [CONFLICT DEBUG] Processing ${
|
|
1132
|
+
if (conflicts.length > 0) {
|
|
1133
|
+
console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
|
|
1051
1134
|
// We need to resolve these.
|
|
1052
1135
|
// Strategy:
|
|
1053
1136
|
// 1. Analyze Divergence (Sender vs Receiver)
|
|
@@ -1073,93 +1156,89 @@ export class SyncSagaCoordinator {
|
|
|
1073
1156
|
// `peer.pull(addr)`?
|
|
1074
1157
|
// Yes! The Coordinator has the `peer`.
|
|
1075
1158
|
// Let's analyze and pull immediately.
|
|
1076
|
-
for (const conflict of
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
//
|
|
1080
|
-
//
|
|
1081
|
-
//
|
|
1082
|
-
//
|
|
1083
|
-
//
|
|
1084
|
-
//
|
|
1085
|
-
|
|
1086
|
-
//
|
|
1087
|
-
//
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
}
|
|
1093
|
-
// Basic Diff: Find what Receiver has that we don't.
|
|
1094
|
-
// Actually, we need to traverse OUR past to find commonality.
|
|
1095
|
-
const senderHistory = [senderTip, ...(senderTipIbGib.rel8ns?.past || [])];
|
|
1096
|
-
const receiverOnlyAddrs = timelineAddrs.filter(addr => !senderHistory.includes(addr));
|
|
1097
|
-
if (receiverOnlyAddrs.length > 0) {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
}
|
|
1158
|
-
else {
|
|
1159
|
-
console.log(`${lc} [CONFLICT DEBUG] No receiver-only frames found for this conflict`);
|
|
1160
|
-
}
|
|
1159
|
+
for (const conflict of conflicts) {
|
|
1160
|
+
// todo: integrate conflict strategies into this point...this whole block needs to be redone, but I want to check the fast-forward/backward simpler case tests first
|
|
1161
|
+
throw new Error(`conflicts not (re)implemented yet (E: 3b7d0819f83842a6de3ae988819bc826)`);
|
|
1162
|
+
// const { timelineAddrs, localAddr: receiverTip, remoteAddr: senderTip } = conflict;
|
|
1163
|
+
// // Sender History
|
|
1164
|
+
// // We need our own history for this timeline.
|
|
1165
|
+
// // We know the 'senderTip' (remoteAddr in Ack).
|
|
1166
|
+
// // Sender should verify it has this tip.
|
|
1167
|
+
// // Compute Diffs
|
|
1168
|
+
// // We need to find `receiverOnly` addrs.
|
|
1169
|
+
// // Receiver sent us `timelineAddrs` (Full History).
|
|
1170
|
+
// const receiverHistorySet = new Set(timelineAddrs);
|
|
1171
|
+
// // We need our execution context's history for this senderTip.
|
|
1172
|
+
// // We can fetch valid 'past' from space.
|
|
1173
|
+
// const resSenderTip = await getFromSpace({ space: destSpace, addr: senderTip });
|
|
1174
|
+
// const senderTipIbGib = resSenderTip.ibGibs?.[0];
|
|
1175
|
+
// if (!senderTipIbGib) { throw new Error(`${lc} Sender missing its own tip? ${senderTip} (E: 832f3804645878869ee3c13714366726)`); }
|
|
1176
|
+
// // Basic Diff: Find what Receiver has that we don't.
|
|
1177
|
+
// // Actually, we need to traverse OUR past to find commonality.
|
|
1178
|
+
// const senderHistory = [senderTip, ...(senderTipIbGib.rel8ns?.past || [])];
|
|
1179
|
+
// const receiverOnlyAddrs = timelineAddrs.filter(addr => !senderHistory.includes(addr));
|
|
1180
|
+
// if (receiverOnlyAddrs.length > 0) {
|
|
1181
|
+
// console.log(`${lc} [CONFLICT DEBUG] Found ${receiverOnlyAddrs.length} receiver-only frames - need to pull for merge`);
|
|
1182
|
+
// console.log(`${lc} [CONFLICT DEBUG] Receiver-only addrs:`, receiverOnlyAddrs);
|
|
1183
|
+
// // PULL these frames from Peer into Local Space
|
|
1184
|
+
// // (Validation: We trust peer for now / verification happens on put)
|
|
1185
|
+
// for (const addr of receiverOnlyAddrs) {
|
|
1186
|
+
// console.error(`${lc} [CONFLICT DEBUG] NOT IMPLEMENTED (E: e6bf1a9d2758c469bb2f97514062d826)`);
|
|
1187
|
+
// }
|
|
1188
|
+
// // Compute DELTA dependencies for each receiver-only frame
|
|
1189
|
+
// // Find LCA to determine what dependencies we already have
|
|
1190
|
+
// const lcaAddr = timelineAddrs.find(addr => senderHistory.includes(addr));
|
|
1191
|
+
// console.log(`${lc} [CONFLICT DEBUG] LCA: ${lcaAddr || 'NONE'}`);
|
|
1192
|
+
// const skipAddrsSet = new Set<string>();
|
|
1193
|
+
// if (lcaAddr) {
|
|
1194
|
+
// try {
|
|
1195
|
+
// const lcaRes = await getFromSpace({ addr: lcaAddr, space: destSpace });
|
|
1196
|
+
// const lcaIbGib = lcaRes.ibGibs?.[0];
|
|
1197
|
+
// if (lcaIbGib) {
|
|
1198
|
+
// const lcaDeps = await getDependencyGraph({ ibGib: lcaIbGib, space: destSpace });
|
|
1199
|
+
// if (lcaDeps) Object.keys(lcaDeps).forEach(a => skipAddrsSet.add(a));
|
|
1200
|
+
// console.log(`${lc} [CONFLICT DEBUG] LCA deps to skip: ${skipAddrsSet.size}`);
|
|
1201
|
+
// }
|
|
1202
|
+
// } catch (e) {
|
|
1203
|
+
// console.warn(`${lc} Error getting LCA deps: ${extractErrorMsg(e)}`);
|
|
1204
|
+
// }
|
|
1205
|
+
// }
|
|
1206
|
+
// // For each receiver-only frame, get its DELTA dependency graph (minus LCA deps)
|
|
1207
|
+
// for (const addr of receiverOnlyAddrs) {
|
|
1208
|
+
// // Add the frame itself first
|
|
1209
|
+
// if (!mergeDeltaReqs.includes(addr)) {
|
|
1210
|
+
// mergeDeltaReqs.push(addr);
|
|
1211
|
+
// }
|
|
1212
|
+
// // Get the frame's delta dependencies (skip LCA's deps)
|
|
1213
|
+
// try {
|
|
1214
|
+
// const frameRes = await getFromSpace({ addr, space: destSpace });
|
|
1215
|
+
// const frameIbGib = frameRes.ibGibs?.[0];
|
|
1216
|
+
// if (frameIbGib) {
|
|
1217
|
+
// // Get dependency graph, skipping all LCA dependencies
|
|
1218
|
+
// const frameDeltaDeps = await getDependencyGraph({
|
|
1219
|
+
// ibGib: frameIbGib,
|
|
1220
|
+
// space: destSpace,
|
|
1221
|
+
// skipAddrs: Array.from(skipAddrsSet), // Skip entire LCA dep graph
|
|
1222
|
+
// });
|
|
1223
|
+
// if (frameDeltaDeps) {
|
|
1224
|
+
// // Add all delta dependencies (Object.keys gives us the addresses)
|
|
1225
|
+
// Object.keys(frameDeltaDeps).forEach(depAddr => {
|
|
1226
|
+
// if (!mergeDeltaReqs.includes(depAddr) && !skipAddrsSet.has(depAddr)) {
|
|
1227
|
+
// mergeDeltaReqs.push(depAddr);
|
|
1228
|
+
// }
|
|
1229
|
+
// });
|
|
1230
|
+
// }
|
|
1231
|
+
// }
|
|
1232
|
+
// } catch (depError) {
|
|
1233
|
+
// console.warn(`${lc} [CONFLICT DEBUG] Error getting delta deps for ${addr}: ${extractErrorMsg(depError)}`);
|
|
1234
|
+
// }
|
|
1235
|
+
// }
|
|
1236
|
+
// console.log(`${lc} [CONFLICT DEBUG] Total merge requests (frames + delta deps): ${mergeDeltaReqs.length}`);
|
|
1237
|
+
// } else {
|
|
1238
|
+
// console.log(`${lc} [CONFLICT DEBUG] No receiver-only frames found for this conflict`);
|
|
1239
|
+
// }
|
|
1161
1240
|
}
|
|
1162
|
-
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${
|
|
1241
|
+
console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. mergeDeltaReqs: ${mergeDeltaReqs.length}`);
|
|
1163
1242
|
}
|
|
1164
1243
|
else {
|
|
1165
1244
|
console.log(`${lc} [CONFLICT DEBUG] No optimistic conflicts to process`);
|