@ibgib/core-gib 0.1.38 → 0.1.40
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/graph-helper.d.mts.map +1 -1
- package/dist/common/other/graph-helper.mjs +18 -3
- package/dist/common/other/graph-helper.mjs.map +1 -1
- package/dist/sync/graft-info/graft-info-helpers.mjs +1 -1
- package/dist/sync/graft-info/graft-info-helpers.mjs.map +1 -1
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +321 -235
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs +6 -6
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +49 -12
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +4 -0
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
- package/dist/test-helpers.d.mts +104 -47
- package/dist/test-helpers.d.mts.map +1 -1
- package/dist/test-helpers.mjs +335 -131
- package/dist/test-helpers.mjs.map +1 -1
- package/dist/test-types.d.mts +25 -7
- package/dist/test-types.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs +2 -2
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs.map +1 -1
- package/package.json +1 -1
- package/src/common/other/graph-helper.mts +14 -2
- package/src/sync/SYNC_TESTING.md +135 -70
- package/src/sync/graft-info/graft-info-helpers.mts +1 -1
- package/src/sync/sync-conflict-adv-multitimelines.respec.mts +332 -245
- package/src/sync/sync-conflict-basic-multitimelines.respec.mts +5 -5
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +1 -1
- package/src/sync/sync-saga-coordinator.mts +58 -14
- package/src/sync/sync-saga-message/sync-saga-message-types.mts +4 -0
- package/src/test-helpers.mts +429 -152
- package/src/test-types.mts +30 -7
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts +2 -2
- package/tmp.md +205 -1160
|
@@ -14,29 +14,26 @@ import { clone, delay, extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/he
|
|
|
14
14
|
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
15
15
|
import { IbGibData_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
16
16
|
|
|
17
|
+
import { GLOBAL_LOG_A_LOT } from '../core-constants.mjs';
|
|
18
|
+
import { TestTransformer, getTestKeystoneServiceHelper } from '../test-helpers.mjs';
|
|
19
|
+
import { TestMut8Info, } from '../test-types.mjs';
|
|
17
20
|
import { SyncSagaCoordinator } from './sync-saga-coordinator.mjs';
|
|
18
21
|
import { getFromSpace } from '../witness/space/space-helper.mjs';
|
|
19
22
|
import { Metaspace_Innerspace } from '../witness/space/metaspace/metaspace-innerspace/metaspace-innerspace.mjs';
|
|
20
23
|
import { InnerSpace_V1 } from '../witness/space/inner-space/inner-space-v1.mjs';
|
|
21
|
-
import { createTimelineRootTestHelper, getTestKeystoneServiceHelper } from '../test-helpers.mjs';
|
|
22
|
-
import { appendToTimeline, createTimeline, mut8Timeline } from '../timeline/timeline-api.mjs';
|
|
23
24
|
import { SyncPeerInnerspace_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
|
|
24
25
|
import { DEFAULT_INNER_SPACE_DATA_V1 } from '../witness/space/inner-space/inner-space-types.mjs';
|
|
25
|
-
import { getIbGibsFromCache_fallbackToSpaces, getTjpAddr,
|
|
26
|
+
import { getIbGibsFromCache_fallbackToSpaces, getTjpAddr, } from '../common/other/ibgib-helper.mjs';
|
|
26
27
|
import { SyncSagaInfo } from './sync-types.mjs';
|
|
27
|
-
import { fnObs } from '../common/pubsub/observer/observer-helper.mjs';
|
|
28
28
|
import { getDependencyGraph, graphsAreEquivalent } from '../common/other/graph-helper.mjs';
|
|
29
|
-
import { ErrorIbGib_V1 } from '../common/error/error-types.mjs';
|
|
30
29
|
import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
|
|
31
30
|
import { SyncConflictStrategy } from './sync-constants.mjs';
|
|
32
|
-
import {
|
|
31
|
+
import { getHistory } from '../timeline/timeline-api.mjs';
|
|
33
32
|
|
|
34
|
-
const logalot =
|
|
33
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
35
34
|
const lc = sir;
|
|
36
35
|
|
|
37
|
-
|
|
38
36
|
interface TestData extends IbGibData_V1 {
|
|
39
|
-
type?: string;
|
|
40
37
|
/**
|
|
41
38
|
* field that is made in a common (pre-sync) ibgib
|
|
42
39
|
*/
|
|
@@ -47,9 +44,10 @@ interface TestData extends IbGibData_V1 {
|
|
|
47
44
|
|
|
48
45
|
const TEST_REL8N_NAME = 'testrel8n';
|
|
49
46
|
|
|
50
|
-
await respecfully(sir, `
|
|
47
|
+
await respecfully(sir, `Multi-round/timeline permutations`, async () => {
|
|
48
|
+
|
|
49
|
+
// #region Init/Setup
|
|
51
50
|
|
|
52
|
-
// 1. Setup Spaces
|
|
53
51
|
const metaspace = new Metaspace_Innerspace(undefined);
|
|
54
52
|
await metaspace.initialize({
|
|
55
53
|
getFnAlert: () => async ({ title, msg }) => { console.log(`[Alert] ${title}: ${msg}`); },
|
|
@@ -77,316 +75,341 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
77
75
|
});
|
|
78
76
|
await destSpace.initialized;
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
mut8Ib: alpha_v0.ib + '_common',
|
|
98
|
-
dataToAddOrPatch: { commonField: 'common yo' }
|
|
99
|
-
},
|
|
100
|
-
metaspace,
|
|
101
|
-
space: sourceSpace,
|
|
102
|
-
});
|
|
103
|
-
const tjpAddr =
|
|
104
|
-
getTjpAddr({ ibGib: alpha_v0, defaultIfNone: 'incomingAddr' }) ??
|
|
105
|
-
getIbGibAddr({ ibGib: alpha_v0 });
|
|
106
|
-
// Sync alpha to dest immediately so they start synced
|
|
107
|
-
// must get the entire dependency graph for alpha
|
|
108
|
-
const depGraph_alpha_v1Andcommon = await getDependencyGraph({
|
|
109
|
-
ibGibAddrs: [tjpAddr],
|
|
110
|
-
space: sourceSpace,
|
|
111
|
-
live: true,
|
|
112
|
-
}) ?? {};
|
|
113
|
-
console.log(`${lc} depGraph_testRootAndV1Common: ${pretty(depGraph_alpha_v1Andcommon)}`)
|
|
114
|
-
if (Object.keys(depGraph_alpha_v1Andcommon).length === 0) {
|
|
115
|
-
throw new Error(`(UNEXPECTED) depGraph_testRootAndV1Common empty? (E: 39b4d855ffa65476084b4123786da826)`);
|
|
116
|
-
}
|
|
117
|
-
// put the entire graph into the destspace, but...
|
|
118
|
-
await metaspace.put({ ibGibs: Object.values(depGraph_alpha_v1Andcommon), space: destSpace });
|
|
119
|
-
const resGetDest = await getFromSpace({ space: destSpace, addr: getIbGibAddr({ ibGib: alpha_v1_common_onSource }) });
|
|
120
|
-
if (!resGetDest.success || !resGetDest.ibGibs || resGetDest.ibGibs.length === 0) {
|
|
121
|
-
throw new Error(`Failed to retrieve v1_Common_onDest from destSpace. (E: 40c67811eba14f729880a46dcbb65126)`);
|
|
78
|
+
const testTransformer = new TestTransformer(metaspace, sourceSpace, destSpace);
|
|
79
|
+
|
|
80
|
+
if (logalot) { console.log(`${lc} Setting up Coordinators...`); }
|
|
81
|
+
const mockKeystone = await getTestKeystoneServiceHelper();
|
|
82
|
+
const senderCoordinator = new SyncSagaCoordinator(mockKeystone);
|
|
83
|
+
const receiverCoordinator = new SyncSagaCoordinator(mockKeystone);
|
|
84
|
+
|
|
85
|
+
async function newTestPeer(): Promise<SyncPeerInnerspace_V1> {
|
|
86
|
+
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
87
|
+
await peer.initialized;
|
|
88
|
+
await peer.initializeSender({
|
|
89
|
+
senderSpace: sourceSpace,
|
|
90
|
+
receiverSpace: destSpace,
|
|
91
|
+
receiverCoordinator: receiverCoordinator,
|
|
92
|
+
receiverMetaspace: metaspace,
|
|
93
|
+
});
|
|
94
|
+
return peer;
|
|
122
95
|
}
|
|
96
|
+
|
|
97
|
+
// #endregion Init/Setup
|
|
98
|
+
|
|
99
|
+
// #region Round 1: Seed common history
|
|
100
|
+
|
|
123
101
|
/**
|
|
124
|
-
*
|
|
102
|
+
* not sure if we're going to do anything with the round info itself
|
|
125
103
|
*/
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
104
|
+
const _r1 = testTransformer.newRound({
|
|
105
|
+
name: 'r1_seedCommonHistory',
|
|
106
|
+
description: 'Create alpha v0 and v1 on source, sync to dest so both v0 and v1 are established as synced.',
|
|
107
|
+
});
|
|
130
108
|
|
|
109
|
+
// #region r1 setup
|
|
131
110
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
111
|
+
if (logalot) { console.log(`${lc} Creating common History...`); }
|
|
112
|
+
const r1_alpha_v0_source = await testTransformer.create({
|
|
113
|
+
atom: 'alpha',
|
|
114
|
+
in: 'source',
|
|
115
|
+
name: 'r1_alpha_v0_source', // should be auto-calculated?
|
|
116
|
+
});
|
|
136
117
|
|
|
137
|
-
//
|
|
118
|
+
// Create v1 (common) - will be synced to dest
|
|
119
|
+
const r1_alpha_v1_source_common = await testTransformer.mut8({
|
|
120
|
+
stepInfo: r1_alpha_v0_source,
|
|
121
|
+
strField: 'commonField',
|
|
122
|
+
name: 'r1_alpha_v1_source_common'
|
|
123
|
+
});
|
|
124
|
+
const alpha_tjpAddr =
|
|
125
|
+
getTjpAddr({ ibGib: r1_alpha_v0_source.ibGib, defaultIfNone: 'incomingAddr' })!;
|
|
138
126
|
|
|
139
|
-
//
|
|
127
|
+
// #endregion r1 setup
|
|
140
128
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
129
|
+
await respecfully(sir, `r1 verify pre`, async () => {
|
|
130
|
+
await ifWeMight(sir, 'dest should NOT have alpha', async () => {
|
|
131
|
+
const resGet = await getFromSpace({
|
|
132
|
+
space: destSpace,
|
|
133
|
+
addr: alpha_tjpAddr,
|
|
134
|
+
});
|
|
135
|
+
// When timeline doesn't exist, getFromSpace returns success:false
|
|
136
|
+
iReckon(sir, resGet.success).asTo('getFromSpace should return false for missing timeline').isGonnaBeFalse();
|
|
137
|
+
iReckon(sir, resGet.ibGibs?.length ?? 0).asTo('Dest should NOT have alpha timeline yet').isGonnaBe(0);
|
|
138
|
+
});
|
|
147
139
|
});
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
mut8Opts: {
|
|
153
|
-
mut8Ib: alpha_v0.ib + '_v2source',
|
|
154
|
-
dataToAddOrPatch: { fieldA: 'source_edit' }
|
|
155
|
-
},
|
|
140
|
+
|
|
141
|
+
const r1_syncSaga = await senderCoordinator.sync({
|
|
142
|
+
peer: await newTestPeer(),
|
|
143
|
+
localSpace: sourceSpace,
|
|
156
144
|
metaspace,
|
|
157
|
-
|
|
145
|
+
domainIbGibs: [r1_alpha_v1_source_common.ibGib],
|
|
146
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
147
|
+
useSessionIdentity: false,
|
|
158
148
|
});
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
149
|
+
|
|
150
|
+
await r1_syncSaga.done;
|
|
151
|
+
if (logalot) { console.log(`${lc} r1_syncSaga Complete.`); }
|
|
152
|
+
|
|
153
|
+
await respecfully(sir, `r1 verify post`, async () => {
|
|
154
|
+
await ifWeMight(sir, 'dest should have alpha', async () => {
|
|
155
|
+
// alpha's full dep graph should exist on dest
|
|
156
|
+
const [alpha_dest] = await getIbGibsFromCache_fallbackToSpaces({
|
|
157
|
+
addrs: [r1_alpha_v0_source.addr],
|
|
158
|
+
space: destSpace,
|
|
159
|
+
});
|
|
160
|
+
iReckon(sir, alpha_dest).asTo('alpha exists in dest').isGonnaBeTruthy();
|
|
161
|
+
if (alpha_dest) {
|
|
162
|
+
const depGraph_alpha_source = await getDependencyGraph({ ibGib: r1_alpha_v0_source.ibGib, space: sourceSpace });
|
|
163
|
+
const depGraph_alpha_dest = await getDependencyGraph({ ibGib: alpha_dest, space: destSpace });
|
|
164
|
+
const alphaDepsAreEqual = graphsAreEquivalent({
|
|
165
|
+
graphA: depGraph_alpha_source, graphB: depGraph_alpha_dest
|
|
166
|
+
});
|
|
167
|
+
iReckon(sir, alphaDepsAreEqual).asTo('alpha got synced and graphs are equal').isGonnaBeTrue();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
166
170
|
});
|
|
167
|
-
/**
|
|
168
|
-
* since we're doing this first, this will be the base in our graft
|
|
169
|
-
*/
|
|
170
|
-
const baseAddr = getIbGibAddr({ ibGib: alpha_v3_source_rel8beta });
|
|
171
171
|
|
|
172
|
-
//
|
|
172
|
+
// Get alpha_v1_common from destSpace for Round 2
|
|
173
|
+
const resGetDest = await getFromSpace({ space: destSpace, addr: alpha_tjpAddr });
|
|
174
|
+
if (!resGetDest.success || !resGetDest.ibGibs || resGetDest.ibGibs.length === 0) {
|
|
175
|
+
throw new Error(`Failed to retrieve alpha from destSpace after sync. (E: 40c67811eba14f729880a46dcbb65126)`);
|
|
176
|
+
}
|
|
177
|
+
const alpha_v1_common_onDest = resGetDest.ibGibs[0];
|
|
173
178
|
|
|
174
|
-
|
|
175
|
-
* timestamp/timestampMs drives orphan/base timeline selection in
|
|
176
|
-
* graftTimelines
|
|
177
|
-
*/
|
|
178
|
-
await delay(16);
|
|
179
|
+
// #endregion Round 1: Seed common history
|
|
179
180
|
|
|
181
|
+
// #region Round 2: Create Divergence (v2source vs v2dest) - "simultaneous" parallel edits
|
|
180
182
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
timeline: alpha_v1_common_onDest,
|
|
185
|
-
mut8Opts: {
|
|
186
|
-
mut8Ib: alpha_v0.ib + '_v2dest',
|
|
187
|
-
dataToAddOrPatch: { fieldB: 'dest_edit' }
|
|
188
|
-
},
|
|
189
|
-
metaspace,
|
|
190
|
-
space: destSpace,
|
|
183
|
+
const _r2 = testTransformer.newRound({
|
|
184
|
+
name: 'r2_divergent_edits',
|
|
185
|
+
description: 'Create conflicts on alpha, add beta relation on source, separate edit on dest'
|
|
191
186
|
});
|
|
192
|
-
/**
|
|
193
|
-
* since we're doing this second (i.e., later temporally), this will be
|
|
194
|
-
* the orphan in our graft
|
|
195
|
-
*/
|
|
196
|
-
const orphanAddr = getIbGibAddr({ ibGib: alpha_v2_dest });
|
|
197
187
|
|
|
198
|
-
//
|
|
199
|
-
console.log(`${lc} Divergence created.`);
|
|
188
|
+
// #region r2 source edits
|
|
200
189
|
|
|
190
|
+
if (logalot) { console.log(`${lc} Creating Divergence...`); }
|
|
201
191
|
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
192
|
+
// Source: Create beta, mutate alpha fieldA, add beta relation
|
|
193
|
+
const r2_beta_v0_source = await testTransformer.create({
|
|
194
|
+
atom: 'beta',
|
|
195
|
+
in: 'source',
|
|
196
|
+
data: { fieldA: 'beta field A created on source' },
|
|
197
|
+
name: 'r2_beta_v0_source'
|
|
198
|
+
});
|
|
199
|
+
const r2_alpha_v2_source_arbitraryMut8 = await testTransformer.mut8({
|
|
200
|
+
ibGib: r1_alpha_v1_source_common.ibGib,
|
|
201
|
+
in: 'source',
|
|
202
|
+
strField: 'fieldA',
|
|
203
|
+
name: 'r2_alpha_v2_source_arbitraryMut8',
|
|
204
|
+
comments_snake_plus_CamelCase: 'editedOnSource',
|
|
205
|
+
});
|
|
206
|
+
const r2_alpha_v3_source_rel8dBeta = await testTransformer.rel8({
|
|
207
|
+
stepInfo: r2_alpha_v2_source_arbitraryMut8,
|
|
208
|
+
in: 'source',
|
|
209
|
+
targetIbGibs: [r2_beta_v0_source.ibGib],
|
|
210
|
+
rel8nName: TEST_REL8N_NAME,
|
|
211
|
+
name: 'r2_alpha_v3_source_rel8dBeta'
|
|
212
|
+
});
|
|
207
213
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
// #endregion r2 source edits
|
|
215
|
+
|
|
216
|
+
// #region r2 dest edits
|
|
217
|
+
|
|
218
|
+
// Dest: Mutate alpha fieldB (different field than source)
|
|
219
|
+
const r2_alpha_v2_dest_mut8FieldB = await testTransformer.mut8({
|
|
220
|
+
ibGib: alpha_v1_common_onDest,
|
|
221
|
+
in: 'dest',
|
|
222
|
+
strField: 'fieldB',
|
|
223
|
+
name: 'r2_alpha_v2_dest_mut8FieldB',
|
|
224
|
+
comments_snake_plus_CamelCase: 'editedOnDest',
|
|
215
225
|
});
|
|
216
226
|
|
|
227
|
+
if (logalot) { console.log(`${lc} Divergence created.`); }
|
|
228
|
+
|
|
229
|
+
// #endregion r2 dest edits
|
|
230
|
+
|
|
217
231
|
// Verify Receiver has correct KV (Pre-Sync Check)
|
|
218
232
|
// This ensures the conflict precondition exists.
|
|
219
|
-
await
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
233
|
+
await respecfully(sir, `r2 verify pre`, async () => {
|
|
234
|
+
await ifWeMight(sir, 'dest has alpha v1 common', async () => {
|
|
235
|
+
try {
|
|
236
|
+
const destKV = await receiverCoordinator.getKnowledgeMap({
|
|
237
|
+
space: destSpace,
|
|
238
|
+
metaspace,
|
|
239
|
+
domainIbGibs: [alpha_v1_common_onDest]
|
|
240
|
+
});
|
|
241
|
+
const alpha_v1_common_tjpAddr_onDest =
|
|
242
|
+
getTjpAddr({ ibGib: alpha_v1_common_onDest, defaultIfNone: 'incomingAddr' })!;
|
|
227
243
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
const destTip = destKV[alpha_v1_common_tjpAddr_onDest];
|
|
245
|
+
iReckon(sir, !!destTip).asTo(`Dest KV has timeline tip for ${alpha_v1_common_tjpAddr_onDest}`).isGonnaBeTruthy();
|
|
246
|
+
if (!destTip) {
|
|
247
|
+
throw new Error(`Test Setup Fail: Dest Space does not have index for timeline ${alpha_v1_common_tjpAddr_onDest}. Seeding failed. (E: c194a80b4e4877b77826c37a1753b826)`);
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
251
|
+
iReckon(sir, true).asTo('getKnowledgeMap errored out').isGonnaBeFalse();
|
|
233
252
|
}
|
|
234
|
-
}
|
|
235
|
-
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
236
|
-
iReckon(sir, true).asTo('getKnowledgeMap errored out').isGonnaBeFalse();
|
|
237
|
-
}
|
|
253
|
+
});
|
|
238
254
|
});
|
|
239
255
|
|
|
240
|
-
console.log(`${lc} Running Sync (ConflictStrategy: optimistic)...`);
|
|
256
|
+
if (logalot) { console.log(`${lc} Running Sync (ConflictStrategy: optimistic)...`); }
|
|
241
257
|
|
|
242
|
-
let
|
|
258
|
+
let r2_syncSaga: SyncSagaInfo | undefined;
|
|
243
259
|
try {
|
|
244
|
-
console.dir(sourceSpace)
|
|
245
|
-
console.dir(destSpace)
|
|
246
|
-
|
|
247
|
-
peer,
|
|
260
|
+
if (logalot) { console.dir(sourceSpace) }
|
|
261
|
+
if (logalot) { console.dir(destSpace) }
|
|
262
|
+
r2_syncSaga = await senderCoordinator.sync({
|
|
263
|
+
peer: await newTestPeer(),
|
|
248
264
|
localSpace: sourceSpace,
|
|
249
265
|
metaspace,
|
|
250
|
-
domainIbGibs: [
|
|
266
|
+
domainIbGibs: [r2_alpha_v3_source_rel8dBeta.ibGib],
|
|
251
267
|
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
252
268
|
useSessionIdentity: false,
|
|
253
269
|
});
|
|
254
270
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
* I have added this so you can see how to subscribe to an ibgib
|
|
258
|
-
* observable using {@link fnObs}.
|
|
259
|
-
*/
|
|
260
|
-
const subscription = await resSync.updates$.subscribe(fnObs({
|
|
261
|
-
next: async (ctxIbGib) => {
|
|
262
|
-
// console.log(`${sublc} next fired. ${JSON.stringify(ctxIbGib)}`);
|
|
263
|
-
console.log(`${sublc} next fired. (I: e68d8894bac8800f9f3430e8a38d6626)`);
|
|
264
|
-
},
|
|
265
|
-
error: async (e: ErrorIbGib_V1) => {
|
|
266
|
-
if (e.data) {
|
|
267
|
-
console.error(`${sublc} error fired. error: ${JSON.stringify(e.data)} (E: eddf17f76a486b9c5a2f4ee86ed38b26)`);
|
|
268
|
-
} else {
|
|
269
|
-
console.dir(e);
|
|
270
|
-
console.error(`${sublc} error fired. error: ${extractErrorMsg(e)} (E: af9c3b6f1c88befeff77ca46111b3826)`);
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
complete: async () => {
|
|
274
|
-
console.log(`${sublc} complete fired`);
|
|
275
|
-
},
|
|
276
|
-
}));
|
|
277
|
-
|
|
278
|
-
console.log(`${lc} awaiting resSync.done`)
|
|
279
|
-
await resSync.done;
|
|
271
|
+
if (logalot) { console.log(`${lc} awaiting r2_syncSaga.done`) }
|
|
272
|
+
await r2_syncSaga.done;
|
|
280
273
|
|
|
281
|
-
console.log(`${lc}
|
|
274
|
+
if (logalot) { console.log(`${lc} r2_syncSaga Complete.`); }
|
|
282
275
|
} catch (e) {
|
|
283
276
|
console.error(`${lc} Sync Failed with Error:`, e);
|
|
284
277
|
iReckon(sir, false).asTo(`Sync failed with error: ${e}`).isGonnaBeTruthy();
|
|
285
278
|
return; // Exit test early
|
|
286
279
|
}
|
|
287
280
|
|
|
288
|
-
// 5. Verification
|
|
289
281
|
// Expectation: Both Spaces should now have a NEW tip (V3) that merges v2source and v2dest.
|
|
282
|
+
await respecfully(sir, `r2 verify post`, async () => {
|
|
290
283
|
|
|
291
|
-
const resSourceTip = await getFromSpace({ space: sourceSpace, addr: getIbGibAddr({ ibGib: alpha_v3_source_rel8beta }) });
|
|
292
|
-
|
|
293
|
-
await respecfully(sir, `verify merge`, async () => {
|
|
294
284
|
// Retrieve updated KV from Source (or check what happened to v2source)
|
|
295
285
|
// Ideally, we just check the source space for the timeline tip
|
|
296
286
|
// The timeline tip for alpha/v0 should now be NEW.
|
|
297
287
|
|
|
298
288
|
try {
|
|
299
289
|
// Get the KV for the Source Space
|
|
300
|
-
const
|
|
290
|
+
const alpha_sourceKV_afterSync = await senderCoordinator.getKnowledgeMap({
|
|
301
291
|
space: sourceSpace,
|
|
302
292
|
metaspace,
|
|
303
|
-
domainIbGibs: [
|
|
293
|
+
domainIbGibs: [r1_alpha_v0_source.ibGib] // We want to know the tip of this timeline
|
|
304
294
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
295
|
+
if (logalot) { console.log(`${lc} getKnowledgeMap returned. sourceKV_afterSync: ${pretty(alpha_sourceKV_afterSync)} (I: e8780cda37c8b2a46eeb85786874e926)`); }
|
|
296
|
+
const alpha_source_tipAddr = alpha_sourceKV_afterSync[alpha_tjpAddr];
|
|
297
|
+
if (logalot) { console.log(`${lc} alpha_source_tipAddr: ${alpha_source_tipAddr} (I: 34590f29c9b706ba04a54b0f633a6426)`); }
|
|
298
|
+
if (!alpha_source_tipAddr) {
|
|
299
|
+
throw new Error(`Source Space missing timeline tip for ${alpha_tjpAddr} (E: ec95980b9c980c5c5870812e15e43826)`);
|
|
300
|
+
}
|
|
310
301
|
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
302
|
+
const alpha_destKV_afterSync = await senderCoordinator.getKnowledgeMap({
|
|
303
|
+
space: destSpace,
|
|
304
|
+
metaspace,
|
|
305
|
+
domainIbGibs: [r1_alpha_v0_source.ibGib] // We want to know the tip of this timeline
|
|
306
|
+
});
|
|
307
|
+
if (logalot) { console.log(`${lc} getKnowledgeMap returned. destKV_afterSync: ${pretty(alpha_destKV_afterSync)} (I: e8780cda37c8b2a46eeb85786874e926)`); }
|
|
308
|
+
const alpha_dest_tipAddr = alpha_destKV_afterSync[alpha_tjpAddr];
|
|
309
|
+
if (logalot) { console.log(`${lc} alpha_dest_tipAddr: ${alpha_dest_tipAddr} (I: afac71eba4e6d3f3c47952680ad8b826)`); }
|
|
310
|
+
if (!alpha_dest_tipAddr) {
|
|
311
|
+
throw new Error(`dest Space missing timeline tip for ${alpha_tjpAddr} (E: 30b018c6349917aa28c9f538fa567826)`);
|
|
314
312
|
}
|
|
313
|
+
await ifWeMight(sir, 'tip addrs', async () => {
|
|
314
|
+
iReckon(sir, alpha_source_tipAddr).asTo('source/dest have same tip addrs').isGonnaBe(alpha_dest_tipAddr);
|
|
315
|
+
})
|
|
315
316
|
|
|
316
317
|
// Fetch the new tip
|
|
317
|
-
const
|
|
318
|
-
const
|
|
318
|
+
const resGet_alpha_source_tipAddr = await getFromSpace({ space: sourceSpace, addr: alpha_source_tipAddr });
|
|
319
|
+
const gotten_alpha_source_tipIbGib = resGet_alpha_source_tipAddr.ibGibs![0] as IbGib_V1<TestData>;
|
|
319
320
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
321
|
+
if (logalot || true) {
|
|
322
|
+
console.log(`${lc} gotten_alpha_source_tipIbGib:\n${pretty(gotten_alpha_source_tipIbGib)} (I: e9c608c1fcb85f08d17d4af319d62726)`);
|
|
323
|
+
}
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
// #region DEBUG SANITY CHECK
|
|
326
|
+
const resGetTjp = await getFromSpace({ space: sourceSpace, addr: alpha_tjpAddr });
|
|
327
|
+
const gottenTjp = resGetTjp.ibGibs![0] as IbGib_V1<TestData>;
|
|
328
|
+
debugger;
|
|
329
|
+
const history = await getHistory({
|
|
330
|
+
timeline: gotten_alpha_source_tipIbGib,
|
|
331
|
+
space: sourceSpace,
|
|
332
|
+
metaspace,
|
|
333
|
+
includeDna: true,
|
|
327
334
|
});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
iReckon(sir,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
//
|
|
341
|
-
const
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
iReckon(sir,
|
|
353
|
-
iReckon(sir, baseRel!.at(-1)).asTo('base rel8ns final addr will be baseAddr').isGonnaBe(baseAddr);
|
|
354
|
-
iReckon(sir, orphanRel![0]).asTo('orphan rel8ns will be later addr').isGonnaBe(orphanAddr);
|
|
335
|
+
debugger;
|
|
336
|
+
// #endregion DEBUG SANITY CHECK
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
await ifWeMight(sir, 'r2 basics of alpha merge', async () => {
|
|
340
|
+
iReckon(sir, alpha_source_tipAddr)
|
|
341
|
+
.asTo(`Source Tip (${alpha_source_tipAddr}) should NOT be r2_alpha_v3_source_rel8dBeta`)
|
|
342
|
+
.not.isGonnaBe(r2_alpha_v3_source_rel8dBeta.addr);
|
|
343
|
+
iReckon(sir, alpha_source_tipAddr)
|
|
344
|
+
.asTo(`Source Tip (${alpha_source_tipAddr}) should NOT be r2_alpha_v2_dest_mut8FieldB`)
|
|
345
|
+
.not.isGonnaBe(r2_alpha_v2_dest_mut8FieldB.addr);
|
|
346
|
+
|
|
347
|
+
// Check Data: Should have BOTH edits (using testTransformer-generated values)
|
|
348
|
+
const r2_source_mut8Info = r2_alpha_v2_source_arbitraryMut8.infos[0] as TestMut8Info;
|
|
349
|
+
const r2_dest_mut8Info = r2_alpha_v2_dest_mut8FieldB.infos[0] as TestMut8Info;
|
|
350
|
+
|
|
351
|
+
const a = gotten_alpha_source_tipIbGib.data![r2_source_mut8Info.key!];
|
|
352
|
+
const a2 = r2_source_mut8Info.value!;
|
|
353
|
+
console.log(`${a} should be ${a2}`)
|
|
354
|
+
iReckon(sir, gotten_alpha_source_tipIbGib.data![r2_source_mut8Info.key!]).asTo(`New Tip has source field ${r2_source_mut8Info.key!}`).isGonnaBe(r2_source_mut8Info.value!);
|
|
355
|
+
|
|
356
|
+
const b = gotten_alpha_source_tipIbGib.data![r2_dest_mut8Info.key!];
|
|
357
|
+
const b2 = r2_dest_mut8Info.value!;
|
|
358
|
+
console.log(`${b} should be ${b2}`)
|
|
359
|
+
iReckon(sir, gotten_alpha_source_tipIbGib.data![r2_dest_mut8Info.key!]).asTo(`New Tip has dest field ${r2_dest_mut8Info.key!}`).isGonnaBe(r2_dest_mut8Info.value!);
|
|
355
360
|
});
|
|
356
361
|
|
|
357
|
-
await ifWeMight(sir, 'alpha and deps synced', async () => {
|
|
358
|
-
// alpha's full dep graph should exist on dest
|
|
359
|
-
|
|
360
|
-
|
|
362
|
+
await ifWeMight(sir, 'r2 alpha and deps synced', async () => {
|
|
363
|
+
// alpha's full dep graph should exist on dest, even though its
|
|
364
|
+
// timeline was grafted
|
|
365
|
+
const [alpha_dest] = await getIbGibsFromCache_fallbackToSpaces({
|
|
366
|
+
addrs: [r1_alpha_v0_source.addr],
|
|
361
367
|
space: destSpace,
|
|
362
368
|
});
|
|
363
|
-
iReckon(sir,
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
369
|
+
iReckon(sir, alpha_dest).asTo('alpha exists in dest').isGonnaBeTruthy();
|
|
370
|
+
if (alpha_dest) {
|
|
371
|
+
try {
|
|
372
|
+
const depGraph_alpha_source = await getDependencyGraph({
|
|
373
|
+
ibGib: r1_alpha_v0_source.ibGib,
|
|
374
|
+
live: true,
|
|
375
|
+
space: sourceSpace
|
|
376
|
+
});
|
|
377
|
+
const depGraph_alpha_dest = await getDependencyGraph({
|
|
378
|
+
ibGib: alpha_dest,
|
|
379
|
+
live: true,
|
|
380
|
+
space: destSpace
|
|
381
|
+
});
|
|
382
|
+
const alphaDepsAreEqual = graphsAreEquivalent({
|
|
383
|
+
graphA: depGraph_alpha_source,
|
|
384
|
+
graphB: depGraph_alpha_dest,
|
|
385
|
+
slowButThorough: true,
|
|
386
|
+
});
|
|
387
|
+
iReckon(sir, alphaDepsAreEqual).asTo('alpha got synced and graphs are equal').isGonnaBeTrue();
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
390
|
+
iReckon(sir, true).asTo('ERROR: alpha exists in dest').isGonnaBeFalse(); // fails
|
|
368
391
|
}
|
|
369
|
-
const depGraph_beta_dest = await getDependencyGraph({ ibGib: beta_dest, space: destSpace });
|
|
370
|
-
const betaDepsAreEqual = graphsAreEquivalent({
|
|
371
|
-
graphA: depGraph_beta_source, graphB: depGraph_beta_dest
|
|
372
|
-
});
|
|
373
|
-
iReckon(sir, betaDepsAreEqual).asTo('beta got synced and graphs are equal').isGonnaBeTrue();
|
|
374
392
|
}
|
|
375
393
|
});
|
|
376
394
|
|
|
377
|
-
await ifWeMight(sir, 'beta and deps synced', async () => {
|
|
395
|
+
await ifWeMight(sir, 'r2 beta and deps synced', async () => {
|
|
378
396
|
// beta's full dep graph should exist on dest
|
|
379
397
|
const [beta_dest] = await getIbGibsFromCache_fallbackToSpaces({
|
|
380
|
-
addrs: [
|
|
398
|
+
addrs: [r2_beta_v0_source.addr],
|
|
381
399
|
space: destSpace,
|
|
382
400
|
});
|
|
383
401
|
iReckon(sir, beta_dest).asTo('beta exists in dest').isGonnaBeTruthy();
|
|
384
402
|
if (beta_dest) {
|
|
385
|
-
const depGraph_beta_source = await getDependencyGraph({
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
403
|
+
const depGraph_beta_source = await getDependencyGraph({
|
|
404
|
+
ibGib: r2_beta_v0_source.ibGib,
|
|
405
|
+
live: true,
|
|
406
|
+
space: sourceSpace
|
|
407
|
+
});
|
|
408
|
+
const depGraph_beta_dest = await getDependencyGraph({
|
|
409
|
+
ibGib: beta_dest,
|
|
410
|
+
live: true,
|
|
411
|
+
space: destSpace
|
|
412
|
+
});
|
|
390
413
|
const betaDepsAreEqual = graphsAreEquivalent({
|
|
391
414
|
graphA: depGraph_beta_source,
|
|
392
415
|
graphB: depGraph_beta_dest,
|
|
@@ -403,4 +426,68 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
403
426
|
|
|
404
427
|
});
|
|
405
428
|
|
|
429
|
+
// #endregion Round 2: Create Divergence (v2source vs v2dest) - "simultaneous" parallel edits
|
|
430
|
+
|
|
431
|
+
// #region Round 3: Multiple Timeline Conflicts
|
|
432
|
+
|
|
433
|
+
const _r3 = testTransformer.newRound({
|
|
434
|
+
name: 'r3_multiple_timeline_conflicts',
|
|
435
|
+
description: 'Both alpha AND beta have divergent edits on source vs dest - tests multiple simultaneous grafts'
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// #region r3 source edits
|
|
439
|
+
|
|
440
|
+
if (logalot) { console.log(`${lc} Creating r3 divergent edits on source...`); }
|
|
441
|
+
|
|
442
|
+
// Source: Mutate alpha fieldC, mutate beta betaFieldA
|
|
443
|
+
// TODO: Add source edits here
|
|
444
|
+
|
|
445
|
+
// #endregion r3 source edits
|
|
446
|
+
|
|
447
|
+
// #region r3 dest edits
|
|
448
|
+
|
|
449
|
+
if (logalot) { console.log(`${lc} Creating r3 divergent edits on dest...`); }
|
|
450
|
+
|
|
451
|
+
// Dest: Mutate alpha fieldD, mutate beta betaFieldB
|
|
452
|
+
// TODO: Add dest edits here
|
|
453
|
+
|
|
454
|
+
// #endregion r3 dest edits
|
|
455
|
+
|
|
456
|
+
await respecfully(sir, `r3 verify pre`, async () => {
|
|
457
|
+
// TODO: Verify pre-sync state
|
|
458
|
+
await ifWeMight(sir, 'source has divergent alpha and beta', async () => {
|
|
459
|
+
// Verify source has its versions
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
await ifWeMight(sir, 'dest has divergent alpha and beta', async () => {
|
|
463
|
+
// Verify dest has its versions
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
if (logalot) { console.log(`${lc} Running r3 Sync...`); }
|
|
468
|
+
|
|
469
|
+
// TODO: Add sync operation here
|
|
470
|
+
// const r3_syncSaga = await senderCoordinator.sync({...});
|
|
471
|
+
|
|
472
|
+
await respecfully(sir, `r3 verify post`, async () => {
|
|
473
|
+
// TODO: Verify post-sync state
|
|
474
|
+
|
|
475
|
+
await ifWeMight(sir, 'r3 alpha merge has both edits', async () => {
|
|
476
|
+
// Verify alpha has fieldC (source) AND fieldD (dest)
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
await ifWeMight(sir, 'r3 beta merge has both edits', async () => {
|
|
480
|
+
// Verify beta has betaFieldA (source) AND betaFieldB (dest)
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
await ifWeMight(sir, 'r3 alpha and deps synced', async () => {
|
|
484
|
+
// Verify alpha's full dep graph on both spaces
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
await ifWeMight(sir, 'r3 beta and deps synced', async () => {
|
|
488
|
+
// Verify beta's full dep graph on both spaces
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// #endregion Round 3: Multiple Timeline Conflicts
|
|
406
493
|
});
|