@livestore/common 0.3.0-dev.26 → 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/adapter-types.d.ts +13 -12
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +5 -6
- package/dist/adapter-types.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
- package/dist/devtools/devtools-messages-common.d.ts +13 -6
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +6 -0
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +25 -25
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +1 -2
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +29 -7
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +259 -199
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/apply-mutation.d.ts +14 -9
- package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
- package/dist/leader-thread/apply-mutation.js +43 -36
- package/dist/leader-thread/apply-mutation.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +4 -5
- package/dist/leader-thread/leader-worker-devtools.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 +29 -34
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/mod.d.ts +1 -1
- package/dist/leader-thread/mod.d.ts.map +1 -1
- package/dist/leader-thread/mod.js +1 -1
- package/dist/leader-thread/mod.js.map +1 -1
- package/dist/leader-thread/mutationlog.d.ts +19 -3
- package/dist/leader-thread/mutationlog.d.ts.map +1 -1
- package/dist/leader-thread/mutationlog.js +105 -12
- package/dist/leader-thread/mutationlog.js.map +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
- package/dist/leader-thread/pull-queue-set.js +6 -16
- package/dist/leader-thread/pull-queue-set.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +4 -3
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +34 -19
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/rehydrate-from-mutationlog.d.ts +5 -4
- package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.js +7 -9
- package/dist/rehydrate-from-mutationlog.js.map +1 -1
- package/dist/schema/EventId.d.ts +9 -0
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +22 -2
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/MutationEvent.d.ts +78 -25
- package/dist/schema/MutationEvent.d.ts.map +1 -1
- package/dist/schema/MutationEvent.js +25 -12
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/system-tables.d.ts +67 -0
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +12 -1
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +9 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +25 -19
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/sync.d.ts +6 -5
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +47 -71
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +136 -139
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +203 -284
- 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/adapter-types.ts +11 -13
- package/src/devtools/devtools-messages-common.ts +9 -0
- package/src/devtools/devtools-messages-leader.ts +1 -2
- package/src/leader-thread/LeaderSyncProcessor.ts +457 -351
- package/src/leader-thread/apply-mutation.ts +81 -71
- package/src/leader-thread/leader-worker-devtools.ts +5 -7
- package/src/leader-thread/make-leader-thread-layer.ts +60 -53
- package/src/leader-thread/mod.ts +1 -1
- package/src/leader-thread/mutationlog.ts +166 -13
- package/src/leader-thread/recreate-db.ts +4 -3
- package/src/leader-thread/types.ts +33 -23
- package/src/rehydrate-from-mutationlog.ts +12 -12
- package/src/schema/EventId.ts +26 -2
- package/src/schema/MutationEvent.ts +32 -16
- package/src/schema/schema.ts +1 -1
- package/src/schema/system-tables.ts +20 -1
- package/src/sync/ClientSessionSyncProcessor.ts +35 -23
- package/src/sync/sync.ts +6 -9
- package/src/sync/syncstate.test.ts +228 -315
- package/src/sync/syncstate.ts +202 -187
- package/src/version.ts +1 -1
- package/tmp/pack.tgz +0 -0
- package/src/leader-thread/pull-queue-set.ts +0 -67
@@ -17,7 +17,6 @@ class TestEvent extends MutationEvent.EncodedWithMeta {
|
|
17
17
|
parentId: EventId.make(parentId),
|
18
18
|
mutation: 'a',
|
19
19
|
args: payload,
|
20
|
-
|
21
20
|
clientId: 'static-local-id',
|
22
21
|
sessionId: 'static-session-id',
|
23
22
|
})
|
@@ -32,14 +31,13 @@ class TestEvent extends MutationEvent.EncodedWithMeta {
|
|
32
31
|
// toString = () => this.toJSON()
|
33
32
|
}
|
34
33
|
|
35
|
-
const
|
36
|
-
const
|
37
|
-
const
|
38
|
-
const
|
39
|
-
const
|
40
|
-
const
|
41
|
-
const
|
42
|
-
const e_2_0 = new TestEvent({ global: 2, client: 0 }, e_1_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)
|
43
41
|
|
44
42
|
const isEqualEvent = MutationEvent.isEqualEncoded
|
45
43
|
|
@@ -47,7 +45,7 @@ const isClientEvent = (event: MutationEvent.EncodedWithMeta) => (event as TestEv
|
|
47
45
|
|
48
46
|
describe('syncstate', () => {
|
49
47
|
describe('merge', () => {
|
50
|
-
const
|
48
|
+
const merge = ({
|
51
49
|
syncState,
|
52
50
|
payload,
|
53
51
|
ignoreClientEvents = false,
|
@@ -57,322 +55,264 @@ describe('syncstate', () => {
|
|
57
55
|
ignoreClientEvents?: boolean
|
58
56
|
}) => SyncState.merge({ syncState, payload, isClientEvent, isEqualEvent, ignoreClientEvents })
|
59
57
|
|
60
|
-
describe
|
61
|
-
'
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
rollbackTail: [e_0_0, e_0_1],
|
99
|
-
upstreamHead: EventId.ROOT,
|
100
|
-
localHead: e_1_0.id,
|
101
|
-
})
|
102
|
-
const e_0_1_e_1_0 = e_0_1.rebase_(e_0_0.id)
|
103
|
-
const result = update({
|
104
|
-
syncState,
|
105
|
-
payload: {
|
106
|
-
_tag: 'upstream-rebase',
|
107
|
-
rollbackUntil: e_0_1.id,
|
108
|
-
newEvents: [e_0_1_e_1_0],
|
109
|
-
trimRollbackUntil: trimRollbackUntil ? e_0_0.id : undefined,
|
110
|
-
},
|
111
|
-
})
|
112
|
-
const e_1_0_e_2_0 = e_1_0.rebase_(e_0_1_e_1_0.id)
|
113
|
-
expectRebase(result)
|
114
|
-
expectEventArraysEqual(result.newSyncState.pending, [e_1_0_e_2_0])
|
115
|
-
if (trimRollbackUntil) {
|
116
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1_e_1_0])
|
117
|
-
} else {
|
118
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1_e_1_0])
|
119
|
-
}
|
120
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1_e_1_0.id)
|
121
|
-
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
122
|
-
expectEventArraysEqual(result.newEvents, [e_0_1_e_1_0, e_1_0_e_2_0])
|
123
|
-
expectEventArraysEqual(result.eventsToRollback, [e_0_1, e_1_0])
|
124
|
-
})
|
125
|
-
|
126
|
-
it('should work for empty pending', () => {
|
127
|
-
const syncState = new SyncState.SyncState({
|
128
|
-
pending: [],
|
129
|
-
rollbackTail: [e_0_0],
|
130
|
-
upstreamHead: EventId.ROOT,
|
131
|
-
localHead: e_0_0.id,
|
132
|
-
})
|
133
|
-
const result = update({
|
134
|
-
syncState,
|
135
|
-
payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [e_1_0] },
|
136
|
-
})
|
137
|
-
expectRebase(result)
|
138
|
-
expectEventArraysEqual(result.newSyncState.pending, [])
|
139
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_1_0])
|
140
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
|
141
|
-
expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
|
142
|
-
expect(result.newEvents).toStrictEqual([e_1_0])
|
143
|
-
})
|
144
|
-
|
145
|
-
it('should fail for empty rollback tail', () => {
|
146
|
-
const syncState = new SyncState.SyncState({
|
147
|
-
pending: [],
|
148
|
-
rollbackTail: [],
|
149
|
-
upstreamHead: EventId.ROOT,
|
150
|
-
localHead: e_0_0.id,
|
151
|
-
})
|
152
|
-
const result = update({
|
153
|
-
syncState,
|
154
|
-
payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [e_1_0] },
|
155
|
-
})
|
156
|
-
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
58
|
+
describe('upstream-rebase', () => {
|
59
|
+
it('should rollback until start', () => {
|
60
|
+
const syncState = new SyncState.SyncState({
|
61
|
+
pending: [e2_0],
|
62
|
+
upstreamHead: EventId.ROOT,
|
63
|
+
localHead: e2_0.id,
|
64
|
+
})
|
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)
|
67
|
+
const result = merge({
|
68
|
+
syncState,
|
69
|
+
payload: SyncState.PayloadUpstreamRebase.make({
|
70
|
+
rollbackEvents: [e1_0, e1_1],
|
71
|
+
newEvents: [e1_0_e2_0, e1_1_e2_1],
|
72
|
+
}),
|
73
|
+
})
|
74
|
+
const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.id)
|
75
|
+
expectRebase(result)
|
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])
|
81
|
+
})
|
82
|
+
|
83
|
+
it('should rollback only to specified point', () => {
|
84
|
+
const syncState = new SyncState.SyncState({
|
85
|
+
pending: [e2_0],
|
86
|
+
upstreamHead: EventId.ROOT,
|
87
|
+
localHead: e2_0.id,
|
88
|
+
})
|
89
|
+
const e1_1_e2_0 = e1_1.rebase_(e1_0.id)
|
90
|
+
const result = merge({
|
91
|
+
syncState,
|
92
|
+
payload: SyncState.PayloadUpstreamRebase.make({
|
93
|
+
newEvents: [e1_1_e2_0],
|
94
|
+
rollbackEvents: [e1_1],
|
95
|
+
}),
|
157
96
|
})
|
97
|
+
const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.id)
|
98
|
+
expectRebase(result)
|
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])
|
104
|
+
})
|
158
105
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
localHead: e_0_0.id,
|
165
|
-
})
|
166
|
-
const result = update({
|
167
|
-
syncState,
|
168
|
-
payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [] },
|
169
|
-
})
|
170
|
-
expectRebase(result)
|
171
|
-
expectEventArraysEqual(result.newSyncState.pending, [])
|
172
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [])
|
173
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
|
174
|
-
expect(result.newSyncState.localHead).toMatchObject(EventId.ROOT)
|
175
|
-
expect(result.newEvents).toStrictEqual([])
|
106
|
+
it('should work for empty pending', () => {
|
107
|
+
const syncState = new SyncState.SyncState({
|
108
|
+
pending: [],
|
109
|
+
upstreamHead: EventId.ROOT,
|
110
|
+
localHead: e1_0.id,
|
176
111
|
})
|
177
|
-
|
178
|
-
|
112
|
+
const result = merge({
|
113
|
+
syncState,
|
114
|
+
payload: SyncState.PayloadUpstreamRebase.make({ rollbackEvents: [e1_0], newEvents: [e2_0] }),
|
115
|
+
})
|
116
|
+
expectRebase(result)
|
117
|
+
expectEventArraysEqual(result.newSyncState.pending, [])
|
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])
|
121
|
+
})
|
122
|
+
})
|
179
123
|
|
180
124
|
describe('upstream-advance: advance', () => {
|
181
125
|
it('should throw error if newEvents are not sorted in ascending order by eventId (client)', () => {
|
182
126
|
const syncState = new SyncState.SyncState({
|
183
|
-
pending: [
|
184
|
-
rollbackTail: [],
|
127
|
+
pending: [e1_0],
|
185
128
|
upstreamHead: EventId.ROOT,
|
186
|
-
localHead:
|
129
|
+
localHead: e1_0.id,
|
187
130
|
})
|
188
|
-
const result =
|
131
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_0] } })
|
189
132
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
190
133
|
})
|
191
134
|
|
192
135
|
it('should throw error if newEvents are not sorted in ascending order by eventId (global)', () => {
|
193
136
|
const syncState = new SyncState.SyncState({
|
194
|
-
pending: [
|
195
|
-
rollbackTail: [],
|
137
|
+
pending: [e1_0],
|
196
138
|
upstreamHead: EventId.ROOT,
|
197
|
-
localHead:
|
139
|
+
localHead: e1_0.id,
|
198
140
|
})
|
199
|
-
const result =
|
141
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0, e1_0] } })
|
200
142
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
201
143
|
})
|
202
144
|
|
203
145
|
it('should throw error if incoming event is < expected upstream head', () => {
|
204
146
|
const syncState = new SyncState.SyncState({
|
205
147
|
pending: [],
|
206
|
-
|
207
|
-
|
208
|
-
localHead: e_1_0.id,
|
148
|
+
upstreamHead: e2_0.id,
|
149
|
+
localHead: e2_0.id,
|
209
150
|
})
|
210
|
-
const result =
|
151
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
211
152
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
212
153
|
})
|
213
154
|
|
214
155
|
it('should throw error if incoming event is = expected upstream head', () => {
|
215
156
|
const syncState = new SyncState.SyncState({
|
216
157
|
pending: [],
|
217
|
-
|
218
|
-
|
219
|
-
localHead: e_1_0.id,
|
158
|
+
upstreamHead: e2_0.id,
|
159
|
+
localHead: e2_0.id,
|
220
160
|
})
|
221
|
-
const result =
|
161
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0] } })
|
222
162
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
223
163
|
})
|
224
164
|
|
225
|
-
it('should
|
165
|
+
it('should confirm pending event when receiving matching event', () => {
|
226
166
|
const syncState = new SyncState.SyncState({
|
227
|
-
pending: [],
|
228
|
-
rollbackTail: [e_0_0],
|
167
|
+
pending: [e1_0],
|
229
168
|
upstreamHead: EventId.ROOT,
|
230
|
-
localHead:
|
169
|
+
localHead: e1_0.id,
|
231
170
|
})
|
232
|
-
const result =
|
233
|
-
|
171
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
172
|
+
|
173
|
+
expectAdvance(result)
|
174
|
+
expectEventArraysEqual(result.newSyncState.pending, [])
|
175
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
176
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0.id)
|
177
|
+
expectEventArraysEqual(result.newEvents, [])
|
178
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
234
179
|
})
|
235
180
|
|
236
|
-
it('should
|
181
|
+
it('should confirm partial pending event when receiving matching event', () => {
|
237
182
|
const syncState = new SyncState.SyncState({
|
238
|
-
pending: [
|
239
|
-
rollbackTail: [],
|
183
|
+
pending: [e1_0, e2_0],
|
240
184
|
upstreamHead: EventId.ROOT,
|
241
|
-
localHead:
|
185
|
+
localHead: e2_0.id,
|
242
186
|
})
|
243
|
-
const result =
|
187
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
244
188
|
|
245
189
|
expectAdvance(result)
|
246
|
-
expectEventArraysEqual(result.newSyncState.pending, [])
|
247
|
-
|
248
|
-
expect(result.newSyncState.
|
249
|
-
|
250
|
-
|
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)
|
193
|
+
expectEventArraysEqual(result.newEvents, [])
|
194
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
251
195
|
})
|
252
196
|
|
253
|
-
it('should
|
197
|
+
it('should confirm pending event and add new event', () => {
|
254
198
|
const syncState = new SyncState.SyncState({
|
255
|
-
pending: [
|
256
|
-
rollbackTail: [],
|
199
|
+
pending: [e1_0],
|
257
200
|
upstreamHead: EventId.ROOT,
|
258
|
-
localHead:
|
201
|
+
localHead: e1_0.id,
|
259
202
|
})
|
260
|
-
const result =
|
203
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0, e1_1] } })
|
261
204
|
|
262
205
|
expectAdvance(result)
|
263
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
264
|
-
|
265
|
-
expect(result.newSyncState.
|
266
|
-
expect(result.
|
267
|
-
|
206
|
+
expectEventArraysEqual(result.newSyncState.pending, [])
|
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])
|
268
211
|
})
|
269
212
|
|
270
|
-
it('should
|
213
|
+
it('should confirm pending event and add multiple new events', () => {
|
271
214
|
const syncState = new SyncState.SyncState({
|
272
|
-
pending: [
|
273
|
-
|
274
|
-
|
275
|
-
|
215
|
+
pending: [e1_1],
|
216
|
+
upstreamHead: e1_0.id,
|
217
|
+
localHead: e1_1.id,
|
218
|
+
})
|
219
|
+
const result = merge({
|
220
|
+
syncState,
|
221
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_2, e1_3, e2_0, e2_1] },
|
276
222
|
})
|
277
|
-
const result = update({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_0_1] } })
|
278
223
|
|
279
224
|
expectAdvance(result)
|
280
225
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
281
|
-
|
282
|
-
expect(result.newSyncState.
|
283
|
-
expect(result.
|
284
|
-
|
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])
|
285
230
|
})
|
286
231
|
|
287
|
-
it('should
|
232
|
+
it('should confirm pending global event while keep pending client events', () => {
|
288
233
|
const syncState = new SyncState.SyncState({
|
289
|
-
pending: [
|
290
|
-
|
291
|
-
|
292
|
-
localHead: e_0_1.id,
|
234
|
+
pending: [e1_0, e1_1],
|
235
|
+
upstreamHead: EventId.ROOT,
|
236
|
+
localHead: e1_1.id,
|
293
237
|
})
|
294
|
-
const result =
|
238
|
+
const result = merge({
|
295
239
|
syncState,
|
296
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
240
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
297
241
|
})
|
298
242
|
|
299
243
|
expectAdvance(result)
|
300
|
-
expectEventArraysEqual(result.newSyncState.pending, [])
|
301
|
-
|
302
|
-
expect(result.newSyncState.
|
303
|
-
|
304
|
-
|
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)
|
247
|
+
expectEventArraysEqual(result.newEvents, [])
|
248
|
+
expectEventArraysEqual(result.confirmedEvents, [e1_0])
|
305
249
|
})
|
306
250
|
|
307
251
|
it('should ignore client events (incoming is subset of pending)', () => {
|
308
252
|
const syncState = new SyncState.SyncState({
|
309
|
-
pending: [
|
310
|
-
rollbackTail: [],
|
253
|
+
pending: [e0_1, e1_0],
|
311
254
|
upstreamHead: EventId.ROOT,
|
312
|
-
localHead:
|
255
|
+
localHead: e1_0.id,
|
313
256
|
})
|
314
|
-
const result =
|
257
|
+
const result = merge({
|
315
258
|
syncState,
|
316
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
259
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
317
260
|
ignoreClientEvents: true,
|
318
261
|
})
|
319
262
|
expectAdvance(result)
|
320
263
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
321
|
-
|
322
|
-
expect(result.newSyncState.
|
323
|
-
|
324
|
-
|
264
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.id)
|
265
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_0.id)
|
266
|
+
expectEventArraysEqual(result.newEvents, [])
|
267
|
+
expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
|
325
268
|
})
|
326
269
|
|
327
270
|
it('should ignore client events (incoming is subset of pending case 2)', () => {
|
328
271
|
const syncState = new SyncState.SyncState({
|
329
|
-
pending: [
|
330
|
-
rollbackTail: [],
|
272
|
+
pending: [e0_1, e1_0, e2_0],
|
331
273
|
upstreamHead: EventId.ROOT,
|
332
|
-
localHead:
|
274
|
+
localHead: e1_0.id,
|
333
275
|
})
|
334
|
-
const result =
|
276
|
+
const result = merge({
|
335
277
|
syncState,
|
336
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
278
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
|
337
279
|
ignoreClientEvents: true,
|
338
280
|
})
|
339
281
|
expectAdvance(result)
|
340
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
341
|
-
|
342
|
-
expect(result.newSyncState.
|
343
|
-
|
344
|
-
|
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)
|
285
|
+
expectEventArraysEqual(result.newEvents, [])
|
286
|
+
expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
|
345
287
|
})
|
346
288
|
|
347
289
|
it('should ignore client events (incoming goes beyond pending)', () => {
|
348
290
|
const syncState = new SyncState.SyncState({
|
349
|
-
pending: [
|
350
|
-
rollbackTail: [],
|
291
|
+
pending: [e0_1, e1_0, e1_1],
|
351
292
|
upstreamHead: EventId.ROOT,
|
352
|
-
localHead:
|
293
|
+
localHead: e1_1.id,
|
353
294
|
})
|
354
|
-
const result =
|
295
|
+
const result = merge({
|
355
296
|
syncState,
|
356
|
-
payload: { _tag: 'upstream-advance', newEvents: [
|
297
|
+
payload: { _tag: 'upstream-advance', newEvents: [e1_0, e2_0] },
|
357
298
|
ignoreClientEvents: true,
|
358
299
|
})
|
359
300
|
|
360
301
|
expectAdvance(result)
|
361
302
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
362
|
-
|
363
|
-
expect(result.newSyncState.
|
364
|
-
expect(result.
|
365
|
-
|
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])
|
366
307
|
})
|
367
308
|
|
368
309
|
it('should fail if incoming event is ≤ local head', () => {
|
369
310
|
const syncState = new SyncState.SyncState({
|
370
311
|
pending: [],
|
371
|
-
|
372
|
-
|
373
|
-
localHead: e_1_0.id,
|
312
|
+
upstreamHead: e2_0.id,
|
313
|
+
localHead: e2_0.id,
|
374
314
|
})
|
375
|
-
const result =
|
315
|
+
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
376
316
|
expect(result).toMatchObject({ _tag: 'unexpected-error' })
|
377
317
|
})
|
378
318
|
})
|
@@ -380,165 +320,138 @@ describe('syncstate', () => {
|
|
380
320
|
describe('upstream-advance: rebase', () => {
|
381
321
|
it('should rebase single client event to end', () => {
|
382
322
|
const syncState = new SyncState.SyncState({
|
383
|
-
pending: [
|
384
|
-
rollbackTail: [],
|
385
|
-
upstreamHead: EventId.ROOT,
|
386
|
-
localHead: e_0_0.id,
|
387
|
-
})
|
388
|
-
const result = update({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_1] } })
|
389
|
-
|
390
|
-
const e_0_0_e_0_2 = e_0_0.rebase_(e_0_1.id)
|
391
|
-
|
392
|
-
expectRebase(result)
|
393
|
-
expectEventArraysEqual(result.newSyncState.pending, [e_0_0_e_0_2])
|
394
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1])
|
395
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1.id)
|
396
|
-
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_0_2.id)
|
397
|
-
expectEventArraysEqual(result.eventsToRollback, [e_0_0])
|
398
|
-
expectEventArraysEqual(result.newEvents, [e_0_1, e_0_0_e_0_2])
|
399
|
-
})
|
400
|
-
|
401
|
-
it('should rebase different event with same id (no rollback tail)', () => {
|
402
|
-
const e_0_0_b = new TestEvent({ global: 0, client: 0 }, EventId.ROOT, '0_0_b', true)
|
403
|
-
const syncState = new SyncState.SyncState({
|
404
|
-
pending: [e_0_0_b],
|
405
|
-
rollbackTail: [],
|
323
|
+
pending: [e1_0],
|
406
324
|
upstreamHead: EventId.ROOT,
|
407
|
-
localHead:
|
325
|
+
localHead: e1_0.id,
|
408
326
|
})
|
409
|
-
const result =
|
327
|
+
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }) })
|
410
328
|
|
411
|
-
const
|
329
|
+
const e1_0_e1_2 = e1_0.rebase_(e1_1.id)
|
412
330
|
|
413
331
|
expectRebase(result)
|
414
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
415
|
-
|
416
|
-
|
417
|
-
expectEventArraysEqual(result.
|
418
|
-
|
419
|
-
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_1_0.id)
|
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])
|
420
337
|
})
|
421
338
|
|
422
339
|
it('should rebase different event with same id', () => {
|
423
|
-
const
|
340
|
+
const e2_0_b = new TestEvent({ global: 1, client: 0 }, e1_0.id, '1_0_b', false)
|
424
341
|
const syncState = new SyncState.SyncState({
|
425
|
-
pending: [
|
426
|
-
rollbackTail: [e_0_0, e_0_1],
|
342
|
+
pending: [e2_0_b],
|
427
343
|
upstreamHead: EventId.ROOT,
|
428
|
-
localHead:
|
344
|
+
localHead: e2_0_b.id,
|
429
345
|
})
|
430
|
-
const result =
|
431
|
-
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)
|
432
348
|
|
433
349
|
expectRebase(result)
|
434
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
435
|
-
expectEventArraysEqual(result.
|
436
|
-
expectEventArraysEqual(result.
|
437
|
-
|
438
|
-
expect(result.newSyncState.
|
439
|
-
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
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)
|
440
355
|
})
|
441
356
|
|
442
357
|
it('should rebase single client event to end (more incoming events)', () => {
|
443
358
|
const syncState = new SyncState.SyncState({
|
444
|
-
pending: [
|
445
|
-
rollbackTail: [],
|
359
|
+
pending: [e1_0],
|
446
360
|
upstreamHead: EventId.ROOT,
|
447
|
-
localHead:
|
361
|
+
localHead: e1_0.id,
|
448
362
|
})
|
449
|
-
const result =
|
363
|
+
const result = merge({
|
450
364
|
syncState,
|
451
|
-
payload: {
|
365
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
|
452
366
|
})
|
453
367
|
|
454
|
-
const
|
368
|
+
const e1_0_e3_0 = e1_0.rebase_(e2_0.id)
|
455
369
|
|
456
370
|
expectRebase(result)
|
457
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
458
|
-
|
459
|
-
expect(result.newSyncState.
|
460
|
-
expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_2_0.id)
|
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)
|
461
374
|
})
|
462
375
|
|
463
376
|
it('should only rebase divergent events when first event matches', () => {
|
464
377
|
const syncState = new SyncState.SyncState({
|
465
|
-
pending: [
|
466
|
-
rollbackTail: [],
|
378
|
+
pending: [e1_0, e1_1],
|
467
379
|
upstreamHead: EventId.ROOT,
|
468
|
-
localHead:
|
380
|
+
localHead: e1_0.id,
|
469
381
|
})
|
470
|
-
const result =
|
382
|
+
const result = merge({
|
471
383
|
syncState,
|
472
|
-
payload: {
|
384
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_0, e1_2, e1_3, e2_0] }),
|
473
385
|
})
|
474
386
|
|
475
|
-
const
|
387
|
+
const e1_1_e2_1 = e1_1.rebase_(e2_0.id)
|
476
388
|
|
477
389
|
expectRebase(result)
|
478
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
479
|
-
expectEventArraysEqual(result.
|
480
|
-
expectEventArraysEqual(result.
|
481
|
-
|
482
|
-
expect(result.newSyncState.
|
483
|
-
expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_1.id)
|
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)
|
484
395
|
})
|
485
396
|
|
486
397
|
it('should rebase all client events when incoming chain starts differently', () => {
|
487
398
|
const syncState = new SyncState.SyncState({
|
488
|
-
pending: [
|
489
|
-
rollbackTail: [],
|
399
|
+
pending: [e1_0, e1_1],
|
490
400
|
upstreamHead: EventId.ROOT,
|
491
|
-
localHead:
|
401
|
+
localHead: e1_1.id,
|
492
402
|
})
|
493
|
-
const result =
|
403
|
+
const result = merge({
|
494
404
|
syncState,
|
495
|
-
payload: {
|
405
|
+
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
|
496
406
|
})
|
497
407
|
|
498
|
-
const
|
499
|
-
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)
|
500
410
|
|
501
411
|
expectRebase(result)
|
502
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
503
|
-
expectEventArraysEqual(result.
|
504
|
-
expectEventArraysEqual(result.
|
505
|
-
|
506
|
-
expect(result.newSyncState.
|
507
|
-
expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_2.id)
|
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)
|
508
417
|
})
|
509
418
|
|
510
419
|
describe('local-push', () => {
|
511
420
|
describe('advance', () => {
|
512
421
|
it('should advance with new events', () => {
|
513
422
|
const syncState = new SyncState.SyncState({
|
514
|
-
pending: [
|
515
|
-
rollbackTail: [],
|
423
|
+
pending: [e1_0],
|
516
424
|
upstreamHead: EventId.ROOT,
|
517
|
-
localHead:
|
425
|
+
localHead: e1_0.id,
|
426
|
+
})
|
427
|
+
const result = merge({
|
428
|
+
syncState,
|
429
|
+
payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2, e1_3] }),
|
518
430
|
})
|
519
|
-
const result = update({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2, e_0_3] } })
|
520
431
|
|
521
432
|
expectAdvance(result)
|
522
|
-
expectEventArraysEqual(result.newSyncState.pending, [
|
523
|
-
expectEventArraysEqual(result.newSyncState.rollbackTail, [])
|
433
|
+
expectEventArraysEqual(result.newSyncState.pending, [e1_0, e1_1, e1_2, e1_3])
|
524
434
|
expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
|
525
|
-
expect(result.newSyncState.localHead).toMatchObject(
|
526
|
-
expectEventArraysEqual(result.newEvents, [
|
435
|
+
expect(result.newSyncState.localHead).toMatchObject(e1_3.id)
|
436
|
+
expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3])
|
437
|
+
expectEventArraysEqual(result.confirmedEvents, [])
|
527
438
|
})
|
528
439
|
})
|
529
440
|
|
530
441
|
describe('reject', () => {
|
531
442
|
it('should reject when new events are greater than pending events', () => {
|
532
443
|
const syncState = new SyncState.SyncState({
|
533
|
-
pending: [
|
534
|
-
rollbackTail: [],
|
444
|
+
pending: [e1_0, e1_1],
|
535
445
|
upstreamHead: EventId.ROOT,
|
536
|
-
localHead:
|
446
|
+
localHead: e1_1.id,
|
447
|
+
})
|
448
|
+
const result = merge({
|
449
|
+
syncState,
|
450
|
+
payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2] }),
|
537
451
|
})
|
538
|
-
const result = update({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2] } })
|
539
452
|
|
540
453
|
expectReject(result)
|
541
|
-
expect(result.expectedMinimumId).toMatchObject(
|
454
|
+
expect(result.expectedMinimumId).toMatchObject(e1_2.id)
|
542
455
|
})
|
543
456
|
})
|
544
457
|
})
|
@@ -568,7 +481,7 @@ function expectAdvance(
|
|
568
481
|
function expectRebase(
|
569
482
|
result: typeof SyncState.MergeResult.Type,
|
570
483
|
): asserts result is typeof SyncState.MergeResultRebase.Type {
|
571
|
-
expect(result._tag).toBe('rebase')
|
484
|
+
expect(result._tag, `Expected rebase, got ${result}`).toBe('rebase')
|
572
485
|
}
|
573
486
|
|
574
487
|
function expectReject(
|