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