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