@livestore/common 0.3.0-dev.27 → 0.3.0-dev.28
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/.tsbuildinfo +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +24 -24
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +16 -3
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +65 -27
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -3
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +8 -1
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +5 -0
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/MutationEvent.js +1 -1
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +21 -15
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +160 -170
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/leader-thread/LeaderSyncProcessor.ts +105 -34
- package/src/leader-thread/make-leader-thread-layer.ts +34 -12
- package/src/schema/EventId.ts +6 -0
- package/src/schema/MutationEvent.ts +1 -1
- package/src/sync/syncstate.test.ts +160 -171
- package/src/sync/syncstate.ts +29 -19
- package/src/version.ts +1 -1
- package/tmp/pack.tgz +0 -0
@@ -31,14 +31,13 @@ class TestEvent extends MutationEvent.EncodedWithMeta {
|
|
31
31
|
// toString = () => this.toJSON()
|
32
32
|
}
|
33
33
|
|
34
|
-
const
|
35
|
-
const
|
36
|
-
const
|
37
|
-
const
|
38
|
-
const
|
39
|
-
const
|
40
|
-
const
|
41
|
-
const e_3_0 = new TestEvent({ global: 3, client: 0 }, e_2_0.id, 'a', false)
|
34
|
+
const e0_1 = new TestEvent({ global: 0, client: 1 }, EventId.ROOT, 'a', true)
|
35
|
+
const e1_0 = new TestEvent({ global: 1, client: 0 }, EventId.ROOT, 'a', false)
|
36
|
+
const e1_1 = new TestEvent({ global: 1, client: 1 }, e1_0.id, 'a', true)
|
37
|
+
const e1_2 = new TestEvent({ global: 1, client: 2 }, e1_1.id, 'a', true)
|
38
|
+
const e1_3 = new TestEvent({ global: 1, client: 3 }, e1_2.id, 'a', true)
|
39
|
+
const e2_0 = new TestEvent({ global: 2, client: 0 }, e1_0.id, 'a', false)
|
40
|
+
const e2_1 = new TestEvent({ global: 2, client: 1 }, e2_0.id, 'a', true)
|
42
41
|
|
43
42
|
const isEqualEvent = MutationEvent.isEqualEncoded
|
44
43
|
|
@@ -59,271 +58,261 @@ describe('syncstate', () => {
|
|
59
58
|
describe('upstream-rebase', () => {
|
60
59
|
it('should rollback until start', () => {
|
61
60
|
const syncState = new SyncState.SyncState({
|
62
|
-
pending: [
|
61
|
+
pending: [e2_0],
|
63
62
|
upstreamHead: EventId.ROOT,
|
64
|
-
localHead:
|
63
|
+
localHead: e2_0.id,
|
65
64
|
})
|
66
|
-
const
|
67
|
-
const
|
65
|
+
const e1_0_e2_0 = e1_0.rebase_(e2_0.id)
|
66
|
+
const e1_1_e2_1 = e1_1.rebase_(e1_0_e2_0.id)
|
68
67
|
const result = merge({
|
69
68
|
syncState,
|
70
69
|
payload: SyncState.PayloadUpstreamRebase.make({
|
71
|
-
rollbackEvents: [
|
72
|
-
newEvents: [
|
70
|
+
rollbackEvents: [e1_0, e1_1],
|
71
|
+
newEvents: [e1_0_e2_0, e1_1_e2_1],
|
73
72
|
}),
|
74
73
|
})
|
75
|
-
const
|
74
|
+
const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.id)
|
76
75
|
expectRebase(result)
|
77
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
78
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
79
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
80
|
-
expectEventArraysEqual(result.newEvents, [
|
81
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
76
|
+
expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
|
77
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_1.id)
|
78
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.id)
|
79
|
+
expectEventArraysEqual(result.newEvents, [e1_0_e2_0, e1_1_e2_1, e2_0_e3_0])
|
80
|
+
expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1, e2_0])
|
82
81
|
})
|
83
82
|
|
84
83
|
it('should rollback only to specified point', () => {
|
85
84
|
const syncState = new SyncState.SyncState({
|
86
|
-
pending: [
|
85
|
+
pending: [e2_0],
|
87
86
|
upstreamHead: EventId.ROOT,
|
88
|
-
localHead:
|
87
|
+
localHead: e2_0.id,
|
89
88
|
})
|
90
|
-
const
|
89
|
+
const e1_1_e2_0 = e1_1.rebase_(e1_0.id)
|
91
90
|
const result = merge({
|
92
91
|
syncState,
|
93
92
|
payload: SyncState.PayloadUpstreamRebase.make({
|
94
|
-
newEvents: [
|
95
|
-
rollbackEvents: [
|
93
|
+
newEvents: [e1_1_e2_0],
|
94
|
+
rollbackEvents: [e1_1],
|
96
95
|
}),
|
97
96
|
})
|
98
|
-
const
|
97
|
+
const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.id)
|
99
98
|
expectRebase(result)
|
100
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
101
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
102
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
103
|
-
expectEventArraysEqual(result.newEvents, [
|
104
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
99
|
+
expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
|
100
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_0.id)
|
101
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.id)
|
102
|
+
expectEventArraysEqual(result.newEvents, [e1_1_e2_0, e2_0_e3_0])
|
103
|
+
expectEventArraysEqual(result.rollbackEvents, [e1_1, e2_0])
|
105
104
|
})
|
106
105
|
|
107
106
|
it('should work for empty pending', () => {
|
108
107
|
const syncState = new SyncState.SyncState({
|
109
108
|
pending: [],
|
110
109
|
upstreamHead: EventId.ROOT,
|
111
|
-
localHead:
|
110
|
+
localHead: e1_0.id,
|
112
111
|
})
|
113
112
|
const result = merge({
|
114
113
|
syncState,
|
115
|
-
payload: SyncState.PayloadUpstreamRebase.make({ rollbackEvents: [
|
114
|
+
payload: SyncState.PayloadUpstreamRebase.make({ rollbackEvents: [e1_0], newEvents: [e2_0] }),
|
116
115
|
})
|
117
116
|
expectRebase(result)
|
118
117
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
119
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
120
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
121
|
-
expect(result.newEvents).toStrictEqual([
|
118
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
119
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0.id)
|
120
|
+
expect(result.newEvents).toStrictEqual([e2_0])
|
122
121
|
})
|
123
122
|
})
|
124
123
|
|
125
124
|
describe('upstream-advance: advance', () => {
|
126
125
|
it('should throw error if newEvents are not sorted in ascending order by eventId (client)', () => {
|
127
126
|
const syncState = new SyncState.SyncState({
|
128
|
-
pending: [
|
127
|
+
pending: [e1_0],
|
129
128
|
upstreamHead: EventId.ROOT,
|
130
|
-
localHead:
|
129
|
+
localHead: e1_0.id,
|
131
130
|
})
|
132
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
131
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_0] } })
|
133
132
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
134
133
|
})
|
135
134
|
|
136
135
|
it('should throw error if newEvents are not sorted in ascending order by eventId (global)', () => {
|
137
136
|
const syncState = new SyncState.SyncState({
|
138
|
-
pending: [
|
137
|
+
pending: [e1_0],
|
139
138
|
upstreamHead: EventId.ROOT,
|
140
|
-
localHead:
|
139
|
+
localHead: e1_0.id,
|
141
140
|
})
|
142
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
141
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0, e1_0] } })
|
143
142
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
144
143
|
})
|
145
144
|
|
146
145
|
it('should throw error if incoming event is < expected upstream head', () => {
|
147
146
|
const syncState = new SyncState.SyncState({
|
148
147
|
pending: [],
|
149
|
-
upstreamHead:
|
150
|
-
localHead:
|
148
|
+
upstreamHead: e2_0.id,
|
149
|
+
localHead: e2_0.id,
|
151
150
|
})
|
152
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
151
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
153
152
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
154
153
|
})
|
155
154
|
|
156
155
|
it('should throw error if incoming event is = expected upstream head', () => {
|
157
156
|
const syncState = new SyncState.SyncState({
|
158
157
|
pending: [],
|
159
|
-
upstreamHead:
|
160
|
-
localHead:
|
158
|
+
upstreamHead: e2_0.id,
|
159
|
+
localHead: e2_0.id,
|
161
160
|
})
|
162
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
163
|
-
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
164
|
-
})
|
165
|
-
|
166
|
-
it('should throw if the parent id of the first incoming event is unknown', () => {
|
167
|
-
const syncState = new SyncState.SyncState({
|
168
|
-
pending: [],
|
169
|
-
upstreamHead: EventId.ROOT,
|
170
|
-
localHead: e_1_0.id,
|
171
|
-
})
|
172
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_3_0] } })
|
161
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0] } })
|
173
162
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
174
163
|
})
|
175
164
|
|
176
165
|
it('should confirm pending event when receiving matching event', () => {
|
177
166
|
const syncState = new SyncState.SyncState({
|
178
|
-
pending: [
|
167
|
+
pending: [e1_0],
|
179
168
|
upstreamHead: EventId.ROOT,
|
180
|
-
localHead:
|
169
|
+
localHead: e1_0.id,
|
181
170
|
})
|
182
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
171
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
183
172
|
|
184
173
|
expectAdvance(result)
|
185
174
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
186
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
187
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
175
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
176
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0.id)
|
188
177
|
expectEventArraysEqual(result.newEvents, [])
|
189
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
178
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
190
179
|
})
|
191
180
|
|
192
181
|
it('should confirm partial pending event when receiving matching event', () => {
|
193
182
|
const syncState = new SyncState.SyncState({
|
194
|
-
pending: [
|
183
|
+
pending: [e1_0, e2_0],
|
195
184
|
upstreamHead: EventId.ROOT,
|
196
|
-
localHead:
|
185
|
+
localHead: e2_0.id,
|
197
186
|
})
|
198
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
187
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
199
188
|
|
200
189
|
expectAdvance(result)
|
201
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
202
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
203
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
190
|
+
expectEventArraysEqual(result.newSyncState.pending, [e2_0])
|
191
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
192
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0.id)
|
204
193
|
expectEventArraysEqual(result.newEvents, [])
|
205
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
194
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
206
195
|
})
|
207
196
|
|
208
197
|
it('should confirm pending event and add new event', () => {
|
209
198
|
const syncState = new SyncState.SyncState({
|
210
|
-
pending: [
|
199
|
+
pending: [e1_0],
|
211
200
|
upstreamHead: EventId.ROOT,
|
212
|
-
localHead:
|
201
|
+
localHead: e1_0.id,
|
213
202
|
})
|
214
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
203
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0, e1_1] } })
|
215
204
|
|
216
205
|
expectAdvance(result)
|
217
206
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
218
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
219
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
220
|
-
expect(result.newEvents).toStrictEqual([
|
221
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
207
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.id)
|
208
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_1.id)
|
209
|
+
expect(result.newEvents).toStrictEqual([e1_1])
|
210
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
222
211
|
})
|
223
212
|
|
224
213
|
it('should confirm pending event and add multiple new events', () => {
|
225
214
|
const syncState = new SyncState.SyncState({
|
226
|
-
pending: [
|
227
|
-
upstreamHead:
|
228
|
-
localHead:
|
215
|
+
pending: [e1_1],
|
216
|
+
upstreamHead: e1_0.id,
|
217
|
+
localHead: e1_1.id,
|
229
218
|
})
|
230
219
|
const result = merge({
|
231
220
|
syncState,
|
232
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
221
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_2, e1_3, e2_0, e2_1] },
|
233
222
|
})
|
234
223
|
|
235
224
|
expectAdvance(result)
|
236
225
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
237
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
238
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
239
|
-
expect(result.newEvents).toStrictEqual([
|
240
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
226
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_1.id)
|
227
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_1.id)
|
228
|
+
expect(result.newEvents).toStrictEqual([e1_2, e1_3, e2_0, e2_1])
|
229
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_1])
|
241
230
|
})
|
242
231
|
|
243
232
|
it('should confirm pending global event while keep pending client events', () => {
|
244
233
|
const syncState = new SyncState.SyncState({
|
245
|
-
pending: [
|
234
|
+
pending: [e1_0, e1_1],
|
246
235
|
upstreamHead: EventId.ROOT,
|
247
|
-
localHead:
|
236
|
+
localHead: e1_1.id,
|
248
237
|
})
|
249
238
|
const result = merge({
|
250
239
|
syncState,
|
251
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
240
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
252
241
|
})
|
253
242
|
|
254
243
|
expectAdvance(result)
|
255
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
256
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
257
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
244
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_1])
|
245
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
246
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_1.id)
|
258
247
|
expectEventArraysEqual(result.newEvents, [])
|
259
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
248
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
260
249
|
})
|
261
250
|
|
262
251
|
it('should ignore client events (incoming is subset of pending)', () => {
|
263
252
|
const syncState = new SyncState.SyncState({
|
264
|
-
pending: [
|
253
|
+
pending: [e0_1, e1_0],
|
265
254
|
upstreamHead: EventId.ROOT,
|
266
|
-
localHead:
|
255
|
+
localHead: e1_0.id,
|
267
256
|
})
|
268
257
|
const result = merge({
|
269
258
|
syncState,
|
270
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
259
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
271
260
|
ignoreClientEvents: true,
|
272
261
|
})
|
273
262
|
expectAdvance(result)
|
274
263
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
275
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
276
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
264
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
265
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0.id)
|
277
266
|
expectEventArraysEqual(result.newEvents, [])
|
278
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
267
|
+
expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
|
279
268
|
})
|
280
269
|
|
281
270
|
it('should ignore client events (incoming is subset of pending case 2)', () => {
|
282
271
|
const syncState = new SyncState.SyncState({
|
283
|
-
pending: [
|
272
|
+
pending: [e0_1, e1_0, e2_0],
|
284
273
|
upstreamHead: EventId.ROOT,
|
285
|
-
localHead:
|
274
|
+
localHead: e1_0.id,
|
286
275
|
})
|
287
276
|
const result = merge({
|
288
277
|
syncState,
|
289
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
278
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
290
279
|
ignoreClientEvents: true,
|
291
280
|
})
|
292
281
|
expectAdvance(result)
|
293
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
294
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
295
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
282
|
+
expectEventArraysEqual(result.newSyncState.pending, [e2_0])
|
283
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
284
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0.id)
|
296
285
|
expectEventArraysEqual(result.newEvents, [])
|
297
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
286
|
+
expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
|
298
287
|
})
|
299
288
|
|
300
289
|
it('should ignore client events (incoming goes beyond pending)', () => {
|
301
290
|
const syncState = new SyncState.SyncState({
|
302
|
-
pending: [
|
291
|
+
pending: [e0_1, e1_0, e1_1],
|
303
292
|
upstreamHead: EventId.ROOT,
|
304
|
-
localHead:
|
293
|
+
localHead: e1_1.id,
|
305
294
|
})
|
306
295
|
const result = merge({
|
307
296
|
syncState,
|
308
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
297
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0, e2_0] },
|
309
298
|
ignoreClientEvents: true,
|
310
299
|
})
|
311
300
|
|
312
301
|
expectAdvance(result)
|
313
302
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
314
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
315
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
316
|
-
expect(result.newEvents).toStrictEqual([
|
317
|
-
expectEventArraysEqual(result.confirmedEvents, [
|
303
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
304
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0.id)
|
305
|
+
expect(result.newEvents).toStrictEqual([e2_0])
|
306
|
+
expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0, e1_1])
|
318
307
|
})
|
319
308
|
|
320
309
|
it('should fail if incoming event is ≤ local head', () => {
|
321
310
|
const syncState = new SyncState.SyncState({
|
322
311
|
pending: [],
|
323
|
-
upstreamHead:
|
324
|
-
localHead:
|
312
|
+
upstreamHead: e2_0.id,
|
313
|
+
localHead: e2_0.id,
|
325
314
|
})
|
326
|
-
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [
|
315
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
327
316
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
328
317
|
})
|
329
318
|
})
|
@@ -331,120 +320,120 @@ describe('syncstate', () => {
|
|
331
320
|
describe('upstream-advance: rebase', () => {
|
332
321
|
it('should rebase single client event to end', () => {
|
333
322
|
const syncState = new SyncState.SyncState({
|
334
|
-
pending: [
|
323
|
+
pending: [e1_0],
|
335
324
|
upstreamHead: EventId.ROOT,
|
336
|
-
localHead:
|
325
|
+
localHead: e1_0.id,
|
337
326
|
})
|
338
|
-
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [
|
327
|
+
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }) })
|
339
328
|
|
340
|
-
const
|
329
|
+
const e1_0_e1_2 = e1_0.rebase_(e1_1.id)
|
341
330
|
|
342
331
|
expectRebase(result)
|
343
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
344
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
345
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
346
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
347
|
-
expectEventArraysEqual(result.newEvents, [
|
332
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_0_e1_2])
|
333
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.id)
|
334
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0_e1_2.id)
|
335
|
+
expectEventArraysEqual(result.rollbackEvents, [e1_0])
|
336
|
+
expectEventArraysEqual(result.newEvents, [e1_1, e1_0_e1_2])
|
348
337
|
})
|
349
338
|
|
350
339
|
it('should rebase different event with same id', () => {
|
351
|
-
const
|
340
|
+
const e2_0_b = new TestEvent({ global: 1, client: 0 }, e1_0.id, '1_0_b', false)
|
352
341
|
const syncState = new SyncState.SyncState({
|
353
|
-
pending: [
|
342
|
+
pending: [e2_0_b],
|
354
343
|
upstreamHead: EventId.ROOT,
|
355
|
-
localHead:
|
344
|
+
localHead: e2_0_b.id,
|
356
345
|
})
|
357
|
-
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [
|
358
|
-
const
|
346
|
+
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e2_0] }) })
|
347
|
+
const e2_0_e3_0 = e2_0_b.rebase_(e2_0.id)
|
359
348
|
|
360
349
|
expectRebase(result)
|
361
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
362
|
-
expectEventArraysEqual(result.newEvents, [
|
363
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
364
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
365
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
350
|
+
expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
|
351
|
+
expectEventArraysEqual(result.newEvents, [e2_0, e2_0_e3_0])
|
352
|
+
expectEventArraysEqual(result.rollbackEvents, [e2_0_b])
|
353
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
354
|
+
expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.id)
|
366
355
|
})
|
367
356
|
|
368
357
|
it('should rebase single client event to end (more incoming events)', () => {
|
369
358
|
const syncState = new SyncState.SyncState({
|
370
|
-
pending: [
|
359
|
+
pending: [e1_0],
|
371
360
|
upstreamHead: EventId.ROOT,
|
372
|
-
localHead:
|
361
|
+
localHead: e1_0.id,
|
373
362
|
})
|
374
363
|
const result = merge({
|
375
364
|
syncState,
|
376
|
-
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [
|
365
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
|
377
366
|
})
|
378
367
|
|
379
|
-
const
|
368
|
+
const e1_0_e3_0 = e1_0.rebase_(e2_0.id)
|
380
369
|
|
381
370
|
expectRebase(result)
|
382
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
383
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
384
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
371
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_0_e3_0])
|
372
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
373
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0_e3_0.id)
|
385
374
|
})
|
386
375
|
|
387
376
|
it('should only rebase divergent events when first event matches', () => {
|
388
377
|
const syncState = new SyncState.SyncState({
|
389
|
-
pending: [
|
378
|
+
pending: [e1_0, e1_1],
|
390
379
|
upstreamHead: EventId.ROOT,
|
391
|
-
localHead:
|
380
|
+
localHead: e1_0.id,
|
392
381
|
})
|
393
382
|
const result = merge({
|
394
383
|
syncState,
|
395
|
-
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [
|
384
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_0, e1_2, e1_3, e2_0] }),
|
396
385
|
})
|
397
386
|
|
398
|
-
const
|
387
|
+
const e1_1_e2_1 = e1_1.rebase_(e2_0.id)
|
399
388
|
|
400
389
|
expectRebase(result)
|
401
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
402
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
403
|
-
expectEventArraysEqual(result.newEvents, [
|
404
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
405
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
390
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_1_e2_1])
|
391
|
+
expectEventArraysEqual(result.rollbackEvents, [e1_1])
|
392
|
+
expectEventArraysEqual(result.newEvents, [e1_2, e1_3, e2_0, e1_1_e2_1])
|
393
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
394
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_1.id)
|
406
395
|
})
|
407
396
|
|
408
397
|
it('should rebase all client events when incoming chain starts differently', () => {
|
409
398
|
const syncState = new SyncState.SyncState({
|
410
|
-
pending: [
|
399
|
+
pending: [e1_0, e1_1],
|
411
400
|
upstreamHead: EventId.ROOT,
|
412
|
-
localHead:
|
401
|
+
localHead: e1_1.id,
|
413
402
|
})
|
414
403
|
const result = merge({
|
415
404
|
syncState,
|
416
|
-
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [
|
405
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
|
417
406
|
})
|
418
407
|
|
419
|
-
const
|
420
|
-
const
|
408
|
+
const e1_0_e2_1 = e1_0.rebase_(e2_0.id)
|
409
|
+
const e1_1_e2_2 = e1_1.rebase_(e1_0_e2_1.id)
|
421
410
|
|
422
411
|
expectRebase(result)
|
423
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
424
|
-
expectEventArraysEqual(result.newEvents, [
|
425
|
-
expectEventArraysEqual(result.rollbackEvents, [
|
426
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(
|
427
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
412
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_0_e2_1, e1_1_e2_2])
|
413
|
+
expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3, e2_0, e1_0_e2_1, e1_1_e2_2])
|
414
|
+
expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1])
|
415
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.id)
|
416
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_2.id)
|
428
417
|
})
|
429
418
|
|
430
419
|
describe('local-push', () => {
|
431
420
|
describe('advance', () => {
|
432
421
|
it('should advance with new events', () => {
|
433
422
|
const syncState = new SyncState.SyncState({
|
434
|
-
pending: [
|
423
|
+
pending: [e1_0],
|
435
424
|
upstreamHead: EventId.ROOT,
|
436
|
-
localHead:
|
425
|
+
localHead: e1_0.id,
|
437
426
|
})
|
438
427
|
const result = merge({
|
439
428
|
syncState,
|
440
|
-
payload: SyncState.PayloadLocalPush.make({ newEvents: [
|
429
|
+
payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2, e1_3] }),
|
441
430
|
})
|
442
431
|
|
443
432
|
expectAdvance(result)
|
444
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
433
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_0, e1_1, e1_2, e1_3])
|
445
434
|
expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
|
446
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
447
|
-
expectEventArraysEqual(result.newEvents, [
|
435
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_3.id)
|
436
|
+
expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3])
|
448
437
|
expectEventArraysEqual(result.confirmedEvents, [])
|
449
438
|
})
|
450
439
|
})
|
@@ -452,17 +441,17 @@ describe('syncstate', () => {
|
|
452
441
|
describe('reject', () => {
|
453
442
|
it('should reject when new events are greater than pending events', () => {
|
454
443
|
const syncState = new SyncState.SyncState({
|
455
|
-
pending: [
|
444
|
+
pending: [e1_0, e1_1],
|
456
445
|
upstreamHead: EventId.ROOT,
|
457
|
-
localHead:
|
446
|
+
localHead: e1_1.id,
|
458
447
|
})
|
459
448
|
const result = merge({
|
460
449
|
syncState,
|
461
|
-
payload: SyncState.PayloadLocalPush.make({ newEvents: [
|
450
|
+
payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2] }),
|
462
451
|
})
|
463
452
|
|
464
453
|
expectReject(result)
|
465
|
-
expect(result.expectedMinimumId).toMatchObject(
|
454
|
+
expect(result.expectedMinimumId).toMatchObject(e1_2.id)
|
466
455
|
})
|
467
456
|
})
|
468
457
|
})
|