@livestore/common 0.4.0-dev.17 → 0.4.0-dev.19
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/ClientSessionLeaderThreadProxy.d.ts +10 -10
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/adapter-types.d.ts +5 -5
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +2 -2
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +33 -28
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +8 -8
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/errors.d.ts +6 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +7 -7
- package/dist/errors.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +2 -2
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +28 -28
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +13 -13
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +12 -11
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +3 -3
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +2 -2
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +10 -8
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/materialize-event.d.ts +1 -1
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +2 -2
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts +2 -2
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +5 -5
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -2
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -2
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/types.d.ts +15 -15
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/make-client-session.d.ts +2 -2
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/materializer-helper.d.ts +5 -5
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +2 -2
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +6 -6
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +147 -0
- package/dist/schema/EventDef/define.d.ts.map +1 -0
- package/dist/schema/EventDef/define.js +139 -0
- package/dist/schema/EventDef/define.js.map +1 -0
- package/dist/schema/EventDef/event-def.d.ts +106 -0
- package/dist/schema/EventDef/event-def.d.ts.map +1 -0
- package/dist/schema/EventDef/event-def.js +2 -0
- package/dist/schema/EventDef/event-def.js.map +1 -0
- package/dist/schema/EventDef/facts.d.ts +118 -0
- package/dist/schema/EventDef/facts.d.ts.map +1 -0
- package/dist/schema/EventDef/facts.js +53 -0
- package/dist/schema/EventDef/facts.js.map +1 -0
- package/dist/schema/EventDef/materializer.d.ts +155 -0
- package/dist/schema/EventDef/materializer.d.ts.map +1 -0
- package/dist/schema/EventDef/materializer.js +83 -0
- package/dist/schema/EventDef/materializer.js.map +1 -0
- package/dist/schema/EventDef/mod.d.ts +5 -0
- package/dist/schema/EventDef/mod.d.ts.map +1 -0
- package/dist/schema/EventDef/mod.js +5 -0
- package/dist/schema/EventDef/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
- package/dist/schema/{EventSequenceNumber.js → EventSequenceNumber/client.js} +86 -39
- package/dist/schema/EventSequenceNumber/client.js.map +1 -0
- package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
- package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/global.js +14 -0
- package/dist/schema/EventSequenceNumber/global.js.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.js +37 -0
- package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber.test.js +41 -41
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +84 -101
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
- package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +69 -52
- package/dist/schema/LiveStoreEvent/client.js.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
- package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
- package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/global.js +31 -0
- package/dist/schema/LiveStoreEvent/global.js.map +1 -0
- package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
- package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/input.js +26 -0
- package/dist/schema/LiveStoreEvent/input.js.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.js +5 -0
- package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
- package/dist/schema/events.d.ts +1 -1
- package/dist/schema/events.d.ts.map +1 -1
- package/dist/schema/events.js +1 -1
- package/dist/schema/events.js.map +1 -1
- package/dist/schema/mod.d.ts +3 -3
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +3 -3
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +2 -2
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +60 -28
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +12 -1
- package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +2 -2
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +1 -1
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +12 -8
- package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.js +18 -11
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +0 -1
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +119 -90
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +5 -5
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables/state-tables.js +3 -3
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
- package/dist/schema/unknown-events.d.ts +3 -3
- package/dist/schema/unknown-events.d.ts.map +1 -1
- package/dist/schema-management/migrations.d.ts +2 -2
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/validate-schema.d.ts +3 -3
- package/dist/schema-management/validate-schema.d.ts.map +1 -1
- package/dist/schema-management/validate-schema.js +2 -2
- package/dist/schema-management/validate-schema.js.map +1 -1
- package/dist/sqlite-types.d.ts +3 -3
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +5 -5
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +12 -12
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +9 -4
- package/dist/sync/errors.d.ts.map +1 -1
- package/dist/sync/errors.js +6 -6
- package/dist/sync/errors.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +6 -6
- package/dist/sync/mock-sync-backend.d.ts.map +1 -1
- package/dist/sync/mock-sync-backend.js +4 -4
- package/dist/sync/mock-sync-backend.js.map +1 -1
- package/dist/sync/next/compact-events.js +2 -2
- package/dist/sync/next/compact-events.js.map +1 -1
- package/dist/sync/next/facts.d.ts +5 -5
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +5 -5
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +5 -5
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.d.ts.map +1 -1
- package/dist/sync/next/history-dag.js +8 -8
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +5 -5
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +5 -5
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts +2 -2
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +9 -9
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync-backend-kv.d.ts +3 -3
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js +3 -3
- package/dist/sync/sync-backend-kv.js.map +1 -1
- package/dist/sync/sync-backend.d.ts +9 -9
- package/dist/sync/sync-backend.d.ts.map +1 -1
- package/dist/sync/syncstate.d.ts +55 -42
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +42 -42
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +40 -40
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/validate-push-payload.d.ts +1 -1
- package/dist/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js +2 -2
- package/dist/sync/validate-push-payload.js.map +1 -1
- package/dist/testing/event-factory.d.ts +3 -3
- package/dist/testing/event-factory.d.ts.map +1 -1
- package/dist/testing/event-factory.js +5 -7
- package/dist/testing/event-factory.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/src/ClientSessionLeaderThreadProxy.ts +10 -10
- package/src/adapter-types.ts +5 -5
- package/src/devtools/devtools-messages-client-session.ts +2 -2
- package/src/devtools/devtools-messages-leader.ts +8 -8
- package/src/errors.ts +11 -13
- package/src/leader-thread/LeaderSyncProcessor.ts +54 -56
- package/src/leader-thread/eventlog.ts +21 -26
- package/src/leader-thread/leader-worker-devtools.ts +3 -3
- package/src/leader-thread/make-leader-thread-layer.ts +12 -10
- package/src/leader-thread/materialize-event.ts +3 -3
- package/src/leader-thread/recreate-db.ts +6 -6
- package/src/leader-thread/shutdown-channel.ts +2 -2
- package/src/leader-thread/types.ts +15 -15
- package/src/make-client-session.ts +2 -2
- package/src/materializer-helper.ts +5 -5
- package/src/rematerialize-from-eventlog.ts +6 -6
- package/src/schema/EventDef/define.ts +201 -0
- package/src/schema/EventDef/event-def.ts +120 -0
- package/src/schema/EventDef/facts.ts +135 -0
- package/src/schema/EventDef/materializer.ts +172 -0
- package/src/schema/EventDef/mod.ts +4 -0
- package/src/schema/EventSequenceNumber/client.ts +257 -0
- package/src/schema/EventSequenceNumber/global.ts +19 -0
- package/src/schema/EventSequenceNumber/mod.ts +37 -0
- package/src/schema/EventSequenceNumber.test.ts +68 -50
- package/src/schema/LiveStoreEvent/client.ts +221 -0
- package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
- package/src/schema/LiveStoreEvent/global.ts +45 -0
- package/src/schema/LiveStoreEvent/input.ts +63 -0
- package/src/schema/LiveStoreEvent/mod.ts +4 -0
- package/src/schema/events.ts +1 -1
- package/src/schema/mod.ts +3 -3
- package/src/schema/schema.ts +1 -1
- package/src/schema/state/sqlite/client-document-def.test.ts +2 -2
- package/src/schema/state/sqlite/client-document-def.ts +3 -3
- package/src/schema/state/sqlite/column-def.test.ts +18 -1
- package/src/schema/state/sqlite/column-def.ts +73 -30
- package/src/schema/state/sqlite/mod.ts +2 -2
- package/src/schema/state/sqlite/query-builder/api.ts +12 -8
- package/src/schema/state/sqlite/query-builder/astToSql.ts +20 -11
- package/src/schema/state/sqlite/query-builder/impl.test.ts +122 -90
- package/src/schema/state/sqlite/query-builder/impl.ts +0 -1
- package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +5 -5
- package/src/schema/state/sqlite/system-tables/state-tables.ts +3 -3
- package/src/schema/unknown-events.ts +3 -3
- package/src/schema-management/migrations.ts +2 -2
- package/src/schema-management/validate-schema.ts +3 -3
- package/src/sqlite-types.ts +3 -3
- package/src/sync/ClientSessionSyncProcessor.ts +17 -17
- package/src/sync/errors.ts +6 -6
- package/src/sync/mock-sync-backend.ts +16 -16
- package/src/sync/next/compact-events.ts +2 -2
- package/src/sync/next/facts.ts +6 -6
- package/src/sync/next/history-dag-common.ts +8 -8
- package/src/sync/next/history-dag.ts +14 -10
- package/src/sync/next/rebase-events.ts +11 -11
- package/src/sync/next/test/event-fixtures.ts +11 -11
- package/src/sync/sync-backend-kv.ts +3 -3
- package/src/sync/sync-backend.ts +9 -9
- package/src/sync/syncstate.test.ts +46 -46
- package/src/sync/syncstate.ts +59 -55
- package/src/sync/validate-push-payload.ts +4 -4
- package/src/testing/event-factory.ts +10 -12
- package/src/version.ts +1 -1
- package/dist/schema/EventDef.d.ts +0 -126
- package/dist/schema/EventDef.d.ts.map +0 -1
- package/dist/schema/EventDef.js +0 -46
- package/dist/schema/EventDef.js.map +0 -1
- package/dist/schema/EventSequenceNumber.d.ts +0 -89
- package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
- package/dist/schema/EventSequenceNumber.js.map +0 -1
- package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
- package/dist/schema/LiveStoreEvent.js.map +0 -1
- package/src/schema/EventDef.ts +0 -222
- package/src/schema/EventSequenceNumber.ts +0 -208
- package/src/schema/LiveStoreEvent.ts +0 -286
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import * as EventSequenceNumber from '../schema/EventSequenceNumber.ts'
|
|
4
|
-
import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
|
|
3
|
+
import * as EventSequenceNumber from '../schema/EventSequenceNumber/mod.ts'
|
|
4
|
+
import * as LiveStoreEvent from '../schema/LiveStoreEvent/mod.ts'
|
|
5
5
|
import * as SyncState from './syncstate.ts'
|
|
6
6
|
|
|
7
|
-
class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
7
|
+
class TestEvent extends LiveStoreEvent.Client.EncodedWithMeta {
|
|
8
8
|
public payload = 'uninitialized'
|
|
9
9
|
public isClient = false
|
|
10
10
|
|
|
11
11
|
static new = (
|
|
12
|
-
seqNum: EventSequenceNumber.
|
|
13
|
-
parentSeqNum: EventSequenceNumber.
|
|
12
|
+
seqNum: EventSequenceNumber.Client.CompositeInput,
|
|
13
|
+
parentSeqNum: EventSequenceNumber.Client.CompositeInput,
|
|
14
14
|
payload: string,
|
|
15
15
|
isClient: boolean,
|
|
16
16
|
) => {
|
|
17
17
|
const event = new TestEvent({
|
|
18
|
-
seqNum: EventSequenceNumber.make(seqNum),
|
|
19
|
-
parentSeqNum: EventSequenceNumber.make(parentSeqNum),
|
|
18
|
+
seqNum: EventSequenceNumber.Client.Composite.make(seqNum),
|
|
19
|
+
parentSeqNum: EventSequenceNumber.Client.Composite.make(parentSeqNum),
|
|
20
20
|
name: 'a',
|
|
21
21
|
args: payload,
|
|
22
22
|
clientId: 'static-local-id',
|
|
@@ -27,7 +27,7 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
|
27
27
|
return event
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
rebase_ = (parentSeqNum: EventSequenceNumber.
|
|
30
|
+
rebase_ = (parentSeqNum: EventSequenceNumber.Client.Composite, rebaseGeneration: number) => {
|
|
31
31
|
return this.rebase({ parentSeqNum, isClient: this.isClient, rebaseGeneration })
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -36,17 +36,17 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
|
36
36
|
// toString = () => this.toJSON()
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const e0_1 = TestEvent.new({ global: 0, client: 1 }, EventSequenceNumber.ROOT, 'a', true)
|
|
40
|
-
const e1_0 = TestEvent.new({ global: 1, client: 0 }, EventSequenceNumber.ROOT, 'a', false)
|
|
39
|
+
const e0_1 = TestEvent.new({ global: 0, client: 1 }, EventSequenceNumber.Client.ROOT, 'a', true)
|
|
40
|
+
const e1_0 = TestEvent.new({ global: 1, client: 0 }, EventSequenceNumber.Client.ROOT, 'a', false)
|
|
41
41
|
const e1_1 = TestEvent.new({ global: 1, client: 1 }, e1_0.seqNum, 'a', true)
|
|
42
42
|
const e1_2 = TestEvent.new({ global: 1, client: 2 }, e1_1.seqNum, 'a', true)
|
|
43
43
|
const e1_3 = TestEvent.new({ global: 1, client: 3 }, e1_2.seqNum, 'a', true)
|
|
44
44
|
const e2_0 = TestEvent.new({ global: 2, client: 0 }, e1_0.seqNum, 'a', false)
|
|
45
45
|
const e2_1 = TestEvent.new({ global: 2, client: 1 }, e2_0.seqNum, 'a', true)
|
|
46
46
|
|
|
47
|
-
const isEqualEvent = LiveStoreEvent.isEqualEncoded
|
|
47
|
+
const isEqualEvent = LiveStoreEvent.Client.isEqualEncoded
|
|
48
48
|
|
|
49
|
-
const isClientEvent = (event: LiveStoreEvent.EncodedWithMeta) => (event as TestEvent).isClient
|
|
49
|
+
const isClientEvent = (event: LiveStoreEvent.Client.EncodedWithMeta) => (event as TestEvent).isClient
|
|
50
50
|
|
|
51
51
|
describe('syncstate', () => {
|
|
52
52
|
describe('merge', () => {
|
|
@@ -64,7 +64,7 @@ describe('syncstate', () => {
|
|
|
64
64
|
it('should rollback until start', () => {
|
|
65
65
|
const syncState = new SyncState.SyncState({
|
|
66
66
|
pending: [e2_0],
|
|
67
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
67
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
68
68
|
localHead: e2_0.seqNum,
|
|
69
69
|
})
|
|
70
70
|
const e1_0_e2_0 = e1_0.rebase_(e2_0.seqNum, 0)
|
|
@@ -88,7 +88,7 @@ describe('syncstate', () => {
|
|
|
88
88
|
it('should rollback only to specified point', () => {
|
|
89
89
|
const syncState = new SyncState.SyncState({
|
|
90
90
|
pending: [e2_0],
|
|
91
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
91
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
92
92
|
localHead: e2_0.seqNum,
|
|
93
93
|
})
|
|
94
94
|
const e1_1_e2_0 = e1_1.rebase_(e1_0.seqNum, 0)
|
|
@@ -111,7 +111,7 @@ describe('syncstate', () => {
|
|
|
111
111
|
it('should work for empty pending', () => {
|
|
112
112
|
const syncState = new SyncState.SyncState({
|
|
113
113
|
pending: [],
|
|
114
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
114
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
115
115
|
localHead: e1_0.seqNum,
|
|
116
116
|
})
|
|
117
117
|
const result = merge({
|
|
@@ -130,21 +130,21 @@ describe('syncstate', () => {
|
|
|
130
130
|
it('should throw error if newEvents are not sorted in ascending order by event number (client)', () => {
|
|
131
131
|
const syncState = new SyncState.SyncState({
|
|
132
132
|
pending: [e1_0],
|
|
133
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
133
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
134
134
|
localHead: e1_0.seqNum,
|
|
135
135
|
})
|
|
136
136
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_0] } })
|
|
137
|
-
expect(result).toMatchObject({ _tag: '
|
|
137
|
+
expect(result).toMatchObject({ _tag: 'unknown-error' })
|
|
138
138
|
})
|
|
139
139
|
|
|
140
140
|
it('should throw error if newEvents are not sorted in ascending order by event number (global)', () => {
|
|
141
141
|
const syncState = new SyncState.SyncState({
|
|
142
142
|
pending: [e1_0],
|
|
143
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
143
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
144
144
|
localHead: e1_0.seqNum,
|
|
145
145
|
})
|
|
146
146
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0, e1_0] } })
|
|
147
|
-
expect(result).toMatchObject({ _tag: '
|
|
147
|
+
expect(result).toMatchObject({ _tag: 'unknown-error' })
|
|
148
148
|
})
|
|
149
149
|
|
|
150
150
|
it('should throw error if incoming event is < expected upstream head', () => {
|
|
@@ -154,7 +154,7 @@ describe('syncstate', () => {
|
|
|
154
154
|
localHead: e2_0.seqNum,
|
|
155
155
|
})
|
|
156
156
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
|
157
|
-
expect(result).toMatchObject({ _tag: '
|
|
157
|
+
expect(result).toMatchObject({ _tag: 'unknown-error' })
|
|
158
158
|
})
|
|
159
159
|
|
|
160
160
|
it('should throw error if incoming event is = expected upstream head', () => {
|
|
@@ -164,13 +164,13 @@ describe('syncstate', () => {
|
|
|
164
164
|
localHead: e2_0.seqNum,
|
|
165
165
|
})
|
|
166
166
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0] } })
|
|
167
|
-
expect(result).toMatchObject({ _tag: '
|
|
167
|
+
expect(result).toMatchObject({ _tag: 'unknown-error' })
|
|
168
168
|
})
|
|
169
169
|
|
|
170
170
|
it('should confirm pending event when receiving matching event', () => {
|
|
171
171
|
const syncState = new SyncState.SyncState({
|
|
172
172
|
pending: [e1_0],
|
|
173
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
173
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
174
174
|
localHead: e1_0.seqNum,
|
|
175
175
|
})
|
|
176
176
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
|
@@ -186,7 +186,7 @@ describe('syncstate', () => {
|
|
|
186
186
|
it('should confirm partial pending event when receiving matching event', () => {
|
|
187
187
|
const syncState = new SyncState.SyncState({
|
|
188
188
|
pending: [e1_0, e2_0],
|
|
189
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
189
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
190
190
|
localHead: e2_0.seqNum,
|
|
191
191
|
})
|
|
192
192
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
|
@@ -202,7 +202,7 @@ describe('syncstate', () => {
|
|
|
202
202
|
it('should confirm pending event and add new event', () => {
|
|
203
203
|
const syncState = new SyncState.SyncState({
|
|
204
204
|
pending: [e1_0],
|
|
205
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
205
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
206
206
|
localHead: e1_0.seqNum,
|
|
207
207
|
})
|
|
208
208
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0, e1_1] } })
|
|
@@ -237,7 +237,7 @@ describe('syncstate', () => {
|
|
|
237
237
|
it('should confirm pending global event while keep pending client events', () => {
|
|
238
238
|
const syncState = new SyncState.SyncState({
|
|
239
239
|
pending: [e1_0, e1_1],
|
|
240
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
240
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
241
241
|
localHead: e1_1.seqNum,
|
|
242
242
|
})
|
|
243
243
|
const result = merge({
|
|
@@ -256,7 +256,7 @@ describe('syncstate', () => {
|
|
|
256
256
|
it('should ignore client events (incoming is subset of pending)', () => {
|
|
257
257
|
const syncState = new SyncState.SyncState({
|
|
258
258
|
pending: [e0_1, e1_0],
|
|
259
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
259
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
260
260
|
localHead: e1_0.seqNum,
|
|
261
261
|
})
|
|
262
262
|
const result = merge({
|
|
@@ -275,7 +275,7 @@ describe('syncstate', () => {
|
|
|
275
275
|
it('should ignore client events (incoming is subset of pending case 2)', () => {
|
|
276
276
|
const syncState = new SyncState.SyncState({
|
|
277
277
|
pending: [e0_1, e1_0, e2_0],
|
|
278
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
278
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
279
279
|
localHead: e1_0.seqNum,
|
|
280
280
|
})
|
|
281
281
|
const result = merge({
|
|
@@ -294,7 +294,7 @@ describe('syncstate', () => {
|
|
|
294
294
|
it('should ignore client events (incoming goes beyond pending)', () => {
|
|
295
295
|
const syncState = new SyncState.SyncState({
|
|
296
296
|
pending: [e0_1, e1_0, e1_1],
|
|
297
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
297
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
298
298
|
localHead: e1_1.seqNum,
|
|
299
299
|
})
|
|
300
300
|
const result = merge({
|
|
@@ -318,7 +318,7 @@ describe('syncstate', () => {
|
|
|
318
318
|
localHead: e2_0.seqNum,
|
|
319
319
|
})
|
|
320
320
|
const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
|
|
321
|
-
expect(result).toMatchObject({ _tag: '
|
|
321
|
+
expect(result).toMatchObject({ _tag: 'unknown-error' })
|
|
322
322
|
})
|
|
323
323
|
})
|
|
324
324
|
|
|
@@ -326,7 +326,7 @@ describe('syncstate', () => {
|
|
|
326
326
|
it('should rebase single client event to end', () => {
|
|
327
327
|
const syncState = new SyncState.SyncState({
|
|
328
328
|
pending: [e1_0],
|
|
329
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
329
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
330
330
|
localHead: e1_0.seqNum,
|
|
331
331
|
})
|
|
332
332
|
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }) })
|
|
@@ -345,7 +345,7 @@ describe('syncstate', () => {
|
|
|
345
345
|
const e2_0_b = TestEvent.new({ global: 1, client: 0 }, e1_0.seqNum, '1_0_b', false)
|
|
346
346
|
const syncState = new SyncState.SyncState({
|
|
347
347
|
pending: [e2_0_b],
|
|
348
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
348
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
349
349
|
localHead: e2_0_b.seqNum,
|
|
350
350
|
})
|
|
351
351
|
const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e2_0] }) })
|
|
@@ -362,7 +362,7 @@ describe('syncstate', () => {
|
|
|
362
362
|
it('should rebase single client event to end (more incoming events)', () => {
|
|
363
363
|
const syncState = new SyncState.SyncState({
|
|
364
364
|
pending: [e1_0],
|
|
365
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
365
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
366
366
|
localHead: e1_0.seqNum,
|
|
367
367
|
})
|
|
368
368
|
const result = merge({
|
|
@@ -381,7 +381,7 @@ describe('syncstate', () => {
|
|
|
381
381
|
it('should only rebase divergent events when first event matches', () => {
|
|
382
382
|
const syncState = new SyncState.SyncState({
|
|
383
383
|
pending: [e1_0, e1_1],
|
|
384
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
384
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
385
385
|
localHead: e1_0.seqNum,
|
|
386
386
|
})
|
|
387
387
|
const result = merge({
|
|
@@ -402,7 +402,7 @@ describe('syncstate', () => {
|
|
|
402
402
|
it('should rebase all client events when incoming chain starts differently', () => {
|
|
403
403
|
const syncState = new SyncState.SyncState({
|
|
404
404
|
pending: [e1_0, e1_1],
|
|
405
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
405
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
406
406
|
localHead: e1_1.seqNum,
|
|
407
407
|
})
|
|
408
408
|
const result = merge({
|
|
@@ -426,7 +426,7 @@ describe('syncstate', () => {
|
|
|
426
426
|
it('should advance with new events', () => {
|
|
427
427
|
const syncState = new SyncState.SyncState({
|
|
428
428
|
pending: [e1_0],
|
|
429
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
429
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
430
430
|
localHead: e1_0.seqNum,
|
|
431
431
|
})
|
|
432
432
|
const result = merge({
|
|
@@ -436,7 +436,7 @@ describe('syncstate', () => {
|
|
|
436
436
|
|
|
437
437
|
expectAdvance(result)
|
|
438
438
|
expectEventArraysEqual(result.newSyncState.pending, [e1_0, e1_1, e1_2, e1_3])
|
|
439
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.ROOT)
|
|
439
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
|
|
440
440
|
expect(result.newSyncState.localHead).toMatchObject(e1_3.seqNum)
|
|
441
441
|
expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3])
|
|
442
442
|
expectEventArraysEqual(result.confirmedEvents, [])
|
|
@@ -447,8 +447,8 @@ describe('syncstate', () => {
|
|
|
447
447
|
it('keeps pending empty when pushing only client-only events that are being ignored', () => {
|
|
448
448
|
const syncState = new SyncState.SyncState({
|
|
449
449
|
pending: [],
|
|
450
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
451
|
-
localHead: EventSequenceNumber.ROOT,
|
|
450
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
451
|
+
localHead: EventSequenceNumber.Client.ROOT,
|
|
452
452
|
})
|
|
453
453
|
|
|
454
454
|
const result = merge({
|
|
@@ -459,16 +459,16 @@ describe('syncstate', () => {
|
|
|
459
459
|
|
|
460
460
|
expectAdvance(result)
|
|
461
461
|
expectEventArraysEqual(result.newSyncState.pending, [])
|
|
462
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.ROOT)
|
|
463
|
-
expect(result.newSyncState.localHead).toMatchObject(EventSequenceNumber.ROOT)
|
|
462
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
|
|
463
|
+
expect(result.newSyncState.localHead).toMatchObject(EventSequenceNumber.Client.ROOT)
|
|
464
464
|
expectEventArraysEqual(result.newEvents, [e0_1])
|
|
465
465
|
})
|
|
466
466
|
|
|
467
467
|
it('appends only upstream-bound events to pending when ignoring client-only pushes', () => {
|
|
468
468
|
const syncState = new SyncState.SyncState({
|
|
469
469
|
pending: [],
|
|
470
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
471
|
-
localHead: EventSequenceNumber.ROOT,
|
|
470
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
471
|
+
localHead: EventSequenceNumber.Client.ROOT,
|
|
472
472
|
})
|
|
473
473
|
|
|
474
474
|
const result = merge({
|
|
@@ -479,7 +479,7 @@ describe('syncstate', () => {
|
|
|
479
479
|
|
|
480
480
|
expectAdvance(result)
|
|
481
481
|
expectEventArraysEqual(result.newSyncState.pending, [e1_0])
|
|
482
|
-
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.ROOT)
|
|
482
|
+
expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
|
|
483
483
|
expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
|
|
484
484
|
expectEventArraysEqual(result.newEvents, [e0_1, e1_0])
|
|
485
485
|
})
|
|
@@ -489,7 +489,7 @@ describe('syncstate', () => {
|
|
|
489
489
|
it('should reject when new events are greater than pending events', () => {
|
|
490
490
|
const syncState = new SyncState.SyncState({
|
|
491
491
|
pending: [e1_0, e1_1],
|
|
492
|
-
upstreamHead: EventSequenceNumber.ROOT,
|
|
492
|
+
upstreamHead: EventSequenceNumber.Client.ROOT,
|
|
493
493
|
localHead: e1_1.seqNum,
|
|
494
494
|
})
|
|
495
495
|
const result = merge({
|
|
@@ -507,8 +507,8 @@ describe('syncstate', () => {
|
|
|
507
507
|
})
|
|
508
508
|
|
|
509
509
|
const expectEventArraysEqual = (
|
|
510
|
-
actual: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
|
511
|
-
expected: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
|
510
|
+
actual: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>,
|
|
511
|
+
expected: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>,
|
|
512
512
|
) => {
|
|
513
513
|
expect(actual.length).toBe(expected.length)
|
|
514
514
|
actual.forEach((event, i) => {
|
package/src/sync/syncstate.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { casesHandled, LS_DEV, shouldNeverHappen } from '@livestore/utils'
|
|
2
2
|
import { Match, ReadonlyArray, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
|
-
import * as EventSequenceNumber from '../schema/EventSequenceNumber.ts'
|
|
5
|
-
import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
|
|
4
|
+
import * as EventSequenceNumber from '../schema/EventSequenceNumber/mod.ts'
|
|
5
|
+
import * as LiveStoreEvent from '../schema/LiveStoreEvent/mod.ts'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* SyncState represents the current sync state of a sync node relative to an upstream node.
|
|
@@ -42,16 +42,16 @@ import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
|
|
|
42
42
|
* handling cases such as upstream rebase, advance and local push.
|
|
43
43
|
*/
|
|
44
44
|
export class SyncState extends Schema.Class<SyncState>('SyncState')({
|
|
45
|
-
pending: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
45
|
+
pending: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
46
46
|
/** What this node expects the next upstream node to have as its own local head */
|
|
47
|
-
upstreamHead: EventSequenceNumber.
|
|
47
|
+
upstreamHead: EventSequenceNumber.Client.Composite,
|
|
48
48
|
/** Equivalent to `pending.at(-1)?.id` if there are pending events */
|
|
49
|
-
localHead: EventSequenceNumber.
|
|
49
|
+
localHead: EventSequenceNumber.Client.Composite,
|
|
50
50
|
}) {
|
|
51
51
|
toJSON = (): any => ({
|
|
52
52
|
pending: this.pending.map((e) => e.toJSON()),
|
|
53
|
-
upstreamHead: EventSequenceNumber.toString(this.upstreamHead),
|
|
54
|
-
localHead: EventSequenceNumber.toString(this.localHead),
|
|
53
|
+
upstreamHead: EventSequenceNumber.Client.toString(this.upstreamHead),
|
|
54
|
+
localHead: EventSequenceNumber.Client.toString(this.localHead),
|
|
55
55
|
})
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -60,17 +60,17 @@ export class SyncState extends Schema.Class<SyncState>('SyncState')({
|
|
|
60
60
|
*/
|
|
61
61
|
export class PayloadUpstreamRebase extends Schema.TaggedStruct('upstream-rebase', {
|
|
62
62
|
/** Events which need to be rolled back */
|
|
63
|
-
rollbackEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
63
|
+
rollbackEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
64
64
|
/** Events which need to be applied after the rollback (already rebased by the upstream node) */
|
|
65
|
-
newEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
65
|
+
newEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
66
66
|
}) {}
|
|
67
67
|
|
|
68
68
|
export class PayloadUpstreamAdvance extends Schema.TaggedStruct('upstream-advance', {
|
|
69
|
-
newEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
69
|
+
newEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
70
70
|
}) {}
|
|
71
71
|
|
|
72
72
|
export class PayloadLocalPush extends Schema.TaggedStruct('local-push', {
|
|
73
|
-
newEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
73
|
+
newEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
74
74
|
}) {}
|
|
75
75
|
|
|
76
76
|
export class Payload extends Schema.Union(PayloadUpstreamRebase, PayloadUpstreamAdvance, PayloadLocalPush) {}
|
|
@@ -109,9 +109,9 @@ export class MergeContext extends Schema.Class<MergeContext>('MergeContext')({
|
|
|
109
109
|
export class MergeResultAdvance extends Schema.Class<MergeResultAdvance>('MergeResultAdvance')({
|
|
110
110
|
_tag: Schema.Literal('advance'),
|
|
111
111
|
newSyncState: SyncState,
|
|
112
|
-
newEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
112
|
+
newEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
113
113
|
/** Events which were previously pending but are now confirmed */
|
|
114
|
-
confirmedEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
114
|
+
confirmedEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
115
115
|
mergeContext: MergeContext,
|
|
116
116
|
}) {
|
|
117
117
|
toJSON = (): any => {
|
|
@@ -128,9 +128,9 @@ export class MergeResultAdvance extends Schema.Class<MergeResultAdvance>('MergeR
|
|
|
128
128
|
export class MergeResultRebase extends Schema.Class<MergeResultRebase>('MergeResultRebase')({
|
|
129
129
|
_tag: Schema.Literal('rebase'),
|
|
130
130
|
newSyncState: SyncState,
|
|
131
|
-
newEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
131
|
+
newEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
132
132
|
/** Events which need to be rolled back */
|
|
133
|
-
rollbackEvents: Schema.Array(LiveStoreEvent.EncodedWithMeta),
|
|
133
|
+
rollbackEvents: Schema.Array(LiveStoreEvent.Client.EncodedWithMeta),
|
|
134
134
|
mergeContext: MergeContext,
|
|
135
135
|
}) {
|
|
136
136
|
toJSON = (): any => {
|
|
@@ -147,20 +147,20 @@ export class MergeResultRebase extends Schema.Class<MergeResultRebase>('MergeRes
|
|
|
147
147
|
export class MergeResultReject extends Schema.Class<MergeResultReject>('MergeResultReject')({
|
|
148
148
|
_tag: Schema.Literal('reject'),
|
|
149
149
|
/** The minimum id that the new events must have */
|
|
150
|
-
expectedMinimumId: EventSequenceNumber.
|
|
150
|
+
expectedMinimumId: EventSequenceNumber.Client.Composite,
|
|
151
151
|
mergeContext: MergeContext,
|
|
152
152
|
}) {
|
|
153
153
|
toJSON = (): any => {
|
|
154
154
|
return {
|
|
155
155
|
_tag: this._tag,
|
|
156
|
-
expectedMinimumId: EventSequenceNumber.toString(this.expectedMinimumId),
|
|
156
|
+
expectedMinimumId: EventSequenceNumber.Client.toString(this.expectedMinimumId),
|
|
157
157
|
mergeContext: this.mergeContext.toJSON(),
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
export class
|
|
163
|
-
_tag: Schema.Literal('
|
|
162
|
+
export class MergeResultUnknownError extends Schema.Class<MergeResultUnknownError>('MergeResultUnknownError')({
|
|
163
|
+
_tag: Schema.Literal('unknown-error'),
|
|
164
164
|
message: Schema.String,
|
|
165
165
|
}) {}
|
|
166
166
|
|
|
@@ -168,7 +168,7 @@ export class MergeResult extends Schema.Union(
|
|
|
168
168
|
MergeResultAdvance,
|
|
169
169
|
MergeResultRebase,
|
|
170
170
|
MergeResultReject,
|
|
171
|
-
|
|
171
|
+
MergeResultUnknownError,
|
|
172
172
|
) {}
|
|
173
173
|
|
|
174
174
|
export const payloadFromMergeResult = (
|
|
@@ -187,13 +187,13 @@ export const payloadFromMergeResult = (
|
|
|
187
187
|
Match.exhaustive,
|
|
188
188
|
)
|
|
189
189
|
|
|
190
|
-
const
|
|
190
|
+
const unknownError = (message: string): MergeResultUnknownError => {
|
|
191
191
|
if (LS_DEV) {
|
|
192
192
|
// biome-ignore lint/suspicious/noDebugger: debug
|
|
193
193
|
debugger
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
return
|
|
196
|
+
return MergeResultUnknownError.make({ _tag: 'unknown-error', message })
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
// TODO Idea: call merge recursively through hierarchy levels
|
|
@@ -212,8 +212,8 @@ export const merge = ({
|
|
|
212
212
|
}: {
|
|
213
213
|
syncState: SyncState
|
|
214
214
|
payload: typeof Payload.Type
|
|
215
|
-
isClientEvent: (event: LiveStoreEvent.EncodedWithMeta) => boolean
|
|
216
|
-
isEqualEvent: (a: LiveStoreEvent.EncodedWithMeta, b: LiveStoreEvent.EncodedWithMeta) => boolean
|
|
215
|
+
isClientEvent: (event: LiveStoreEvent.Client.EncodedWithMeta) => boolean
|
|
216
|
+
isEqualEvent: (a: LiveStoreEvent.Client.EncodedWithMeta, b: LiveStoreEvent.Client.EncodedWithMeta) => boolean
|
|
217
217
|
/** This is used in the leader which should ignore client events when receiving an upstream-advance payload */
|
|
218
218
|
ignoreClientEvents?: boolean
|
|
219
219
|
}): typeof MergeResult.Type => {
|
|
@@ -271,20 +271,20 @@ export const merge = ({
|
|
|
271
271
|
|
|
272
272
|
// Validate that newEvents are sorted in ascending order by eventNum
|
|
273
273
|
for (let i = 1; i < payload.newEvents.length; i++) {
|
|
274
|
-
if (EventSequenceNumber.isGreaterThan(payload.newEvents[i - 1]!.seqNum, payload.newEvents[i]!.seqNum)) {
|
|
275
|
-
return
|
|
276
|
-
`Events must be sorted in ascending order by event number. Received: [${payload.newEvents.map((e) => EventSequenceNumber.toString(e.seqNum)).join(', ')}]`,
|
|
274
|
+
if (EventSequenceNumber.Client.isGreaterThan(payload.newEvents[i - 1]!.seqNum, payload.newEvents[i]!.seqNum)) {
|
|
275
|
+
return unknownError(
|
|
276
|
+
`Events must be sorted in ascending order by event number. Received: [${payload.newEvents.map((e) => EventSequenceNumber.Client.toString(e.seqNum)).join(', ')}]`,
|
|
277
277
|
)
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
// Validate that incoming events are larger than upstream head
|
|
282
282
|
if (
|
|
283
|
-
EventSequenceNumber.isGreaterThan(syncState.upstreamHead, payload.newEvents[0]!.seqNum) ||
|
|
284
|
-
EventSequenceNumber.isEqual(syncState.upstreamHead, payload.newEvents[0]!.seqNum)
|
|
283
|
+
EventSequenceNumber.Client.isGreaterThan(syncState.upstreamHead, payload.newEvents[0]!.seqNum) ||
|
|
284
|
+
EventSequenceNumber.Client.isEqual(syncState.upstreamHead, payload.newEvents[0]!.seqNum)
|
|
285
285
|
) {
|
|
286
|
-
return
|
|
287
|
-
`Incoming events must be greater than upstream head. Expected greater than: ${EventSequenceNumber.toString(syncState.upstreamHead)}. Received: [${payload.newEvents.map((e) => EventSequenceNumber.toString(e.seqNum)).join(', ')}]`,
|
|
286
|
+
return unknownError(
|
|
287
|
+
`Incoming events must be greater than upstream head. Expected greater than: ${EventSequenceNumber.Client.toString(syncState.upstreamHead)}. Received: [${payload.newEvents.map((e) => EventSequenceNumber.Client.toString(e.seqNum)).join(', ')}]`,
|
|
288
288
|
)
|
|
289
289
|
}
|
|
290
290
|
|
|
@@ -336,7 +336,7 @@ export const merge = ({
|
|
|
336
336
|
pending: pendingRemaining,
|
|
337
337
|
upstreamHead: newUpstreamHead,
|
|
338
338
|
localHead:
|
|
339
|
-
pendingRemaining.at(-1)?.seqNum ?? EventSequenceNumber.max(syncState.localHead, newUpstreamHead),
|
|
339
|
+
pendingRemaining.at(-1)?.seqNum ?? EventSequenceNumber.Client.max(syncState.localHead, newUpstreamHead),
|
|
340
340
|
}),
|
|
341
341
|
newEvents,
|
|
342
342
|
confirmedEvents: pendingMatching,
|
|
@@ -392,10 +392,10 @@ export const merge = ({
|
|
|
392
392
|
|
|
393
393
|
const newEventsFirst = payload.newEvents.at(0)!
|
|
394
394
|
const invalidEventSequenceNumber =
|
|
395
|
-
EventSequenceNumber.isGreaterThan(newEventsFirst.seqNum, syncState.localHead) === false
|
|
395
|
+
EventSequenceNumber.Client.isGreaterThan(newEventsFirst.seqNum, syncState.localHead) === false
|
|
396
396
|
|
|
397
397
|
if (invalidEventSequenceNumber) {
|
|
398
|
-
const expectedMinimumId = EventSequenceNumber.nextPair({
|
|
398
|
+
const expectedMinimumId = EventSequenceNumber.Client.nextPair({
|
|
399
399
|
seqNum: syncState.localHead,
|
|
400
400
|
isClient: true,
|
|
401
401
|
}).seqNum
|
|
@@ -412,7 +412,7 @@ export const merge = ({
|
|
|
412
412
|
: payload.newEvents
|
|
413
413
|
const newPending = [...syncState.pending, ...nonClientEvents]
|
|
414
414
|
const newLocalHead =
|
|
415
|
-
newPending.at(-1)?.seqNum ?? EventSequenceNumber.max(syncState.localHead, syncState.upstreamHead)
|
|
415
|
+
newPending.at(-1)?.seqNum ?? EventSequenceNumber.Client.max(syncState.localHead, syncState.upstreamHead)
|
|
416
416
|
|
|
417
417
|
return validateMergeResult(
|
|
418
418
|
MergeResultAdvance.make({
|
|
@@ -447,10 +447,10 @@ export const findDivergencePoint = ({
|
|
|
447
447
|
isClientEvent,
|
|
448
448
|
ignoreClientEvents,
|
|
449
449
|
}: {
|
|
450
|
-
existingEvents: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>
|
|
451
|
-
incomingEvents: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>
|
|
452
|
-
isEqualEvent: (a: LiveStoreEvent.EncodedWithMeta, b: LiveStoreEvent.EncodedWithMeta) => boolean
|
|
453
|
-
isClientEvent: (event: LiveStoreEvent.EncodedWithMeta) => boolean
|
|
450
|
+
existingEvents: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>
|
|
451
|
+
incomingEvents: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>
|
|
452
|
+
isEqualEvent: (a: LiveStoreEvent.Client.EncodedWithMeta, b: LiveStoreEvent.Client.EncodedWithMeta) => boolean
|
|
453
|
+
isClientEvent: (event: LiveStoreEvent.Client.EncodedWithMeta) => boolean
|
|
454
454
|
ignoreClientEvents: boolean
|
|
455
455
|
}): number => {
|
|
456
456
|
if (ignoreClientEvents) {
|
|
@@ -468,7 +468,7 @@ export const findDivergencePoint = ({
|
|
|
468
468
|
const divergencePointEventSequenceNumber = existingEvents[divergencePointWithoutClientEvents]!.seqNum
|
|
469
469
|
// Now find the divergence point in the original array
|
|
470
470
|
return existingEvents.findIndex((event) =>
|
|
471
|
-
EventSequenceNumber.isEqual(event.seqNum, divergencePointEventSequenceNumber),
|
|
471
|
+
EventSequenceNumber.Client.isEqual(event.seqNum, divergencePointEventSequenceNumber),
|
|
472
472
|
)
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -484,10 +484,10 @@ const rebaseEvents = ({
|
|
|
484
484
|
baseEventSequenceNumber,
|
|
485
485
|
isClientEvent,
|
|
486
486
|
}: {
|
|
487
|
-
events: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>
|
|
488
|
-
baseEventSequenceNumber: EventSequenceNumber.
|
|
489
|
-
isClientEvent: (event: LiveStoreEvent.EncodedWithMeta) => boolean
|
|
490
|
-
}): ReadonlyArray<LiveStoreEvent.EncodedWithMeta> => {
|
|
487
|
+
events: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>
|
|
488
|
+
baseEventSequenceNumber: EventSequenceNumber.Client.Composite
|
|
489
|
+
isClientEvent: (event: LiveStoreEvent.Client.EncodedWithMeta) => boolean
|
|
490
|
+
}): ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta> => {
|
|
491
491
|
let prevEventSequenceNumber = baseEventSequenceNumber
|
|
492
492
|
const rebaseGeneration = baseEventSequenceNumber.rebaseGeneration + 1
|
|
493
493
|
return events.map((event) => {
|
|
@@ -513,9 +513,11 @@ const _flattenMergeResults = (_updateResults: ReadonlyArray<MergeResult>) => {}
|
|
|
513
513
|
|
|
514
514
|
const validatePayload = (payload: typeof Payload.Type) => {
|
|
515
515
|
for (let i = 1; i < payload.newEvents.length; i++) {
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
|
|
516
|
+
if (
|
|
517
|
+
EventSequenceNumber.Client.isGreaterThanOrEqual(payload.newEvents[i - 1]!.seqNum, payload.newEvents[i]!.seqNum)
|
|
518
|
+
) {
|
|
519
|
+
return unknownError(
|
|
520
|
+
`Events must be ordered in monotonically ascending order by eventNum. Received: [${payload.newEvents.map((e) => EventSequenceNumber.Client.toString(e.seqNum)).join(', ')}]`,
|
|
519
521
|
)
|
|
520
522
|
}
|
|
521
523
|
}
|
|
@@ -527,9 +529,9 @@ const validateSyncState = (syncState: SyncState) => {
|
|
|
527
529
|
const nextEvent = syncState.pending[i + 1]
|
|
528
530
|
if (nextEvent === undefined) break // Reached end of chain
|
|
529
531
|
|
|
530
|
-
if (EventSequenceNumber.isGreaterThanOrEqual(event.seqNum, nextEvent.seqNum)) {
|
|
532
|
+
if (EventSequenceNumber.Client.isGreaterThanOrEqual(event.seqNum, nextEvent.seqNum)) {
|
|
531
533
|
shouldNeverHappen(
|
|
532
|
-
`Events must be ordered in monotonically ascending order by eventNum. Received: [${syncState.pending.map((e) => EventSequenceNumber.toString(e.seqNum)).join(', ')}]`,
|
|
534
|
+
`Events must be ordered in monotonically ascending order by eventNum. Received: [${syncState.pending.map((e) => EventSequenceNumber.Client.toString(e.seqNum)).join(', ')}]`,
|
|
533
535
|
{
|
|
534
536
|
event,
|
|
535
537
|
nextEvent,
|
|
@@ -542,7 +544,7 @@ const validateSyncState = (syncState: SyncState) => {
|
|
|
542
544
|
if (globalIdHasIncreased) {
|
|
543
545
|
if (nextEvent.seqNum.client !== 0) {
|
|
544
546
|
shouldNeverHappen(
|
|
545
|
-
`New global events must point to clientId 0 in the parentSeqNum. Received: (${EventSequenceNumber.toString(nextEvent.seqNum)})`,
|
|
547
|
+
`New global events must point to clientId 0 in the parentSeqNum. Received: (${EventSequenceNumber.Client.toString(nextEvent.seqNum)})`,
|
|
546
548
|
syncState.pending,
|
|
547
549
|
{
|
|
548
550
|
event,
|
|
@@ -552,7 +554,7 @@ const validateSyncState = (syncState: SyncState) => {
|
|
|
552
554
|
}
|
|
553
555
|
} else {
|
|
554
556
|
// Otherwise, the parentSeqNum must be the same as the previous event's id
|
|
555
|
-
if (EventSequenceNumber.isEqual(nextEvent.parentSeqNum, event.seqNum) === false) {
|
|
557
|
+
if (EventSequenceNumber.Client.isEqual(nextEvent.parentSeqNum, event.seqNum) === false) {
|
|
556
558
|
shouldNeverHappen('Events must be linked in a continuous chain via the parentSeqNum', syncState.pending, {
|
|
557
559
|
event,
|
|
558
560
|
nextEvent,
|
|
@@ -563,12 +565,14 @@ const validateSyncState = (syncState: SyncState) => {
|
|
|
563
565
|
}
|
|
564
566
|
|
|
565
567
|
const validateMergeResult = (mergeResult: typeof MergeResult.Type) => {
|
|
566
|
-
if (mergeResult._tag === '
|
|
568
|
+
if (mergeResult._tag === 'unknown-error' || mergeResult._tag === 'reject') return mergeResult
|
|
567
569
|
|
|
568
570
|
validateSyncState(mergeResult.newSyncState)
|
|
569
571
|
|
|
570
572
|
// Ensure local head is always greater than or equal to upstream head
|
|
571
|
-
if (
|
|
573
|
+
if (
|
|
574
|
+
EventSequenceNumber.Client.isGreaterThan(mergeResult.newSyncState.upstreamHead, mergeResult.newSyncState.localHead)
|
|
575
|
+
) {
|
|
572
576
|
shouldNeverHappen('Local head must be greater than or equal to upstream head', {
|
|
573
577
|
localHead: mergeResult.newSyncState.localHead,
|
|
574
578
|
upstreamHead: mergeResult.newSyncState.upstreamHead,
|
|
@@ -577,7 +581,7 @@ const validateMergeResult = (mergeResult: typeof MergeResult.Type) => {
|
|
|
577
581
|
|
|
578
582
|
// Ensure new local head is greater than or equal to the previous local head
|
|
579
583
|
if (
|
|
580
|
-
EventSequenceNumber.isGreaterThanOrEqual(
|
|
584
|
+
EventSequenceNumber.Client.isGreaterThanOrEqual(
|
|
581
585
|
mergeResult.newSyncState.localHead,
|
|
582
586
|
mergeResult.mergeContext.syncState.localHead,
|
|
583
587
|
) === false
|
|
@@ -590,7 +594,7 @@ const validateMergeResult = (mergeResult: typeof MergeResult.Type) => {
|
|
|
590
594
|
|
|
591
595
|
// Ensure new upstream head is greater than or equal to the previous upstream head
|
|
592
596
|
if (
|
|
593
|
-
EventSequenceNumber.isGreaterThanOrEqual(
|
|
597
|
+
EventSequenceNumber.Client.isGreaterThanOrEqual(
|
|
594
598
|
mergeResult.newSyncState.upstreamHead,
|
|
595
599
|
mergeResult.mergeContext.syncState.upstreamHead,
|
|
596
600
|
) === false
|
|
@@ -5,15 +5,15 @@ import { InvalidPushError, ServerAheadError } from './sync.ts'
|
|
|
5
5
|
|
|
6
6
|
// TODO proper batch validation
|
|
7
7
|
export const validatePushPayload = (
|
|
8
|
-
batch: ReadonlyArray<LiveStoreEvent.
|
|
9
|
-
currentEventSequenceNumber: EventSequenceNumber.
|
|
8
|
+
batch: ReadonlyArray<LiveStoreEvent.Global.Encoded>,
|
|
9
|
+
currentEventSequenceNumber: EventSequenceNumber.Global.Type,
|
|
10
10
|
) =>
|
|
11
11
|
Effect.gen(function* () {
|
|
12
12
|
if (batch[0]!.seqNum <= currentEventSequenceNumber) {
|
|
13
13
|
return yield* InvalidPushError.make({
|
|
14
14
|
cause: new ServerAheadError({
|
|
15
|
-
minimumExpectedNum: EventSequenceNumber.
|
|
16
|
-
providedNum: EventSequenceNumber.
|
|
15
|
+
minimumExpectedNum: EventSequenceNumber.Global.make(currentEventSequenceNumber + 1),
|
|
16
|
+
providedNum: EventSequenceNumber.Global.make(batch[0]!.seqNum),
|
|
17
17
|
}),
|
|
18
18
|
})
|
|
19
19
|
}
|