@livestore/common 0.0.0-snapshot-2b8a9de3ec1a701aca891ebc2c98eb328274ae9e → 0.0.0-snapshot-2c861249e50661661613204300b1fc0d902c2e46
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/__tests__/fixture.d.ts +83 -221
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +33 -11
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/adapter-types.d.ts +36 -22
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +20 -8
- package/dist/adapter-types.js.map +1 -1
- package/dist/debug-info.d.ts.map +1 -1
- package/dist/debug-info.js +1 -0
- package/dist/debug-info.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 +46 -46
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +12 -13
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -5
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +34 -12
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +284 -226
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/apply-event.d.ts +16 -0
- package/dist/leader-thread/apply-event.d.ts.map +1 -0
- package/dist/leader-thread/apply-event.js +122 -0
- package/dist/leader-thread/apply-event.js.map +1 -0
- package/dist/leader-thread/eventlog.d.ts +27 -0
- package/dist/leader-thread/eventlog.d.ts.map +1 -0
- package/dist/leader-thread/eventlog.js +123 -0
- package/dist/leader-thread/eventlog.js.map +1 -0
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +22 -23
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +16 -4
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +36 -41
- 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/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +7 -7
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +40 -25
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/materializer-helper.d.ts +23 -0
- package/dist/materializer-helper.d.ts.map +1 -0
- package/dist/materializer-helper.js +70 -0
- package/dist/materializer-helper.js.map +1 -0
- package/dist/query-builder/api.d.ts +55 -50
- package/dist/query-builder/api.d.ts.map +1 -1
- package/dist/query-builder/api.js +3 -5
- package/dist/query-builder/api.js.map +1 -1
- package/dist/query-builder/astToSql.d.ts.map +1 -1
- package/dist/query-builder/astToSql.js +59 -37
- package/dist/query-builder/astToSql.js.map +1 -1
- package/dist/query-builder/impl.d.ts +2 -3
- package/dist/query-builder/impl.d.ts.map +1 -1
- package/dist/query-builder/impl.js +47 -43
- package/dist/query-builder/impl.js.map +1 -1
- package/dist/query-builder/impl.test.d.ts +86 -1
- package/dist/query-builder/impl.test.d.ts.map +1 -1
- package/dist/query-builder/impl.test.js +223 -36
- package/dist/query-builder/impl.test.js.map +1 -1
- package/dist/rehydrate-from-eventlog.d.ts +15 -0
- package/dist/rehydrate-from-eventlog.d.ts.map +1 -0
- package/dist/{rehydrate-from-mutationlog.js → rehydrate-from-eventlog.js} +27 -28
- package/dist/rehydrate-from-eventlog.js.map +1 -0
- package/dist/schema/EventDef.d.ts +136 -0
- package/dist/schema/EventDef.d.ts.map +1 -0
- package/dist/schema/EventDef.js +58 -0
- package/dist/schema/EventDef.js.map +1 -0
- package/dist/schema/EventId.d.ts +10 -1
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +24 -3
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/LiveStoreEvent.d.ts +255 -0
- package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent.js +118 -0
- package/dist/schema/LiveStoreEvent.js.map +1 -0
- package/dist/schema/client-document-def.d.ts +223 -0
- package/dist/schema/client-document-def.d.ts.map +1 -0
- package/dist/schema/client-document-def.js +164 -0
- package/dist/schema/client-document-def.js.map +1 -0
- package/dist/schema/client-document-def.test.d.ts +2 -0
- package/dist/schema/client-document-def.test.d.ts.map +1 -0
- package/dist/schema/client-document-def.test.js +161 -0
- package/dist/schema/client-document-def.test.js.map +1 -0
- package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/events.d.ts +2 -0
- package/dist/schema/events.d.ts.map +1 -0
- package/dist/schema/events.js +2 -0
- package/dist/schema/events.js.map +1 -0
- package/dist/schema/mod.d.ts +4 -3
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +4 -3
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts +26 -22
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +45 -43
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/sqlite-state.d.ts +12 -0
- package/dist/schema/sqlite-state.d.ts.map +1 -0
- package/dist/schema/sqlite-state.js +36 -0
- package/dist/schema/sqlite-state.js.map +1 -0
- package/dist/schema/system-tables.d.ts +121 -85
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +68 -43
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/schema/table-def.d.ts +26 -96
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js +14 -64
- package/dist/schema/table-def.js.map +1 -1
- package/dist/schema/view.d.ts +3 -0
- package/dist/schema/view.d.ts.map +1 -0
- package/dist/schema/view.js +3 -0
- package/dist/schema/view.js.map +1 -0
- package/dist/schema-management/common.d.ts +4 -4
- package/dist/schema-management/common.d.ts.map +1 -1
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +6 -6
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/validate-mutation-defs.d.ts +3 -3
- package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
- package/dist/schema-management/validate-mutation-defs.js +17 -17
- package/dist/schema-management/validate-mutation-defs.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +16 -8
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +50 -43
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/next/facts.d.ts +19 -19
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +2 -2
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +3 -3
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +1 -1
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.js +1 -1
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +7 -7
- 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/compact-events.calculator.test.js +38 -33
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +71 -71
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +25 -25
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
- package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +60 -25
- package/dist/sync/next/test/event-fixtures.js.map +1 -0
- package/dist/sync/next/test/mod.d.ts +1 -1
- package/dist/sync/next/test/mod.d.ts.map +1 -1
- package/dist/sync/next/test/mod.js +1 -1
- package/dist/sync/next/test/mod.js.map +1 -1
- package/dist/sync/sync.d.ts +8 -7
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +69 -93
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +143 -146
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +208 -289
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/validate-push-payload.d.ts +2 -2
- package/dist/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/__tests__/fixture.ts +36 -15
- package/src/adapter-types.ts +34 -23
- package/src/debug-info.ts +1 -0
- package/src/devtools/devtools-messages-common.ts +9 -0
- package/src/devtools/devtools-messages-leader.ts +14 -15
- package/src/index.ts +2 -5
- package/src/leader-thread/LeaderSyncProcessor.ts +485 -389
- package/src/leader-thread/apply-event.ts +197 -0
- package/src/leader-thread/eventlog.ts +199 -0
- package/src/leader-thread/leader-worker-devtools.ts +23 -25
- package/src/leader-thread/make-leader-thread-layer.ts +68 -61
- package/src/leader-thread/mod.ts +1 -1
- package/src/leader-thread/recreate-db.ts +7 -8
- package/src/leader-thread/types.ts +39 -29
- package/src/materializer-helper.ts +110 -0
- package/src/query-builder/api.ts +76 -102
- package/src/query-builder/astToSql.ts +68 -39
- package/src/query-builder/impl.test.ts +239 -42
- package/src/query-builder/impl.ts +66 -54
- package/src/{rehydrate-from-mutationlog.ts → rehydrate-from-eventlog.ts} +37 -40
- package/src/schema/EventDef.ts +216 -0
- package/src/schema/EventId.ts +30 -4
- package/src/schema/LiveStoreEvent.ts +239 -0
- package/src/schema/client-document-def.test.ts +188 -0
- package/src/schema/client-document-def.ts +436 -0
- package/src/schema/db-schema/dsl/mod.ts +0 -1
- package/src/schema/events.ts +1 -0
- package/src/schema/mod.ts +4 -3
- package/src/schema/schema.ts +78 -68
- package/src/schema/sqlite-state.ts +62 -0
- package/src/schema/system-tables.ts +54 -46
- package/src/schema/table-def.ts +51 -209
- package/src/schema/view.ts +2 -0
- package/src/schema-management/common.ts +4 -4
- package/src/schema-management/migrations.ts +8 -9
- package/src/schema-management/validate-mutation-defs.ts +22 -24
- package/src/sync/ClientSessionSyncProcessor.ts +66 -53
- package/src/sync/next/facts.ts +31 -32
- package/src/sync/next/history-dag-common.ts +4 -4
- package/src/sync/next/history-dag.ts +1 -1
- package/src/sync/next/rebase-events.ts +13 -13
- package/src/sync/next/test/compact-events.calculator.test.ts +45 -45
- package/src/sync/next/test/compact-events.test.ts +73 -73
- package/src/sync/next/test/event-fixtures.ts +219 -0
- package/src/sync/next/test/mod.ts +1 -1
- package/src/sync/sync.ts +9 -12
- package/src/sync/syncstate.test.ts +236 -323
- package/src/sync/syncstate.ts +218 -203
- package/src/sync/validate-push-payload.ts +2 -2
- package/src/version.ts +1 -1
- package/tsconfig.json +1 -0
- package/dist/derived-mutations.d.ts +0 -109
- package/dist/derived-mutations.d.ts.map +0 -1
- package/dist/derived-mutations.js +0 -54
- package/dist/derived-mutations.js.map +0 -1
- package/dist/derived-mutations.test.d.ts +0 -2
- package/dist/derived-mutations.test.d.ts.map +0 -1
- package/dist/derived-mutations.test.js +0 -93
- package/dist/derived-mutations.test.js.map +0 -1
- package/dist/init-singleton-tables.d.ts +0 -4
- package/dist/init-singleton-tables.d.ts.map +0 -1
- package/dist/init-singleton-tables.js +0 -16
- package/dist/init-singleton-tables.js.map +0 -1
- package/dist/leader-thread/apply-mutation.d.ts +0 -11
- package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
- package/dist/leader-thread/apply-mutation.js +0 -115
- package/dist/leader-thread/apply-mutation.js.map +0 -1
- package/dist/leader-thread/mutationlog.d.ts +0 -11
- package/dist/leader-thread/mutationlog.d.ts.map +0 -1
- package/dist/leader-thread/mutationlog.js +0 -31
- package/dist/leader-thread/mutationlog.js.map +0 -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/dist/mutation.d.ts +0 -20
- package/dist/mutation.d.ts.map +0 -1
- package/dist/mutation.js +0 -68
- package/dist/mutation.js.map +0 -1
- package/dist/query-info.d.ts +0 -41
- package/dist/query-info.d.ts.map +0 -1
- package/dist/query-info.js +0 -7
- package/dist/query-info.js.map +0 -1
- package/dist/rehydrate-from-mutationlog.d.ts +0 -14
- package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
- package/dist/rehydrate-from-mutationlog.js.map +0 -1
- package/dist/schema/MutationEvent.d.ts +0 -202
- package/dist/schema/MutationEvent.d.ts.map +0 -1
- package/dist/schema/MutationEvent.js +0 -105
- package/dist/schema/MutationEvent.js.map +0 -1
- package/dist/schema/mutations.d.ts +0 -115
- package/dist/schema/mutations.d.ts.map +0 -1
- package/dist/schema/mutations.js +0 -42
- package/dist/schema/mutations.js.map +0 -1
- package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
- package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
- package/src/derived-mutations.test.ts +0 -101
- package/src/derived-mutations.ts +0 -170
- package/src/init-singleton-tables.ts +0 -24
- package/src/leader-thread/apply-mutation.ts +0 -187
- package/src/leader-thread/mutationlog.ts +0 -49
- package/src/leader-thread/pull-queue-set.ts +0 -67
- package/src/mutation.ts +0 -108
- package/src/query-info.ts +0 -83
- package/src/schema/MutationEvent.ts +0 -224
- package/src/schema/mutations.ts +0 -193
- package/src/sync/next/test/mutation-fixtures.ts +0 -228
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
1
2
|
import { LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
|
|
2
3
|
import type { Runtime, Scope } from '@livestore/utils/effect'
|
|
3
4
|
import { BucketQueue, Effect, FiberHandle, Queue, Schema, Stream, Subscribable } from '@livestore/utils/effect'
|
|
@@ -5,16 +6,17 @@ import * as otel from '@opentelemetry/api'
|
|
|
5
6
|
|
|
6
7
|
import type { ClientSession, UnexpectedError } from '../adapter-types.js'
|
|
7
8
|
import * as EventId from '../schema/EventId.js'
|
|
8
|
-
import
|
|
9
|
-
import
|
|
9
|
+
import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
|
|
10
|
+
import { getEventDef, LEADER_MERGE_COUNTER_TABLE, type LiveStoreSchema } from '../schema/mod.js'
|
|
11
|
+
import { sql } from '../util.js'
|
|
10
12
|
import * as SyncState from './syncstate.js'
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Rebase behaviour:
|
|
14
|
-
* - We continously pull
|
|
16
|
+
* - We continously pull events from the leader and apply them to the local store.
|
|
15
17
|
* - If there was a race condition (i.e. the leader and client session have both advacned),
|
|
16
|
-
* we'll need to rebase the local pending
|
|
17
|
-
* - The goal is to never block the UI, so we'll interrupt rebasing if a new
|
|
18
|
+
* we'll need to rebase the local pending events on top of the leader's head.
|
|
19
|
+
* - The goal is to never block the UI, so we'll interrupt rebasing if a new events is pushed by the client session.
|
|
18
20
|
* - We also want to avoid "backwards-jumping" in the UI, so we'll transactionally apply a read model changes during a rebase.
|
|
19
21
|
* - We might need to make the rebase behaviour configurable e.g. to let users manually trigger a rebase
|
|
20
22
|
*
|
|
@@ -24,7 +26,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
24
26
|
schema,
|
|
25
27
|
clientSession,
|
|
26
28
|
runtime,
|
|
27
|
-
|
|
29
|
+
applyEvent,
|
|
28
30
|
rollback,
|
|
29
31
|
refreshTables,
|
|
30
32
|
span,
|
|
@@ -34,12 +36,12 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
34
36
|
schema: LiveStoreSchema
|
|
35
37
|
clientSession: ClientSession
|
|
36
38
|
runtime: Runtime.Runtime<Scope.Scope>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
applyEvent: (
|
|
40
|
+
eventDecoded: LiveStoreEvent.PartialAnyDecoded,
|
|
39
41
|
options: { otelContext: otel.Context; withChangeset: boolean },
|
|
40
42
|
) => {
|
|
41
43
|
writeTables: Set<string>
|
|
42
|
-
sessionChangeset: Uint8Array |
|
|
44
|
+
sessionChangeset: { _tag: 'sessionChangeset'; data: Uint8Array; debug: any } | { _tag: 'no-op' } | { _tag: 'unset' }
|
|
43
45
|
}
|
|
44
46
|
rollback: (changeset: Uint8Array) => void
|
|
45
47
|
refreshTables: (tables: Set<string>) => void
|
|
@@ -53,36 +55,37 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
53
55
|
*/
|
|
54
56
|
confirmUnsavedChanges: boolean
|
|
55
57
|
}): ClientSessionSyncProcessor => {
|
|
56
|
-
const
|
|
58
|
+
const eventSchema = LiveStoreEvent.makeEventDefSchemaMemo(schema)
|
|
57
59
|
|
|
58
60
|
const syncStateRef = {
|
|
61
|
+
// The initial state is identical to the leader's initial state
|
|
59
62
|
current: new SyncState.SyncState({
|
|
60
63
|
localHead: clientSession.leaderThread.initialState.leaderHead,
|
|
61
64
|
upstreamHead: clientSession.leaderThread.initialState.leaderHead,
|
|
65
|
+
// Given we're starting with the leader's snapshot, we don't have any pending events intially
|
|
62
66
|
pending: [],
|
|
63
|
-
// TODO init rollbackTail from leader to be ready for backend rebasing
|
|
64
|
-
rollbackTail: [],
|
|
65
67
|
}),
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
const syncStateUpdateQueue = Queue.unbounded<SyncState.SyncState>().pipe(Effect.runSync)
|
|
69
|
-
const isClientEvent = (
|
|
70
|
-
|
|
71
|
+
const isClientEvent = (eventEncoded: LiveStoreEvent.EncodedWithMeta) =>
|
|
72
|
+
getEventDef(schema, eventEncoded.name).eventDef.options.clientOnly
|
|
71
73
|
|
|
72
74
|
/** We're queuing push requests to reduce the number of messages sent to the leader by batching them */
|
|
73
|
-
const leaderPushQueue = BucketQueue.make<
|
|
75
|
+
const leaderPushQueue = BucketQueue.make<LiveStoreEvent.EncodedWithMeta>().pipe(Effect.runSync)
|
|
74
76
|
|
|
75
77
|
const push: ClientSessionSyncProcessor['push'] = (batch, { otelContext }) => {
|
|
76
78
|
// TODO validate batch
|
|
77
79
|
|
|
78
80
|
let baseEventId = syncStateRef.current.localHead
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const nextIdPair = EventId.nextPair(baseEventId,
|
|
81
|
+
const encodedEventDefs = batch.map(({ name, args }) => {
|
|
82
|
+
const eventDef = getEventDef(schema, name)
|
|
83
|
+
const nextIdPair = EventId.nextPair(baseEventId, eventDef.eventDef.options.clientOnly)
|
|
82
84
|
baseEventId = nextIdPair.id
|
|
83
|
-
return new
|
|
84
|
-
Schema.encodeUnknownSync(
|
|
85
|
-
|
|
85
|
+
return new LiveStoreEvent.EncodedWithMeta(
|
|
86
|
+
Schema.encodeUnknownSync(eventSchema)({
|
|
87
|
+
name,
|
|
88
|
+
args,
|
|
86
89
|
...nextIdPair,
|
|
87
90
|
clientId: clientSession.clientId,
|
|
88
91
|
sessionId: clientSession.sessionId,
|
|
@@ -92,9 +95,9 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
92
95
|
|
|
93
96
|
const mergeResult = SyncState.merge({
|
|
94
97
|
syncState: syncStateRef.current,
|
|
95
|
-
payload: { _tag: 'local-push', newEvents:
|
|
98
|
+
payload: { _tag: 'local-push', newEvents: encodedEventDefs },
|
|
96
99
|
isClientEvent,
|
|
97
|
-
isEqualEvent:
|
|
100
|
+
isEqualEvent: LiveStoreEvent.isEqualEncoded,
|
|
98
101
|
})
|
|
99
102
|
|
|
100
103
|
if (mergeResult._tag === 'unexpected-error') {
|
|
@@ -102,7 +105,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
span.addEvent('local-push', {
|
|
105
|
-
batchSize:
|
|
108
|
+
batchSize: encodedEventDefs.length,
|
|
106
109
|
mergeResult: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
|
|
107
110
|
})
|
|
108
111
|
|
|
@@ -114,18 +117,18 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
114
117
|
syncStateUpdateQueue.offer(mergeResult.newSyncState).pipe(Effect.runSync)
|
|
115
118
|
|
|
116
119
|
const writeTables = new Set<string>()
|
|
117
|
-
for (const
|
|
120
|
+
for (const event of mergeResult.newEvents) {
|
|
118
121
|
// TODO avoid encoding and decoding here again
|
|
119
|
-
const
|
|
120
|
-
const res =
|
|
122
|
+
const decodedEventDef = Schema.decodeSync(eventSchema)(event)
|
|
123
|
+
const res = applyEvent(decodedEventDef, { otelContext, withChangeset: true })
|
|
121
124
|
for (const table of res.writeTables) {
|
|
122
125
|
writeTables.add(table)
|
|
123
126
|
}
|
|
124
|
-
|
|
127
|
+
event.meta.sessionChangeset = res.sessionChangeset
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
// console.debug('pushToLeader',
|
|
128
|
-
BucketQueue.offerAll(leaderPushQueue,
|
|
130
|
+
// console.debug('pushToLeader', encodedEventDefs.length, ...encodedEventDefs.map((_) => _.toJSON()))
|
|
131
|
+
BucketQueue.offerAll(leaderPushQueue, encodedEventDefs).pipe(Effect.runSync)
|
|
129
132
|
|
|
130
133
|
return { writeTables }
|
|
131
134
|
}
|
|
@@ -158,7 +161,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
158
161
|
|
|
159
162
|
const backgroundLeaderPushing = Effect.gen(function* () {
|
|
160
163
|
const batch = yield* BucketQueue.takeBetween(leaderPushQueue, 1, params.leaderPushBatchSize)
|
|
161
|
-
yield* clientSession.leaderThread.
|
|
164
|
+
yield* clientSession.leaderThread.events.push(batch).pipe(
|
|
162
165
|
Effect.catchTag('LeaderAheadError', () => {
|
|
163
166
|
debugInfo.rejectCount++
|
|
164
167
|
return BucketQueue.clear(leaderPushQueue)
|
|
@@ -168,13 +171,21 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
168
171
|
|
|
169
172
|
yield* FiberHandle.run(leaderPushingFiberHandle, backgroundLeaderPushing)
|
|
170
173
|
|
|
174
|
+
const getMergeCounter = () =>
|
|
175
|
+
clientSession.sqliteDb.select<{ mergeCounter: number }>(
|
|
176
|
+
sql`SELECT mergeCounter FROM ${LEADER_MERGE_COUNTER_TABLE} WHERE id = 0`,
|
|
177
|
+
)[0]?.mergeCounter ?? 0
|
|
178
|
+
|
|
171
179
|
// NOTE We need to lazily call `.pull` as we want the cursor to be updated
|
|
172
180
|
yield* Stream.suspend(() =>
|
|
173
|
-
clientSession.leaderThread.
|
|
181
|
+
clientSession.leaderThread.events.pull({
|
|
182
|
+
cursor: { mergeCounter: getMergeCounter(), eventId: syncStateRef.current.localHead },
|
|
183
|
+
}),
|
|
174
184
|
).pipe(
|
|
175
|
-
Stream.tap(({ payload,
|
|
185
|
+
Stream.tap(({ payload, mergeCounter: leaderMergeCounter }) =>
|
|
176
186
|
Effect.gen(function* () {
|
|
177
|
-
//
|
|
187
|
+
// yield* Effect.logDebug('ClientSessionSyncProcessor:pull', payload)
|
|
188
|
+
|
|
178
189
|
if (clientSession.devtools.enabled) {
|
|
179
190
|
yield* clientSession.devtools.pullLatch.await
|
|
180
191
|
}
|
|
@@ -183,7 +194,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
183
194
|
syncState: syncStateRef.current,
|
|
184
195
|
payload,
|
|
185
196
|
isClientEvent,
|
|
186
|
-
isEqualEvent:
|
|
197
|
+
isEqualEvent: LiveStoreEvent.isEqualEncoded,
|
|
187
198
|
})
|
|
188
199
|
|
|
189
200
|
if (mergeResult._tag === 'unexpected-error') {
|
|
@@ -196,13 +207,13 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
196
207
|
syncStateUpdateQueue.offer(mergeResult.newSyncState).pipe(Effect.runSync)
|
|
197
208
|
|
|
198
209
|
if (mergeResult._tag === 'rebase') {
|
|
199
|
-
span.addEvent('pull:rebase', {
|
|
210
|
+
span.addEvent('merge:pull:rebase', {
|
|
200
211
|
payloadTag: payload._tag,
|
|
201
212
|
payload: TRACE_VERBOSE ? JSON.stringify(payload) : undefined,
|
|
202
213
|
newEventsCount: mergeResult.newEvents.length,
|
|
203
|
-
rollbackCount: mergeResult.
|
|
214
|
+
rollbackCount: mergeResult.rollbackEvents.length,
|
|
204
215
|
res: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
|
|
205
|
-
|
|
216
|
+
leaderMergeCounter,
|
|
206
217
|
})
|
|
207
218
|
|
|
208
219
|
debugInfo.rebaseCount++
|
|
@@ -216,28 +227,29 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
216
227
|
|
|
217
228
|
if (LS_DEV) {
|
|
218
229
|
Effect.logDebug(
|
|
219
|
-
'pull:rebase: rollback',
|
|
220
|
-
mergeResult.
|
|
221
|
-
...mergeResult.
|
|
230
|
+
'merge:pull:rebase: rollback',
|
|
231
|
+
mergeResult.rollbackEvents.length,
|
|
232
|
+
...mergeResult.rollbackEvents.slice(0, 10).map((_) => _.toJSON()),
|
|
233
|
+
{ leaderMergeCounter },
|
|
222
234
|
).pipe(Effect.provide(runtime), Effect.runSync)
|
|
223
235
|
}
|
|
224
236
|
|
|
225
|
-
for (let i = mergeResult.
|
|
226
|
-
const event = mergeResult.
|
|
227
|
-
if (event.meta.sessionChangeset) {
|
|
228
|
-
rollback(event.meta.sessionChangeset)
|
|
229
|
-
event.meta.sessionChangeset =
|
|
237
|
+
for (let i = mergeResult.rollbackEvents.length - 1; i >= 0; i--) {
|
|
238
|
+
const event = mergeResult.rollbackEvents[i]!
|
|
239
|
+
if (event.meta.sessionChangeset._tag !== 'no-op' && event.meta.sessionChangeset._tag !== 'unset') {
|
|
240
|
+
rollback(event.meta.sessionChangeset.data)
|
|
241
|
+
event.meta.sessionChangeset = { _tag: 'unset' }
|
|
230
242
|
}
|
|
231
243
|
}
|
|
232
244
|
|
|
233
245
|
yield* BucketQueue.offerAll(leaderPushQueue, mergeResult.newSyncState.pending)
|
|
234
246
|
} else {
|
|
235
|
-
span.addEvent('pull:advance', {
|
|
247
|
+
span.addEvent('merge:pull:advance', {
|
|
236
248
|
payloadTag: payload._tag,
|
|
237
249
|
payload: TRACE_VERBOSE ? JSON.stringify(payload) : undefined,
|
|
238
250
|
newEventsCount: mergeResult.newEvents.length,
|
|
239
251
|
res: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
|
|
240
|
-
|
|
252
|
+
leaderMergeCounter,
|
|
241
253
|
})
|
|
242
254
|
|
|
243
255
|
debugInfo.advanceCount++
|
|
@@ -246,14 +258,15 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
246
258
|
if (mergeResult.newEvents.length === 0) return
|
|
247
259
|
|
|
248
260
|
const writeTables = new Set<string>()
|
|
249
|
-
for (const
|
|
250
|
-
|
|
251
|
-
const
|
|
261
|
+
for (const event of mergeResult.newEvents) {
|
|
262
|
+
// TODO apply changeset if available (will require tracking of write tables as well)
|
|
263
|
+
const decodedEventDef = Schema.decodeSync(eventSchema)(event)
|
|
264
|
+
const res = applyEvent(decodedEventDef, { otelContext, withChangeset: true })
|
|
252
265
|
for (const table of res.writeTables) {
|
|
253
266
|
writeTables.add(table)
|
|
254
267
|
}
|
|
255
268
|
|
|
256
|
-
|
|
269
|
+
event.meta.sessionChangeset = res.sessionChangeset
|
|
257
270
|
}
|
|
258
271
|
|
|
259
272
|
refreshTables(writeTables)
|
|
@@ -302,7 +315,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
302
315
|
|
|
303
316
|
export interface ClientSessionSyncProcessor {
|
|
304
317
|
push: (
|
|
305
|
-
batch: ReadonlyArray<
|
|
318
|
+
batch: ReadonlyArray<LiveStoreEvent.PartialAnyDecoded>,
|
|
306
319
|
options: { otelContext: otel.Context },
|
|
307
320
|
) => {
|
|
308
321
|
writeTables: Set<string>
|
package/src/sync/next/facts.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { notYetImplemented } from '@livestore/utils'
|
|
2
2
|
|
|
3
|
-
import type * as EventId from '../../schema/EventId.js'
|
|
4
3
|
import type {
|
|
4
|
+
EventDefFactInput,
|
|
5
|
+
EventDefFacts,
|
|
6
|
+
EventDefFactsGroup,
|
|
7
|
+
EventDefFactsSnapshot,
|
|
5
8
|
FactsCallback,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
MutationEventFactsGroup,
|
|
9
|
-
MutationEventFactsSnapshot,
|
|
10
|
-
} from '../../schema/mutations.js'
|
|
9
|
+
} from '../../schema/EventDef.js'
|
|
10
|
+
import type * as EventId from '../../schema/EventId.js'
|
|
11
11
|
import { graphologyDag } from './graphology_.js'
|
|
12
12
|
import { EMPTY_FACT_VALUE, type HistoryDag, type HistoryDagNode } from './history-dag-common.js'
|
|
13
13
|
|
|
14
14
|
export const factsSnapshotForEvents = (
|
|
15
15
|
events: HistoryDagNode[],
|
|
16
16
|
endEventId: EventId.EventId,
|
|
17
|
-
):
|
|
17
|
+
): EventDefFactsSnapshot => {
|
|
18
18
|
const facts = new Map<string, any>()
|
|
19
19
|
|
|
20
20
|
for (const event of events) {
|
|
@@ -31,7 +31,7 @@ export const factsSnapshotForEvents = (
|
|
|
31
31
|
export const factsSnapshotForDag = (
|
|
32
32
|
dag: HistoryDag,
|
|
33
33
|
endEventId: EventId.EventId | undefined,
|
|
34
|
-
):
|
|
34
|
+
): EventDefFactsSnapshot => {
|
|
35
35
|
const facts = new Map<string, any>()
|
|
36
36
|
|
|
37
37
|
const orderedEventIdStrs = graphologyDag.topologicalSort(dag)
|
|
@@ -56,20 +56,20 @@ export type FactValidationResult =
|
|
|
56
56
|
success: false
|
|
57
57
|
/** Index of the item that caused the validation to fail */
|
|
58
58
|
index: number
|
|
59
|
-
requiredFacts:
|
|
59
|
+
requiredFacts: EventDefFacts
|
|
60
60
|
mismatch: {
|
|
61
|
-
existing:
|
|
62
|
-
required:
|
|
61
|
+
existing: EventDefFacts
|
|
62
|
+
required: EventDefFacts
|
|
63
63
|
}
|
|
64
|
-
currentSnapshot:
|
|
64
|
+
currentSnapshot: EventDefFacts
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export const validateFacts = ({
|
|
68
68
|
factGroups,
|
|
69
69
|
initialSnapshot,
|
|
70
70
|
}: {
|
|
71
|
-
factGroups:
|
|
72
|
-
initialSnapshot:
|
|
71
|
+
factGroups: EventDefFactsGroup[]
|
|
72
|
+
initialSnapshot: EventDefFactsSnapshot
|
|
73
73
|
}): FactValidationResult => {
|
|
74
74
|
const currentSnapshot = new Map(initialSnapshot)
|
|
75
75
|
|
|
@@ -102,13 +102,13 @@ export const validateFacts = ({
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
export const applyFactGroups = (factGroups:
|
|
105
|
+
export const applyFactGroups = (factGroups: EventDefFactsGroup[], snapshot: EventDefFactsSnapshot) => {
|
|
106
106
|
for (const factGroup of factGroups) {
|
|
107
107
|
applyFactGroup(factGroup, snapshot)
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
export const applyFactGroup = (factGroup:
|
|
111
|
+
export const applyFactGroup = (factGroup: EventDefFactsGroup, snapshot: EventDefFactsSnapshot) => {
|
|
112
112
|
for (const [key, value] of factGroup.modifySet) {
|
|
113
113
|
snapshot.set(key, value)
|
|
114
114
|
}
|
|
@@ -119,7 +119,7 @@ export const applyFactGroup = (factGroup: MutationEventFactsGroup, snapshot: Mut
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/** Check if setA is a subset of setB */
|
|
122
|
-
const isSubSetMapByValue = (setA:
|
|
122
|
+
const isSubSetMapByValue = (setA: EventDefFacts, setB: EventDefFacts) => {
|
|
123
123
|
for (const [key, value] of setA) {
|
|
124
124
|
if (setB.get(key) !== value) {
|
|
125
125
|
return false
|
|
@@ -129,7 +129,7 @@ const isSubSetMapByValue = (setA: MutationEventFacts, setB: MutationEventFacts)
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/** Check if setA is a subset of setB */
|
|
132
|
-
const isSubSetMapByKey = (setA:
|
|
132
|
+
const isSubSetMapByKey = (setA: EventDefFacts, setB: EventDefFacts) => {
|
|
133
133
|
for (const [key, _value] of setA) {
|
|
134
134
|
if (!setB.has(key)) {
|
|
135
135
|
return false
|
|
@@ -139,17 +139,16 @@ const isSubSetMapByKey = (setA: MutationEventFacts, setB: MutationEventFacts) =>
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
/** Check if groupA depends on groupB */
|
|
142
|
-
export const dependsOn = (groupA:
|
|
142
|
+
export const dependsOn = (groupA: EventDefFactsGroup, groupB: EventDefFactsGroup): boolean =>
|
|
143
143
|
factsIntersect(groupA.depRead, groupB.modifySet) ||
|
|
144
144
|
factsIntersect(groupA.depRead, groupB.modifyUnset) ||
|
|
145
145
|
factsIntersect(groupA.depRequire, groupB.modifySet) ||
|
|
146
146
|
factsIntersect(groupA.depRequire, groupB.modifyUnset)
|
|
147
147
|
|
|
148
|
-
export const replacesFacts = (groupA:
|
|
149
|
-
const replaces = (a:
|
|
148
|
+
export const replacesFacts = (groupA: EventDefFactsGroup, groupB: EventDefFactsGroup): boolean => {
|
|
149
|
+
const replaces = (a: EventDefFacts, b: EventDefFacts) => a.size > 0 && b.size > 0 && isSameMapByKey(a, b)
|
|
150
150
|
|
|
151
|
-
const noFactsOrSame = (a:
|
|
152
|
-
a.size === 0 || b.size === 0 || isSameMapByKey(a, b)
|
|
151
|
+
const noFactsOrSame = (a: EventDefFacts, b: EventDefFacts) => a.size === 0 || b.size === 0 || isSameMapByKey(a, b)
|
|
153
152
|
|
|
154
153
|
return (
|
|
155
154
|
(replaces(groupA.modifySet, groupB.modifySet) && noFactsOrSame(groupA.modifyUnset, groupB.modifyUnset)) ||
|
|
@@ -159,16 +158,16 @@ export const replacesFacts = (groupA: MutationEventFactsGroup, groupB: MutationE
|
|
|
159
158
|
)
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
export const isSameMapByKey = (set:
|
|
161
|
+
export const isSameMapByKey = (set: EventDefFacts, otherSet: EventDefFacts) =>
|
|
163
162
|
set.size === otherSet.size && isSubSetMapByKey(set, otherSet)
|
|
164
163
|
|
|
165
|
-
export const factsToString = (facts:
|
|
164
|
+
export const factsToString = (facts: EventDefFacts) => {
|
|
166
165
|
return Array.from(facts)
|
|
167
166
|
.map(([key, value]) => (value === EMPTY_FACT_VALUE ? key : `${key}=${value}`))
|
|
168
167
|
.join(', ')
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
export const factsIntersect = (setA:
|
|
170
|
+
export const factsIntersect = (setA: EventDefFacts, setB: EventDefFacts): boolean => {
|
|
172
171
|
for (const [key, _value] of setA) {
|
|
173
172
|
if (setB.has(key)) {
|
|
174
173
|
return true
|
|
@@ -177,16 +176,16 @@ export const factsIntersect = (setA: MutationEventFacts, setB: MutationEventFact
|
|
|
177
176
|
return false
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
export const
|
|
179
|
+
export const getFactsGroupForEventArgs = ({
|
|
181
180
|
factsCallback,
|
|
182
181
|
args,
|
|
183
182
|
currentFacts,
|
|
184
183
|
}: {
|
|
185
184
|
factsCallback: FactsCallback<any> | undefined
|
|
186
185
|
args: any
|
|
187
|
-
currentFacts:
|
|
188
|
-
}):
|
|
189
|
-
const depRead:
|
|
186
|
+
currentFacts: EventDefFactsSnapshot
|
|
187
|
+
}): EventDefFactsGroup => {
|
|
188
|
+
const depRead: EventDefFactsSnapshot = new Map<string, any>()
|
|
190
189
|
const factsSnapshotProxy = new Proxy(currentFacts, {
|
|
191
190
|
get: (target, prop) => {
|
|
192
191
|
if (prop === 'has') {
|
|
@@ -201,12 +200,12 @@ export const getFactsGroupForMutationArgs = ({
|
|
|
201
200
|
}
|
|
202
201
|
}
|
|
203
202
|
|
|
204
|
-
notYetImplemented(`
|
|
203
|
+
notYetImplemented(`getFactsGroupForEventArgs: ${prop.toString()} is not yet implemented`)
|
|
205
204
|
},
|
|
206
205
|
})
|
|
207
206
|
|
|
208
207
|
const factsRes = factsCallback?.(args, factsSnapshotProxy)
|
|
209
|
-
const iterableToMap = (iterable: Iterable<
|
|
208
|
+
const iterableToMap = (iterable: Iterable<EventDefFactInput>) => {
|
|
210
209
|
const map = new Map()
|
|
211
210
|
for (const item of iterable) {
|
|
212
211
|
if (typeof item === 'string') {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { EventDefFactsGroup } from '../../schema/EventDef.js'
|
|
1
2
|
import * as EventId from '../../schema/EventId.js'
|
|
2
|
-
import type { MutationEventFactsGroup } from '../../schema/mutations.js'
|
|
3
3
|
import { graphology } from './graphology_.js'
|
|
4
4
|
|
|
5
5
|
export const connectionTypeOptions = ['parent', 'facts'] as const
|
|
@@ -25,10 +25,10 @@ export const rootParentId = EventId.make({ global: EventId.ROOT.global - 1, clie
|
|
|
25
25
|
export type HistoryDagNode = {
|
|
26
26
|
id: EventId.EventId
|
|
27
27
|
parentId: EventId.EventId
|
|
28
|
-
|
|
28
|
+
name: string
|
|
29
29
|
args: any
|
|
30
30
|
/** Facts are being used for conflict detection and history compaction */
|
|
31
|
-
factsGroup:
|
|
31
|
+
factsGroup: EventDefFactsGroup
|
|
32
32
|
meta?: any
|
|
33
33
|
clientId: string
|
|
34
34
|
sessionId: string | undefined
|
|
@@ -38,7 +38,7 @@ export const rootEventNode: HistoryDagNode = {
|
|
|
38
38
|
id: EventId.ROOT,
|
|
39
39
|
parentId: rootParentId,
|
|
40
40
|
// unused below
|
|
41
|
-
|
|
41
|
+
name: '__Root__',
|
|
42
42
|
args: {},
|
|
43
43
|
factsGroup: { modifySet: new Map(), modifyUnset: new Map(), depRequire: new Map(), depRead: new Map() },
|
|
44
44
|
clientId: 'root',
|
|
@@ -14,7 +14,7 @@ export const historyDagFromNodes = (dagNodes: HistoryDagNode[], options?: { skip
|
|
|
14
14
|
|
|
15
15
|
if (validationResult.success === false) {
|
|
16
16
|
throw new Error(
|
|
17
|
-
`
|
|
17
|
+
`Event ${dagNodes[validationResult.index]!.name} requires facts that have not been set yet.\nRequires: ${factsToString(validationResult.requiredFacts)}\nFacts Snapshot: ${factsToString(validationResult.currentSnapshot)}`,
|
|
18
18
|
)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import type { EventDef, EventDefFactsSnapshot } from '../../schema/EventDef.js'
|
|
1
2
|
import * as EventId from '../../schema/EventId.js'
|
|
2
|
-
import type * as
|
|
3
|
-
import type { MutationDef, MutationEventFactsSnapshot } from '../../schema/mutations.js'
|
|
3
|
+
import type * as LiveStoreEvent from '../../schema/LiveStoreEvent.js'
|
|
4
4
|
import {
|
|
5
5
|
applyFactGroups,
|
|
6
6
|
factsIntersect,
|
|
7
7
|
type FactValidationResult,
|
|
8
|
-
|
|
8
|
+
getFactsGroupForEventArgs,
|
|
9
9
|
validateFacts,
|
|
10
10
|
} from './facts.js'
|
|
11
11
|
import type { HistoryDagNode } from './history-dag-common.js'
|
|
@@ -19,13 +19,13 @@ export type RebaseInput = {
|
|
|
19
19
|
newRemoteEvents: RebaseEventWithConflict[]
|
|
20
20
|
pendingLocalEvents: RebaseEventWithConflict[]
|
|
21
21
|
validate: (args: {
|
|
22
|
-
rebasedLocalEvents:
|
|
23
|
-
|
|
22
|
+
rebasedLocalEvents: LiveStoreEvent.PartialAnyDecoded[]
|
|
23
|
+
eventDefs: Record<string, EventDef.Any>
|
|
24
24
|
}) => FactValidationResult
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export type RebaseOutput = {
|
|
28
|
-
rebasedLocalEvents:
|
|
28
|
+
rebasedLocalEvents: LiveStoreEvent.PartialAnyDecoded[]
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export type RebaseFn = (input: RebaseInput) => RebaseOutput
|
|
@@ -49,10 +49,10 @@ export const rebaseEvents = ({
|
|
|
49
49
|
pendingLocalEvents: HistoryDagNode[]
|
|
50
50
|
newRemoteEvents: HistoryDagNode[]
|
|
51
51
|
rebaseFn: RebaseFn
|
|
52
|
-
currentFactsSnapshot:
|
|
52
|
+
currentFactsSnapshot: EventDefFactsSnapshot
|
|
53
53
|
clientId: string
|
|
54
54
|
sessionId: string
|
|
55
|
-
}): ReadonlyArray<
|
|
55
|
+
}): ReadonlyArray<LiveStoreEvent.AnyDecoded> => {
|
|
56
56
|
const initialSnapshot = new Map(currentFactsSnapshot)
|
|
57
57
|
applyFactGroups(
|
|
58
58
|
newRemoteEvents.map((event) => event.factsGroup),
|
|
@@ -76,11 +76,11 @@ export const rebaseEvents = ({
|
|
|
76
76
|
factsIntersect(pending.factsGroup.modifySet, remote.factsGroup.modifySet),
|
|
77
77
|
),
|
|
78
78
|
})),
|
|
79
|
-
validate: ({ rebasedLocalEvents,
|
|
79
|
+
validate: ({ rebasedLocalEvents, eventDefs }) =>
|
|
80
80
|
validateFacts({
|
|
81
81
|
factGroups: rebasedLocalEvents.map((event) =>
|
|
82
|
-
|
|
83
|
-
factsCallback:
|
|
82
|
+
getFactsGroupForEventArgs({
|
|
83
|
+
factsCallback: eventDefs[event.name]!.options.facts,
|
|
84
84
|
args: event.args,
|
|
85
85
|
currentFacts: new Map(),
|
|
86
86
|
}),
|
|
@@ -95,10 +95,10 @@ export const rebaseEvents = ({
|
|
|
95
95
|
({
|
|
96
96
|
id: EventId.make({ global: headGlobalId + index + 1, client: EventId.clientDefault }),
|
|
97
97
|
parentId: EventId.make({ global: headGlobalId + index, client: EventId.clientDefault }),
|
|
98
|
-
|
|
98
|
+
name: event.name,
|
|
99
99
|
args: event.args,
|
|
100
100
|
clientId,
|
|
101
101
|
sessionId,
|
|
102
|
-
}) satisfies
|
|
102
|
+
}) satisfies LiveStoreEvent.AnyDecoded,
|
|
103
103
|
)
|
|
104
104
|
}
|