@livestore/common 0.3.0-dev.8 → 0.3.0-dev.9
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.d.ts +39 -39
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +16 -26
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +146 -157
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/apply-mutation.js +1 -1
- package/dist/leader-thread/apply-mutation.js.map +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
- package/dist/leader-thread/types.d.ts +9 -3
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/schema/MutationEvent.d.ts +6 -5
- package/dist/schema/MutationEvent.d.ts.map +1 -1
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +5 -3
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/syncstate.d.ts +39 -17
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +56 -12
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +110 -51
- 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 +3 -3
- package/src/leader-thread/LeaderSyncProcessor.ts +196 -205
- package/src/leader-thread/apply-mutation.ts +1 -1
- package/src/leader-thread/types.ts +10 -2
- package/src/schema/MutationEvent.ts +5 -1
- package/src/sync/ClientSessionSyncProcessor.ts +6 -4
- package/src/sync/syncstate.test.ts +110 -51
- package/src/sync/syncstate.ts +21 -19
- package/src/version.ts +1 -1
@@ -37,7 +37,6 @@ const e_0_2 = new TestEvent({ global: 0, local: 2 }, e_0_1.id, 'a', true)
|
|
37
37
|
const e_0_3 = new TestEvent({ global: 0, local: 3 }, e_0_2.id, 'a', true)
|
38
38
|
const e_1_0 = new TestEvent({ global: 1, local: 0 }, e_0_0.id, 'a', false)
|
39
39
|
const e_1_1 = new TestEvent({ global: 1, local: 1 }, e_1_0.id, 'a', true)
|
40
|
-
const e_2_0 = new TestEvent({ global: 2, local: 0 }, e_1_0.id, 'a', false)
|
41
40
|
|
42
41
|
const isEqualEvent = MutationEvent.isEqualEncoded
|
43
42
|
|
@@ -59,12 +58,12 @@ describe('syncstate', () => {
|
|
59
58
|
'upstream-rebase (trimRollbackUntil: $trimRollbackUntil)',
|
60
59
|
({ trimRollbackUntil }) => {
|
61
60
|
it('should rollback until start', () => {
|
62
|
-
const syncState = {
|
61
|
+
const syncState = new SyncState.SyncState({
|
63
62
|
pending: [e_1_0],
|
64
63
|
rollbackTail: [e_0_0, e_0_1],
|
65
64
|
upstreamHead: EventId.ROOT,
|
66
65
|
localHead: e_1_0.id,
|
67
|
-
}
|
66
|
+
})
|
68
67
|
const e_0_0_e_1_0 = e_0_0.rebase_(e_1_0.id)
|
69
68
|
const e_0_1_e_1_1 = e_0_1.rebase_(e_0_0_e_1_0.id)
|
70
69
|
const result = run({
|
@@ -84,19 +83,19 @@ describe('syncstate', () => {
|
|
84
83
|
} else {
|
85
84
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0_e_1_0, e_0_1_e_1_1])
|
86
85
|
}
|
87
|
-
expect(result.newSyncState.upstreamHead).
|
86
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1_e_1_1.id)
|
88
87
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
89
88
|
expectEventArraysEqual(result.newEvents, [e_0_0_e_1_0, e_0_1_e_1_1])
|
90
89
|
expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1, e_1_0])
|
91
90
|
})
|
92
91
|
|
93
92
|
it('should rollback only to specified point', () => {
|
94
|
-
const syncState = {
|
93
|
+
const syncState = new SyncState.SyncState({
|
95
94
|
pending: [e_1_0],
|
96
95
|
rollbackTail: [e_0_0, e_0_1],
|
97
96
|
upstreamHead: EventId.ROOT,
|
98
97
|
localHead: e_1_0.id,
|
99
|
-
}
|
98
|
+
})
|
100
99
|
const e_0_1_e_1_0 = e_0_1.rebase_(e_0_0.id)
|
101
100
|
const result = run({
|
102
101
|
syncState,
|
@@ -115,14 +114,19 @@ describe('syncstate', () => {
|
|
115
114
|
} else {
|
116
115
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1_e_1_0])
|
117
116
|
}
|
118
|
-
expect(result.newSyncState.upstreamHead).
|
117
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1_e_1_0.id)
|
119
118
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
120
119
|
expectEventArraysEqual(result.newEvents, [e_0_1_e_1_0])
|
121
120
|
expectEventArraysEqual(result.eventsToRollback, [e_0_1, e_1_0])
|
122
121
|
})
|
123
122
|
|
124
123
|
it('should work for empty pending', () => {
|
125
|
-
const syncState =
|
124
|
+
const syncState = new SyncState.SyncState({
|
125
|
+
pending: [],
|
126
|
+
rollbackTail: [e_0_0],
|
127
|
+
upstreamHead: EventId.ROOT,
|
128
|
+
localHead: e_0_0.id,
|
129
|
+
})
|
126
130
|
const result = run({
|
127
131
|
syncState,
|
128
132
|
payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [e_1_0] },
|
@@ -130,13 +134,18 @@ describe('syncstate', () => {
|
|
130
134
|
expectRebase(result)
|
131
135
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
132
136
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_1_0])
|
133
|
-
expect(result.newSyncState.upstreamHead).
|
137
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
134
138
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
|
135
139
|
expect(result.newEvents).toStrictEqual([e_1_0])
|
136
140
|
})
|
137
141
|
|
138
142
|
it('should fail for empty rollback tail', () => {
|
139
|
-
const syncState =
|
143
|
+
const syncState = new SyncState.SyncState({
|
144
|
+
pending: [],
|
145
|
+
rollbackTail: [],
|
146
|
+
upstreamHead: EventId.ROOT,
|
147
|
+
localHead: e_0_0.id,
|
148
|
+
})
|
140
149
|
expect(() =>
|
141
150
|
run({
|
142
151
|
syncState,
|
@@ -146,7 +155,12 @@ describe('syncstate', () => {
|
|
146
155
|
})
|
147
156
|
|
148
157
|
it('should work for empty incoming', () => {
|
149
|
-
const syncState =
|
158
|
+
const syncState = new SyncState.SyncState({
|
159
|
+
pending: [],
|
160
|
+
rollbackTail: [e_0_0],
|
161
|
+
upstreamHead: EventId.ROOT,
|
162
|
+
localHead: e_0_0.id,
|
163
|
+
})
|
150
164
|
const result = run({
|
151
165
|
syncState,
|
152
166
|
payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [] },
|
@@ -154,7 +168,7 @@ describe('syncstate', () => {
|
|
154
168
|
expectRebase(result)
|
155
169
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
156
170
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [])
|
157
|
-
expect(result.newSyncState.upstreamHead).
|
171
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
|
158
172
|
expect(result.newSyncState.localHead).toMatchObject(EventId.ROOT)
|
159
173
|
expect(result.newEvents).toStrictEqual([])
|
160
174
|
})
|
@@ -163,58 +177,83 @@ describe('syncstate', () => {
|
|
163
177
|
|
164
178
|
describe('upstream-advance: advance', () => {
|
165
179
|
it('should throw error if newEvents are not sorted in ascending order by eventId (local)', () => {
|
166
|
-
const syncState =
|
180
|
+
const syncState = new SyncState.SyncState({
|
181
|
+
pending: [e_0_0],
|
182
|
+
rollbackTail: [],
|
183
|
+
upstreamHead: EventId.ROOT,
|
184
|
+
localHead: e_0_0.id,
|
185
|
+
})
|
167
186
|
expect(() => run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_0] } })).toThrow()
|
168
187
|
})
|
169
188
|
|
170
189
|
it('should throw error if newEvents are not sorted in ascending order by eventId (global)', () => {
|
171
|
-
const syncState =
|
190
|
+
const syncState = new SyncState.SyncState({
|
191
|
+
pending: [e_0_0],
|
192
|
+
rollbackTail: [],
|
193
|
+
upstreamHead: EventId.ROOT,
|
194
|
+
localHead: e_0_0.id,
|
195
|
+
})
|
172
196
|
expect(() => run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_1_0, e_0_0] } })).toThrow()
|
173
197
|
})
|
174
198
|
|
175
199
|
it('should acknowledge pending event when receiving matching event', () => {
|
176
|
-
const syncState =
|
200
|
+
const syncState = new SyncState.SyncState({
|
201
|
+
pending: [e_0_0],
|
202
|
+
rollbackTail: [],
|
203
|
+
upstreamHead: EventId.ROOT,
|
204
|
+
localHead: e_0_0.id,
|
205
|
+
})
|
177
206
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
|
178
207
|
|
179
208
|
expectAdvance(result)
|
180
209
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
181
210
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
|
182
|
-
expect(result.newSyncState.upstreamHead).
|
211
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
|
183
212
|
expect(result.newSyncState.localHead).toMatchObject(e_0_0.id)
|
184
213
|
expect(result.newEvents).toStrictEqual([])
|
185
214
|
})
|
186
215
|
|
187
216
|
it('should acknowledge partial pending event when receiving matching event', () => {
|
188
|
-
const syncState = {
|
217
|
+
const syncState = new SyncState.SyncState({
|
189
218
|
pending: [e_0_0, e_1_0],
|
190
219
|
rollbackTail: [],
|
191
220
|
upstreamHead: EventId.ROOT,
|
192
221
|
localHead: e_1_0.id,
|
193
|
-
}
|
222
|
+
})
|
194
223
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
|
195
224
|
|
196
225
|
expectAdvance(result)
|
197
226
|
expectEventArraysEqual(result.newSyncState.pending, [e_1_0])
|
198
227
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
|
199
|
-
expect(result.newSyncState.upstreamHead).
|
228
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
|
200
229
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
|
201
230
|
expect(result.newEvents).toStrictEqual([])
|
202
231
|
})
|
203
232
|
|
204
233
|
it('should acknowledge pending event and add new event', () => {
|
205
|
-
const syncState =
|
234
|
+
const syncState = new SyncState.SyncState({
|
235
|
+
pending: [e_0_0],
|
236
|
+
rollbackTail: [],
|
237
|
+
upstreamHead: EventId.ROOT,
|
238
|
+
localHead: e_0_0.id,
|
239
|
+
})
|
206
240
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_0_1] } })
|
207
241
|
|
208
242
|
expectAdvance(result)
|
209
243
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
210
244
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1])
|
211
|
-
expect(result.newSyncState.upstreamHead).
|
245
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1.id)
|
212
246
|
expect(result.newSyncState.localHead).toMatchObject(e_0_1.id)
|
213
247
|
expect(result.newEvents).toStrictEqual([e_0_1])
|
214
248
|
})
|
215
249
|
|
216
250
|
it('should acknowledge pending event and add multiple new events', () => {
|
217
|
-
const syncState =
|
251
|
+
const syncState = new SyncState.SyncState({
|
252
|
+
pending: [e_0_1],
|
253
|
+
rollbackTail: [],
|
254
|
+
upstreamHead: e_0_0.id,
|
255
|
+
localHead: e_0_1.id,
|
256
|
+
})
|
218
257
|
const result = run({
|
219
258
|
syncState,
|
220
259
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0, e_1_1] },
|
@@ -223,18 +262,18 @@ describe('syncstate', () => {
|
|
223
262
|
expectAdvance(result)
|
224
263
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
225
264
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0, e_1_1])
|
226
|
-
expect(result.newSyncState.upstreamHead).
|
265
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_1.id)
|
227
266
|
expect(result.newSyncState.localHead).toMatchObject(e_1_1.id)
|
228
267
|
expect(result.newEvents).toStrictEqual([e_0_2, e_0_3, e_1_0, e_1_1])
|
229
268
|
})
|
230
269
|
|
231
270
|
it('should ignore local events (incoming is subset of pending)', () => {
|
232
|
-
const syncState = {
|
271
|
+
const syncState = new SyncState.SyncState({
|
233
272
|
pending: [e_r_1, e_0_0],
|
234
273
|
rollbackTail: [],
|
235
274
|
upstreamHead: EventId.ROOT,
|
236
275
|
localHead: e_0_0.id,
|
237
|
-
}
|
276
|
+
})
|
238
277
|
const result = run({
|
239
278
|
syncState,
|
240
279
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_0] },
|
@@ -243,18 +282,18 @@ describe('syncstate', () => {
|
|
243
282
|
expectAdvance(result)
|
244
283
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
245
284
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0])
|
246
|
-
expect(result.newSyncState.upstreamHead).
|
285
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
|
247
286
|
expect(result.newSyncState.localHead).toMatchObject(e_0_0.id)
|
248
287
|
expect(result.newEvents).toStrictEqual([])
|
249
288
|
})
|
250
289
|
|
251
290
|
it('should ignore local events (incoming is subset of pending case 2)', () => {
|
252
|
-
const syncState = {
|
291
|
+
const syncState = new SyncState.SyncState({
|
253
292
|
pending: [e_r_1, e_0_0, e_1_0],
|
254
293
|
rollbackTail: [],
|
255
294
|
upstreamHead: EventId.ROOT,
|
256
295
|
localHead: e_0_0.id,
|
257
|
-
}
|
296
|
+
})
|
258
297
|
const result = run({
|
259
298
|
syncState,
|
260
299
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_0] },
|
@@ -263,18 +302,18 @@ describe('syncstate', () => {
|
|
263
302
|
expectAdvance(result)
|
264
303
|
expectEventArraysEqual(result.newSyncState.pending, [e_1_0])
|
265
304
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0])
|
266
|
-
expect(result.newSyncState.upstreamHead).
|
305
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
|
267
306
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
|
268
307
|
expect(result.newEvents).toStrictEqual([])
|
269
308
|
})
|
270
309
|
|
271
310
|
it('should ignore local events (incoming goes beyond pending)', () => {
|
272
|
-
const syncState = {
|
311
|
+
const syncState = new SyncState.SyncState({
|
273
312
|
pending: [e_r_1, e_0_0, e_0_1],
|
274
313
|
rollbackTail: [],
|
275
314
|
upstreamHead: EventId.ROOT,
|
276
315
|
localHead: e_0_1.id,
|
277
|
-
}
|
316
|
+
})
|
278
317
|
const result = run({
|
279
318
|
syncState,
|
280
319
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_1_0] },
|
@@ -284,7 +323,7 @@ describe('syncstate', () => {
|
|
284
323
|
expectAdvance(result)
|
285
324
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
286
325
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0, e_0_1, e_1_0])
|
287
|
-
expect(result.newSyncState.upstreamHead).
|
326
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
288
327
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
|
289
328
|
expect(result.newEvents).toStrictEqual([e_1_0])
|
290
329
|
})
|
@@ -292,7 +331,12 @@ describe('syncstate', () => {
|
|
292
331
|
|
293
332
|
describe('upstream-advance: rebase', () => {
|
294
333
|
it('should rebase single local event to end', () => {
|
295
|
-
const syncState =
|
334
|
+
const syncState = new SyncState.SyncState({
|
335
|
+
pending: [e_0_0],
|
336
|
+
rollbackTail: [],
|
337
|
+
upstreamHead: EventId.ROOT,
|
338
|
+
localHead: e_0_0.id,
|
339
|
+
})
|
296
340
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_1] } })
|
297
341
|
|
298
342
|
const e_0_0_e_0_2 = e_0_0.rebase_(e_0_1.id)
|
@@ -300,7 +344,7 @@ describe('syncstate', () => {
|
|
300
344
|
expectRebase(result)
|
301
345
|
expectEventArraysEqual(result.newSyncState.pending, [e_0_0_e_0_2])
|
302
346
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1])
|
303
|
-
expect(result.newSyncState.upstreamHead).
|
347
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1.id)
|
304
348
|
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_0_2.id)
|
305
349
|
expectEventArraysEqual(result.eventsToRollback, [e_0_0])
|
306
350
|
expectEventArraysEqual(result.newEvents, [e_0_1, e_0_0_e_0_2])
|
@@ -308,7 +352,12 @@ describe('syncstate', () => {
|
|
308
352
|
|
309
353
|
it('should rebase different event with same id (no rollback tail)', () => {
|
310
354
|
const e_0_0_b = new TestEvent({ global: 0, local: 0 }, EventId.ROOT, '0_0_b', true)
|
311
|
-
const syncState =
|
355
|
+
const syncState = new SyncState.SyncState({
|
356
|
+
pending: [e_0_0_b],
|
357
|
+
rollbackTail: [],
|
358
|
+
upstreamHead: EventId.ROOT,
|
359
|
+
localHead: e_0_0_b.id,
|
360
|
+
})
|
312
361
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
|
313
362
|
|
314
363
|
const e_0_0_e_1_0 = e_0_0_b.rebase_(e_0_0.id)
|
@@ -318,18 +367,18 @@ describe('syncstate', () => {
|
|
318
367
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
|
319
368
|
expectEventArraysEqual(result.newEvents, [e_0_0, e_0_0_e_1_0])
|
320
369
|
expectEventArraysEqual(result.eventsToRollback, [e_0_0_b])
|
321
|
-
expect(result.newSyncState.upstreamHead).
|
370
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
|
322
371
|
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_1_0.id)
|
323
372
|
})
|
324
373
|
|
325
374
|
it('should rebase different event with same id', () => {
|
326
375
|
const e_1_0_b = new TestEvent({ global: 1, local: 0 }, e_0_0.id, '1_0_b', false)
|
327
|
-
const syncState = {
|
376
|
+
const syncState = new SyncState.SyncState({
|
328
377
|
pending: [e_1_0_b],
|
329
378
|
rollbackTail: [e_0_0, e_0_1],
|
330
379
|
upstreamHead: EventId.ROOT,
|
331
380
|
localHead: e_1_0_b.id,
|
332
|
-
}
|
381
|
+
})
|
333
382
|
const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_1_0] } })
|
334
383
|
const e_1_0_e_2_0 = e_1_0_b.rebase_(e_1_0.id)
|
335
384
|
|
@@ -338,12 +387,17 @@ describe('syncstate', () => {
|
|
338
387
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1, e_1_0])
|
339
388
|
expectEventArraysEqual(result.newEvents, [e_1_0, e_1_0_e_2_0])
|
340
389
|
expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1, e_1_0_b])
|
341
|
-
expect(result.newSyncState.upstreamHead).
|
390
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
342
391
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
343
392
|
})
|
344
393
|
|
345
394
|
it('should rebase single local event to end (more incoming events)', () => {
|
346
|
-
const syncState =
|
395
|
+
const syncState = new SyncState.SyncState({
|
396
|
+
pending: [e_0_0],
|
397
|
+
rollbackTail: [],
|
398
|
+
upstreamHead: EventId.ROOT,
|
399
|
+
localHead: e_0_0.id,
|
400
|
+
})
|
347
401
|
const result = run({
|
348
402
|
syncState,
|
349
403
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0] },
|
@@ -354,17 +408,17 @@ describe('syncstate', () => {
|
|
354
408
|
expectRebase(result)
|
355
409
|
expectEventArraysEqual(result.newSyncState.pending, [e_0_0_e_2_0])
|
356
410
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0])
|
357
|
-
expect(result.newSyncState.upstreamHead).
|
411
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
358
412
|
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_2_0.id)
|
359
413
|
})
|
360
414
|
|
361
415
|
it('should only rebase divergent events when first event matches', () => {
|
362
|
-
const syncState = {
|
416
|
+
const syncState = new SyncState.SyncState({
|
363
417
|
pending: [e_0_0, e_0_1],
|
364
418
|
rollbackTail: [],
|
365
419
|
upstreamHead: EventId.ROOT,
|
366
420
|
localHead: e_0_0.id,
|
367
|
-
}
|
421
|
+
})
|
368
422
|
const result = run({
|
369
423
|
syncState,
|
370
424
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_0_2, e_0_3, e_1_0] },
|
@@ -377,17 +431,17 @@ describe('syncstate', () => {
|
|
377
431
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_2, e_0_3, e_1_0])
|
378
432
|
expectEventArraysEqual(result.eventsToRollback, [e_0_1])
|
379
433
|
expectEventArraysEqual(result.newEvents, [e_0_2, e_0_3, e_1_0, e_0_1_e_1_1])
|
380
|
-
expect(result.newSyncState.upstreamHead).
|
434
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
381
435
|
expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_1.id)
|
382
436
|
})
|
383
437
|
|
384
438
|
it('should rebase all local events when incoming chain starts differently', () => {
|
385
|
-
const syncState = {
|
439
|
+
const syncState = new SyncState.SyncState({
|
386
440
|
pending: [e_0_0, e_0_1],
|
387
441
|
rollbackTail: [],
|
388
442
|
upstreamHead: EventId.ROOT,
|
389
443
|
localHead: e_0_1.id,
|
390
|
-
}
|
444
|
+
})
|
391
445
|
const result = run({
|
392
446
|
syncState,
|
393
447
|
payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0] },
|
@@ -401,20 +455,25 @@ describe('syncstate', () => {
|
|
401
455
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0])
|
402
456
|
expectEventArraysEqual(result.newEvents, [e_0_1, e_0_2, e_0_3, e_1_0, e_0_0_e_1_1, e_0_1_e_1_2])
|
403
457
|
expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1])
|
404
|
-
expect(result.newSyncState.upstreamHead).
|
458
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
405
459
|
expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_2.id)
|
406
460
|
})
|
407
461
|
|
408
462
|
describe('local-push', () => {
|
409
463
|
describe('advance', () => {
|
410
464
|
it('should advance with new events', () => {
|
411
|
-
const syncState =
|
465
|
+
const syncState = new SyncState.SyncState({
|
466
|
+
pending: [e_0_0],
|
467
|
+
rollbackTail: [],
|
468
|
+
upstreamHead: EventId.ROOT,
|
469
|
+
localHead: e_0_0.id,
|
470
|
+
})
|
412
471
|
const result = run({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2, e_0_3] } })
|
413
472
|
|
414
473
|
expectAdvance(result)
|
415
474
|
expectEventArraysEqual(result.newSyncState.pending, [e_0_0, e_0_1, e_0_2, e_0_3])
|
416
475
|
expectEventArraysEqual(result.newSyncState.rollbackTail, [])
|
417
|
-
expect(result.newSyncState.upstreamHead).
|
476
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
|
418
477
|
expect(result.newSyncState.localHead).toMatchObject(e_0_3.id)
|
419
478
|
expectEventArraysEqual(result.newEvents, [e_0_1, e_0_2, e_0_3])
|
420
479
|
})
|
@@ -422,12 +481,12 @@ describe('syncstate', () => {
|
|
422
481
|
|
423
482
|
describe('reject', () => {
|
424
483
|
it('should reject when new events are greater than pending events', () => {
|
425
|
-
const syncState = {
|
484
|
+
const syncState = new SyncState.SyncState({
|
426
485
|
pending: [e_0_0, e_0_1],
|
427
486
|
rollbackTail: [],
|
428
487
|
upstreamHead: EventId.ROOT,
|
429
488
|
localHead: e_0_1.id,
|
430
|
-
}
|
489
|
+
})
|
431
490
|
const result = run({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2] } })
|
432
491
|
|
433
492
|
expectReject(result)
|
package/src/sync/syncstate.ts
CHANGED
@@ -39,19 +39,21 @@ import * as MutationEvent from '../schema/MutationEvent.js'
|
|
39
39
|
* The `updateSyncState` function processes updates to the sync state based on incoming payloads,
|
40
40
|
* handling cases such as upstream rebase, advance, local push, and rollback tail trimming.
|
41
41
|
*/
|
42
|
-
export
|
43
|
-
pending: ReadonlyArray<MutationEvent.EncodedWithMeta>
|
44
|
-
rollbackTail: ReadonlyArray<MutationEvent.EncodedWithMeta>
|
45
|
-
upstreamHead: EventId.EventId
|
46
|
-
localHead: EventId.EventId
|
47
|
-
}
|
48
|
-
|
49
|
-
export const SyncState = Schema.Struct({
|
42
|
+
export class SyncState extends Schema.Class<SyncState>('SyncState')({
|
50
43
|
pending: Schema.Array(MutationEvent.EncodedWithMeta),
|
51
44
|
rollbackTail: Schema.Array(MutationEvent.EncodedWithMeta),
|
52
45
|
upstreamHead: EventId.EventId,
|
53
46
|
localHead: EventId.EventId,
|
54
|
-
})
|
47
|
+
}) {
|
48
|
+
toJSON = (): any => {
|
49
|
+
return {
|
50
|
+
pending: this.pending.map((e) => e.toJSON()),
|
51
|
+
rollbackTail: this.rollbackTail.map((e) => e.toJSON()),
|
52
|
+
upstreamHead: `(${this.upstreamHead.global},${this.upstreamHead.local})`,
|
53
|
+
localHead: `(${this.localHead.global},${this.localHead.local})`,
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
55
57
|
|
56
58
|
export class PayloadUpstreamRebase extends Schema.TaggedStruct('upstream-rebase', {
|
57
59
|
/** Rollback until this event in the rollback tail (inclusive). Starting from the end of the rollback tail. */
|
@@ -153,12 +155,12 @@ export const updateSyncState = ({
|
|
153
155
|
|
154
156
|
return {
|
155
157
|
_tag: 'rebase',
|
156
|
-
newSyncState: {
|
158
|
+
newSyncState: new SyncState({
|
157
159
|
pending: rebasedPending,
|
158
160
|
rollbackTail: trimRollbackTail([...syncState.rollbackTail.slice(0, rollbackIndex), ...payload.newEvents]),
|
159
161
|
upstreamHead: newUpstreamHead,
|
160
162
|
localHead: rebasedPending.at(-1)?.id ?? newUpstreamHead,
|
161
|
-
},
|
163
|
+
}),
|
162
164
|
previousSyncState: syncState,
|
163
165
|
newEvents: payload.newEvents,
|
164
166
|
eventsToRollback,
|
@@ -169,12 +171,12 @@ export const updateSyncState = ({
|
|
169
171
|
if (payload.newEvents.length === 0) {
|
170
172
|
return {
|
171
173
|
_tag: 'advance',
|
172
|
-
newSyncState: {
|
174
|
+
newSyncState: new SyncState({
|
173
175
|
pending: syncState.pending,
|
174
176
|
rollbackTail: trimRollbackTail(syncState.rollbackTail),
|
175
177
|
upstreamHead: syncState.upstreamHead,
|
176
178
|
localHead: syncState.localHead,
|
177
|
-
},
|
179
|
+
}),
|
178
180
|
previousSyncState: syncState,
|
179
181
|
newEvents: [],
|
180
182
|
}
|
@@ -235,12 +237,12 @@ export const updateSyncState = ({
|
|
235
237
|
|
236
238
|
return {
|
237
239
|
_tag: 'advance',
|
238
|
-
newSyncState: {
|
240
|
+
newSyncState: new SyncState({
|
239
241
|
pending: pendingRemaining,
|
240
242
|
rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...pendingAndNewEvents]),
|
241
243
|
upstreamHead: newUpstreamHead,
|
242
244
|
localHead: pendingRemaining.at(-1)?.id ?? newUpstreamHead,
|
243
|
-
},
|
245
|
+
}),
|
244
246
|
previousSyncState: syncState,
|
245
247
|
newEvents,
|
246
248
|
}
|
@@ -262,12 +264,12 @@ export const updateSyncState = ({
|
|
262
264
|
|
263
265
|
return {
|
264
266
|
_tag: 'rebase',
|
265
|
-
newSyncState: {
|
267
|
+
newSyncState: new SyncState({
|
266
268
|
pending: rebasedPending,
|
267
269
|
rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...payload.newEvents]),
|
268
270
|
upstreamHead: newUpstreamHead,
|
269
271
|
localHead: rebasedPending.at(-1)!.id,
|
270
|
-
},
|
272
|
+
}),
|
271
273
|
previousSyncState: syncState,
|
272
274
|
newEvents: [...payload.newEvents.slice(divergentNewEventsIndex), ...rebasedPending],
|
273
275
|
eventsToRollback: [...syncState.rollbackTail, ...divergentPending],
|
@@ -289,12 +291,12 @@ export const updateSyncState = ({
|
|
289
291
|
} else {
|
290
292
|
return {
|
291
293
|
_tag: 'advance',
|
292
|
-
newSyncState: {
|
294
|
+
newSyncState: new SyncState({
|
293
295
|
pending: [...syncState.pending, ...payload.newEvents],
|
294
296
|
rollbackTail: syncState.rollbackTail,
|
295
297
|
upstreamHead: syncState.upstreamHead,
|
296
298
|
localHead: payload.newEvents.at(-1)!.id,
|
297
|
-
},
|
299
|
+
}),
|
298
300
|
previousSyncState: syncState,
|
299
301
|
newEvents: payload.newEvents,
|
300
302
|
}
|
package/src/version.ts
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
// import packageJson from '../package.json' with { type: 'json' }
|
3
3
|
// export const liveStoreVersion = packageJson.version
|
4
4
|
|
5
|
-
export const liveStoreVersion = '0.3.0-dev.
|
5
|
+
export const liveStoreVersion = '0.3.0-dev.9' as const
|
6
6
|
|
7
7
|
/**
|
8
8
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|