@livestore/common 0.3.0-dev.28 → 0.3.0-dev.29
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 +22 -15
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +15 -2
- package/dist/adapter-types.js.map +1 -1
- package/dist/bounded-collections.d.ts +1 -1
- package/dist/bounded-collections.d.ts.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 +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +45 -45
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +11 -11
- 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 +10 -10
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +63 -65
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/{apply-mutation.d.ts → apply-event.d.ts} +7 -7
- package/dist/leader-thread/apply-event.d.ts.map +1 -0
- package/dist/leader-thread/apply-event.js +103 -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.js +18 -18
- 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 +16 -16
- 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 +6 -8
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +11 -11
- package/dist/leader-thread/types.d.ts.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 +58 -53
- 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 +48 -46
- 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 +244 -36
- package/dist/query-builder/impl.test.js.map +1 -1
- package/dist/rehydrate-from-eventlog.d.ts +14 -0
- package/dist/rehydrate-from-eventlog.d.ts.map +1 -0
- package/dist/{rehydrate-from-mutationlog.js → rehydrate-from-eventlog.js} +25 -26
- 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 +2 -2
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +3 -2
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/{MutationEvent.d.ts → LiveStoreEvent.d.ts} +56 -56
- package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
- package/dist/schema/{MutationEvent.js → LiveStoreEvent.js} +24 -24
- 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 +170 -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 +201 -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 +27 -23
- 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 +67 -98
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +62 -48
- 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 +16 -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 +7 -7
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +31 -30
- 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} +29 -29
- 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 +3 -3
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/syncstate.d.ts +32 -32
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +10 -10
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +5 -5
- 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 +3 -3
- package/src/__tests__/fixture.ts +36 -15
- package/src/adapter-types.ts +23 -16
- package/src/debug-info.ts +1 -0
- package/src/devtools/devtools-messages-leader.ts +13 -13
- package/src/index.ts +2 -5
- package/src/leader-thread/LeaderSyncProcessor.ts +81 -91
- package/src/leader-thread/{apply-mutation.ts → apply-event.ts} +50 -74
- package/src/leader-thread/eventlog.ts +199 -0
- package/src/leader-thread/leader-worker-devtools.ts +18 -18
- package/src/leader-thread/make-leader-thread-layer.ts +18 -18
- package/src/leader-thread/mod.ts +1 -1
- package/src/leader-thread/recreate-db.ts +6 -9
- package/src/leader-thread/types.ts +12 -12
- package/src/materializer-helper.ts +110 -0
- package/src/query-builder/api.ts +79 -105
- package/src/query-builder/astToSql.ts +68 -39
- package/src/query-builder/impl.test.ts +264 -42
- package/src/query-builder/impl.ts +72 -56
- package/src/{rehydrate-from-mutationlog.ts → rehydrate-from-eventlog.ts} +33 -40
- package/src/schema/EventDef.ts +216 -0
- package/src/schema/EventId.ts +5 -3
- package/src/schema/{MutationEvent.ts → LiveStoreEvent.ts} +67 -68
- package/src/schema/client-document-def.test.ts +239 -0
- package/src/schema/client-document-def.ts +444 -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 +79 -69
- package/src/schema/sqlite-state.ts +62 -0
- package/src/schema/system-tables.ts +42 -53
- package/src/schema/table-def.ts +53 -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 +37 -36
- 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 +3 -3
- package/src/sync/syncstate.test.ts +8 -8
- package/src/sync/syncstate.ts +19 -19
- package/src/sync/validate-push-payload.ts +2 -2
- package/src/version.ts +1 -1
- package/tmp/pack.tgz +0 -0
- 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.map +0 -1
- package/dist/leader-thread/apply-mutation.js +0 -122
- package/dist/leader-thread/apply-mutation.js.map +0 -1
- package/dist/leader-thread/mutationlog.d.ts +0 -27
- package/dist/leader-thread/mutationlog.d.ts.map +0 -1
- package/dist/leader-thread/mutationlog.js +0 -124
- 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 -38
- 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 -15
- 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.map +0 -1
- 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/mutationlog.ts +0 -202
- package/src/mutation.ts +0 -108
- package/src/query-info.ts +0 -83
- package/src/schema/mutations.ts +0 -193
- package/src/sync/next/test/mutation-fixtures.ts +0 -228
@@ -20,36 +20,36 @@ import { UnexpectedError } from '../adapter-types.js'
|
|
20
20
|
import type { LiveStoreSchema } from '../schema/mod.js'
|
21
21
|
import {
|
22
22
|
EventId,
|
23
|
-
|
23
|
+
getEventDef,
|
24
24
|
LEADER_MERGE_COUNTER_TABLE,
|
25
|
-
|
25
|
+
LiveStoreEvent,
|
26
26
|
SESSION_CHANGESET_META_TABLE,
|
27
27
|
} from '../schema/mod.js'
|
28
28
|
import { LeaderAheadError } from '../sync/sync.js'
|
29
29
|
import * as SyncState from '../sync/syncstate.js'
|
30
30
|
import { sql } from '../util.js'
|
31
|
-
import { rollback } from './apply-
|
32
|
-
import * as
|
31
|
+
import { rollback } from './apply-event.js'
|
32
|
+
import * as Eventlog from './eventlog.js'
|
33
33
|
import type { InitialBlockingSyncContext, LeaderSyncProcessor } from './types.js'
|
34
34
|
import { LeaderThreadCtx } from './types.js'
|
35
35
|
|
36
36
|
type LocalPushQueueItem = [
|
37
|
-
|
37
|
+
event: LiveStoreEvent.EncodedWithMeta,
|
38
38
|
deferred: Deferred.Deferred<void, LeaderAheadError> | undefined,
|
39
39
|
/** Used to determine whether the batch has become invalid due to a rejected local push batch */
|
40
40
|
generation: number,
|
41
41
|
]
|
42
42
|
|
43
43
|
/**
|
44
|
-
* The LeaderSyncProcessor manages synchronization of
|
44
|
+
* The LeaderSyncProcessor manages synchronization of events between
|
45
45
|
* the local state and the sync backend, ensuring efficient and orderly processing.
|
46
46
|
*
|
47
47
|
* In the LeaderSyncProcessor, pulling always has precedence over pushing.
|
48
48
|
*
|
49
49
|
* Responsibilities:
|
50
|
-
* - Queueing incoming local
|
51
|
-
* - Broadcasting
|
52
|
-
* - Pushing
|
50
|
+
* - Queueing incoming local events in a localPushesQueue.
|
51
|
+
* - Broadcasting events to client sessions via pull queues.
|
52
|
+
* - Pushing events to the sync backend.
|
53
53
|
*
|
54
54
|
* Notes:
|
55
55
|
*
|
@@ -57,12 +57,12 @@ type LocalPushQueueItem = [
|
|
57
57
|
* - localPushesQueue:
|
58
58
|
* - Maintains events in ascending order.
|
59
59
|
* - Uses `Deferred` objects to resolve/reject events based on application success.
|
60
|
-
* - Processes events from the queue, applying
|
60
|
+
* - Processes events from the queue, applying events in batches.
|
61
61
|
* - Controlled by a `Latch` to manage execution flow.
|
62
62
|
* - The latch closes on pull receipt and re-opens post-pull completion.
|
63
63
|
* - Processes up to `maxBatchSize` events per cycle.
|
64
64
|
*
|
65
|
-
* Currently we're advancing the db read model and
|
65
|
+
* Currently we're advancing the db read model and eventlog in lockstep, but we could also decouple this in the future
|
66
66
|
*
|
67
67
|
* Tricky concurrency scenarios:
|
68
68
|
* - Queued local push batches becoming invalid due to a prior local push item being rejected.
|
@@ -71,8 +71,8 @@ type LocalPushQueueItem = [
|
|
71
71
|
*/
|
72
72
|
export const makeLeaderSyncProcessor = ({
|
73
73
|
schema,
|
74
|
-
|
75
|
-
|
74
|
+
dbEventlogMissing,
|
75
|
+
dbEventlog,
|
76
76
|
dbReadModel,
|
77
77
|
dbReadModelMissing,
|
78
78
|
initialBlockingSyncContext,
|
@@ -81,9 +81,9 @@ export const makeLeaderSyncProcessor = ({
|
|
81
81
|
testing,
|
82
82
|
}: {
|
83
83
|
schema: LiveStoreSchema
|
84
|
-
/** Only used to know whether we can safely query
|
85
|
-
|
86
|
-
|
84
|
+
/** Only used to know whether we can safely query dbEventlog during setup execution */
|
85
|
+
dbEventlogMissing: boolean
|
86
|
+
dbEventlog: SqliteDb
|
87
87
|
dbReadModel: SqliteDb
|
88
88
|
/** Only used to know whether we can safely query dbReadModel during setup execution */
|
89
89
|
dbReadModelMissing: boolean
|
@@ -106,15 +106,15 @@ export const makeLeaderSyncProcessor = ({
|
|
106
106
|
}
|
107
107
|
}): Effect.Effect<LeaderSyncProcessor, UnexpectedError, Scope.Scope> =>
|
108
108
|
Effect.gen(function* () {
|
109
|
-
const syncBackendPushQueue = yield* BucketQueue.make<
|
109
|
+
const syncBackendPushQueue = yield* BucketQueue.make<LiveStoreEvent.EncodedWithMeta>()
|
110
110
|
const localPushBatchSize = params.localPushBatchSize ?? 10
|
111
111
|
const backendPushBatchSize = params.backendPushBatchSize ?? 50
|
112
112
|
|
113
113
|
const syncStateSref = yield* SubscriptionRef.make<SyncState.SyncState | undefined>(undefined)
|
114
114
|
|
115
|
-
const isClientEvent = (
|
116
|
-
const
|
117
|
-
return
|
115
|
+
const isClientEvent = (eventEncoded: LiveStoreEvent.EncodedWithMeta) => {
|
116
|
+
const eventDef = getEventDef(schema, eventEncoded.name)
|
117
|
+
return eventDef.eventDef.options.clientOnly
|
118
118
|
}
|
119
119
|
|
120
120
|
const connectedClientSessionPullQueues = yield* makePullQueueSet
|
@@ -177,16 +177,14 @@ export const makeLeaderSyncProcessor = ({
|
|
177
177
|
const deferreds = yield* Effect.forEach(newEvents, () => Deferred.make<void, LeaderAheadError>())
|
178
178
|
|
179
179
|
const items = newEvents.map(
|
180
|
-
(
|
180
|
+
(eventEncoded, i) => [eventEncoded, deferreds[i], generation] as LocalPushQueueItem,
|
181
181
|
)
|
182
182
|
|
183
183
|
yield* BucketQueue.offerAll(localPushesQueue, items)
|
184
184
|
|
185
185
|
yield* Effect.all(deferreds)
|
186
186
|
} else {
|
187
|
-
const items = newEvents.map(
|
188
|
-
(mutationEventEncoded) => [mutationEventEncoded, undefined, generation] as LocalPushQueueItem,
|
189
|
-
)
|
187
|
+
const items = newEvents.map((eventEncoded) => [eventEncoded, undefined, generation] as LocalPushQueueItem)
|
190
188
|
yield* BucketQueue.offerAll(localPushesQueue, items)
|
191
189
|
}
|
192
190
|
}).pipe(
|
@@ -199,26 +197,22 @@ export const makeLeaderSyncProcessor = ({
|
|
199
197
|
}),
|
200
198
|
)
|
201
199
|
|
202
|
-
const pushPartial: LeaderSyncProcessor['pushPartial'] = ({
|
203
|
-
mutationEvent: { mutation, args },
|
204
|
-
clientId,
|
205
|
-
sessionId,
|
206
|
-
}) =>
|
200
|
+
const pushPartial: LeaderSyncProcessor['pushPartial'] = ({ event: { name, args }, clientId, sessionId }) =>
|
207
201
|
Effect.gen(function* () {
|
208
202
|
const syncState = yield* syncStateSref
|
209
203
|
if (syncState === undefined) return shouldNeverHappen('Not initialized')
|
210
204
|
|
211
|
-
const
|
205
|
+
const eventDef = getEventDef(schema, name)
|
212
206
|
|
213
|
-
const
|
214
|
-
|
207
|
+
const eventEncoded = new LiveStoreEvent.EncodedWithMeta({
|
208
|
+
name,
|
215
209
|
args,
|
216
210
|
clientId,
|
217
211
|
sessionId,
|
218
|
-
...EventId.nextPair(syncState.localHead,
|
212
|
+
...EventId.nextPair(syncState.localHead, eventDef.eventDef.options.clientOnly),
|
219
213
|
})
|
220
214
|
|
221
|
-
yield* push([
|
215
|
+
yield* push([eventEncoded])
|
222
216
|
}).pipe(Effect.catchTag('LeaderAheadError', Effect.orDie))
|
223
217
|
|
224
218
|
// Starts various background loops
|
@@ -235,11 +229,9 @@ export const makeLeaderSyncProcessor = ({
|
|
235
229
|
runtime,
|
236
230
|
}
|
237
231
|
|
238
|
-
const initialLocalHead =
|
232
|
+
const initialLocalHead = dbEventlogMissing ? EventId.ROOT : Eventlog.getClientHeadFromDb(dbEventlog)
|
239
233
|
|
240
|
-
const initialBackendHead =
|
241
|
-
? EventId.ROOT.global
|
242
|
-
: Mutationlog.getBackendHeadFromDb(dbMutationLog)
|
234
|
+
const initialBackendHead = dbEventlogMissing ? EventId.ROOT.global : Eventlog.getBackendHeadFromDb(dbEventlog)
|
243
235
|
|
244
236
|
if (initialBackendHead > initialLocalHead.global) {
|
245
237
|
return shouldNeverHappen(
|
@@ -247,12 +239,12 @@ export const makeLeaderSyncProcessor = ({
|
|
247
239
|
)
|
248
240
|
}
|
249
241
|
|
250
|
-
const
|
242
|
+
const pendingEvents = dbEventlogMissing
|
251
243
|
? []
|
252
|
-
: yield*
|
244
|
+
: yield* Eventlog.getEventsSince({ global: initialBackendHead, client: EventId.clientDefault })
|
253
245
|
|
254
246
|
const initialSyncState = new SyncState.SyncState({
|
255
|
-
pending:
|
247
|
+
pending: pendingEvents,
|
256
248
|
upstreamHead: { global: initialBackendHead, client: EventId.clientDefault },
|
257
249
|
localHead: initialLocalHead,
|
258
250
|
})
|
@@ -261,16 +253,16 @@ export const makeLeaderSyncProcessor = ({
|
|
261
253
|
yield* SubscriptionRef.set(syncStateSref, initialSyncState)
|
262
254
|
|
263
255
|
// Rehydrate sync queue
|
264
|
-
if (
|
265
|
-
const
|
266
|
-
// Don't sync clientOnly
|
267
|
-
.filter((
|
268
|
-
const
|
269
|
-
return
|
256
|
+
if (pendingEvents.length > 0) {
|
257
|
+
const globalPendingEvents = pendingEvents
|
258
|
+
// Don't sync clientOnly events
|
259
|
+
.filter((eventEncoded) => {
|
260
|
+
const eventDef = getEventDef(schema, eventEncoded.name)
|
261
|
+
return eventDef.eventDef.options.clientOnly === false
|
270
262
|
})
|
271
263
|
|
272
|
-
if (
|
273
|
-
yield* BucketQueue.offerAll(syncBackendPushQueue,
|
264
|
+
if (globalPendingEvents.length > 0) {
|
265
|
+
yield* BucketQueue.offerAll(syncBackendPushQueue, globalPendingEvents)
|
274
266
|
}
|
275
267
|
}
|
276
268
|
|
@@ -360,8 +352,8 @@ export const makeLeaderSyncProcessor = ({
|
|
360
352
|
return {
|
361
353
|
payload: {
|
362
354
|
_tag: 'upstream-advance' as const,
|
363
|
-
newEvents: ReadonlyArray.dropWhile(payload.newEvents, (
|
364
|
-
EventId.isGreaterThanOrEqual(cursor.eventId,
|
355
|
+
newEvents: ReadonlyArray.dropWhile(payload.newEvents, (eventEncoded) =>
|
356
|
+
EventId.isGreaterThanOrEqual(cursor.eventId, eventEncoded.id),
|
365
357
|
),
|
366
358
|
},
|
367
359
|
mergeCounter,
|
@@ -417,9 +409,9 @@ const backgroundApplyLocalPushes = ({
|
|
417
409
|
localPushesLatch: Effect.Latch
|
418
410
|
localPushesQueue: BucketQueue.BucketQueue<LocalPushQueueItem>
|
419
411
|
syncStateSref: SubscriptionRef.SubscriptionRef<SyncState.SyncState | undefined>
|
420
|
-
syncBackendPushQueue: BucketQueue.BucketQueue<
|
412
|
+
syncBackendPushQueue: BucketQueue.BucketQueue<LiveStoreEvent.EncodedWithMeta>
|
421
413
|
schema: LiveStoreSchema
|
422
|
-
isClientEvent: (
|
414
|
+
isClientEvent: (eventEncoded: LiveStoreEvent.EncodedWithMeta) => boolean
|
423
415
|
otelSpan: otel.Span | undefined
|
424
416
|
currentLocalPushGenerationRef: { current: number }
|
425
417
|
connectedClientSessionPullQueues: PullQueueSet
|
@@ -448,7 +440,7 @@ const backgroundApplyLocalPushes = ({
|
|
448
440
|
// It's important that we filter after we got localPushesLatch, otherwise we might filter with the old generation
|
449
441
|
const filteredBatchItems = batchItems
|
450
442
|
.filter(([_1, _2, generation]) => generation === currentLocalPushGenerationRef.current)
|
451
|
-
.map(([
|
443
|
+
.map(([eventEncoded, deferred]) => [eventEncoded, deferred] as const)
|
452
444
|
|
453
445
|
if (filteredBatchItems.length === 0) {
|
454
446
|
// console.log('dropping old-gen batch', currentLocalPushGenerationRef.current)
|
@@ -466,7 +458,7 @@ const backgroundApplyLocalPushes = ({
|
|
466
458
|
syncState,
|
467
459
|
payload: { _tag: 'local-push', newEvents },
|
468
460
|
isClientEvent,
|
469
|
-
isEqualEvent:
|
461
|
+
isEqualEvent: LiveStoreEvent.isEqualEncoded,
|
470
462
|
})
|
471
463
|
|
472
464
|
const mergeCounter = yield* incrementMergeCounter(mergeCounterRef)
|
@@ -552,23 +544,23 @@ const backgroundApplyLocalPushes = ({
|
|
552
544
|
mergeResult: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
|
553
545
|
})
|
554
546
|
|
555
|
-
// Don't sync clientOnly
|
556
|
-
const filteredBatch = mergeResult.newEvents.filter((
|
557
|
-
const
|
558
|
-
return
|
547
|
+
// Don't sync clientOnly events
|
548
|
+
const filteredBatch = mergeResult.newEvents.filter((eventEncoded) => {
|
549
|
+
const eventDef = getEventDef(schema, eventEncoded.name)
|
550
|
+
return eventDef.eventDef.options.clientOnly === false
|
559
551
|
})
|
560
552
|
|
561
553
|
yield* BucketQueue.offerAll(syncBackendPushQueue, filteredBatch)
|
562
554
|
|
563
|
-
yield*
|
555
|
+
yield* applyEventsBatch({ batchItems: mergeResult.newEvents, deferreds })
|
564
556
|
|
565
557
|
// Allow the backend pulling to start
|
566
558
|
yield* pullLatch.open
|
567
559
|
}
|
568
560
|
})
|
569
561
|
|
570
|
-
type
|
571
|
-
batchItems: ReadonlyArray<
|
562
|
+
type ApplyEventsBatch = (_: {
|
563
|
+
batchItems: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>
|
572
564
|
/**
|
573
565
|
* The deferreds are used by the caller to know when the mutation has been processed.
|
574
566
|
* Indexes are aligned with `batchItems`
|
@@ -577,13 +569,13 @@ type ApplyMutationsBatch = (_: {
|
|
577
569
|
}) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
|
578
570
|
|
579
571
|
// TODO how to handle errors gracefully
|
580
|
-
const
|
572
|
+
const applyEventsBatch: ApplyEventsBatch = ({ batchItems, deferreds }) =>
|
581
573
|
Effect.gen(function* () {
|
582
|
-
const { dbReadModel: db,
|
574
|
+
const { dbReadModel: db, dbEventlog, applyEvent } = yield* LeaderThreadCtx
|
583
575
|
|
584
|
-
// NOTE We always start a transaction to ensure consistency between db and
|
576
|
+
// NOTE We always start a transaction to ensure consistency between db and eventlog (even for single-item batches)
|
585
577
|
db.execute('BEGIN TRANSACTION', undefined) // Start the transaction
|
586
|
-
|
578
|
+
dbEventlog.execute('BEGIN TRANSACTION', undefined) // Start the transaction
|
587
579
|
|
588
580
|
yield* Effect.addFinalizer((exit) =>
|
589
581
|
Effect.gen(function* () {
|
@@ -591,12 +583,12 @@ const applyMutationsBatch: ApplyMutationsBatch = ({ batchItems, deferreds }) =>
|
|
591
583
|
|
592
584
|
// Rollback in case of an error
|
593
585
|
db.execute('ROLLBACK', undefined)
|
594
|
-
|
586
|
+
dbEventlog.execute('ROLLBACK', undefined)
|
595
587
|
}),
|
596
588
|
)
|
597
589
|
|
598
590
|
for (let i = 0; i < batchItems.length; i++) {
|
599
|
-
const { sessionChangeset } = yield*
|
591
|
+
const { sessionChangeset } = yield* applyEvent(batchItems[i]!)
|
600
592
|
batchItems[i]!.meta.sessionChangeset = sessionChangeset
|
601
593
|
|
602
594
|
if (deferreds?.[i] !== undefined) {
|
@@ -605,11 +597,11 @@ const applyMutationsBatch: ApplyMutationsBatch = ({ batchItems, deferreds }) =>
|
|
605
597
|
}
|
606
598
|
|
607
599
|
db.execute('COMMIT', undefined) // Commit the transaction
|
608
|
-
|
600
|
+
dbEventlog.execute('COMMIT', undefined) // Commit the transaction
|
609
601
|
}).pipe(
|
610
602
|
Effect.uninterruptible,
|
611
603
|
Effect.scoped,
|
612
|
-
Effect.withSpan('@livestore/common:LeaderSyncProcessor:
|
604
|
+
Effect.withSpan('@livestore/common:LeaderSyncProcessor:applyEventItems', {
|
613
605
|
attributes: { batchSize: batchItems.length },
|
614
606
|
}),
|
615
607
|
Effect.tapCauseLogPretty,
|
@@ -632,9 +624,9 @@ const backgroundBackendPulling = ({
|
|
632
624
|
advancePushHead,
|
633
625
|
}: {
|
634
626
|
initialBackendHead: EventId.GlobalEventId
|
635
|
-
isClientEvent: (
|
627
|
+
isClientEvent: (eventEncoded: LiveStoreEvent.EncodedWithMeta) => boolean
|
636
628
|
restartBackendPushing: (
|
637
|
-
filteredRebasedPending: ReadonlyArray<
|
629
|
+
filteredRebasedPending: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
638
630
|
) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx | HttpClient.HttpClient>
|
639
631
|
otelSpan: otel.Span | undefined
|
640
632
|
syncStateSref: SubscriptionRef.SubscriptionRef<SyncState.SyncState | undefined>
|
@@ -648,11 +640,11 @@ const backgroundBackendPulling = ({
|
|
648
640
|
advancePushHead: (eventId: EventId.EventId) => void
|
649
641
|
}) =>
|
650
642
|
Effect.gen(function* () {
|
651
|
-
const { syncBackend, dbReadModel: db,
|
643
|
+
const { syncBackend, dbReadModel: db, dbEventlog, schema } = yield* LeaderThreadCtx
|
652
644
|
|
653
645
|
if (syncBackend === undefined) return
|
654
646
|
|
655
|
-
const onNewPullChunk = (newEvents:
|
647
|
+
const onNewPullChunk = (newEvents: LiveStoreEvent.EncodedWithMeta[], remaining: number) =>
|
656
648
|
Effect.gen(function* () {
|
657
649
|
if (newEvents.length === 0) return
|
658
650
|
|
@@ -673,7 +665,7 @@ const backgroundBackendPulling = ({
|
|
673
665
|
syncState,
|
674
666
|
payload: SyncState.PayloadUpstreamAdvance.make({ newEvents }),
|
675
667
|
isClientEvent,
|
676
|
-
isEqualEvent:
|
668
|
+
isEqualEvent: LiveStoreEvent.isEqualEncoded,
|
677
669
|
ignoreClientEvents: true,
|
678
670
|
})
|
679
671
|
|
@@ -691,7 +683,7 @@ const backgroundBackendPulling = ({
|
|
691
683
|
|
692
684
|
const newBackendHead = newEvents.at(-1)!.id
|
693
685
|
|
694
|
-
|
686
|
+
Eventlog.updateBackendHead(dbEventlog, newBackendHead)
|
695
687
|
|
696
688
|
if (mergeResult._tag === 'rebase') {
|
697
689
|
otelSpan?.addEvent(`[${mergeCounter}]:pull:rebase`, {
|
@@ -701,14 +693,14 @@ const backgroundBackendPulling = ({
|
|
701
693
|
mergeResult: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
|
702
694
|
})
|
703
695
|
|
704
|
-
const globalRebasedPendingEvents = mergeResult.newSyncState.pending.filter((
|
705
|
-
const
|
706
|
-
return
|
696
|
+
const globalRebasedPendingEvents = mergeResult.newSyncState.pending.filter((event) => {
|
697
|
+
const eventDef = getEventDef(schema, event.name)
|
698
|
+
return eventDef.eventDef.options.clientOnly === false
|
707
699
|
})
|
708
700
|
yield* restartBackendPushing(globalRebasedPendingEvents)
|
709
701
|
|
710
702
|
if (mergeResult.rollbackEvents.length > 0) {
|
711
|
-
yield* rollback({ db,
|
703
|
+
yield* rollback({ db, dbEventlog, eventIdsToRollback: mergeResult.rollbackEvents.map((_) => _.id) })
|
712
704
|
}
|
713
705
|
|
714
706
|
yield* connectedClientSessionPullQueues.offer({
|
@@ -740,12 +732,10 @@ const backgroundBackendPulling = ({
|
|
740
732
|
if (mergeResult.confirmedEvents.length > 0) {
|
741
733
|
// `mergeResult.confirmedEvents` don't contain the correct sync metadata, so we need to use
|
742
734
|
// `newEvents` instead which we filter via `mergeResult.confirmedEvents`
|
743
|
-
const confirmedNewEvents = newEvents.filter((
|
744
|
-
mergeResult.confirmedEvents.some((confirmedEvent) =>
|
745
|
-
EventId.isEqual(mutationEvent.id, confirmedEvent.id),
|
746
|
-
),
|
735
|
+
const confirmedNewEvents = newEvents.filter((event) =>
|
736
|
+
mergeResult.confirmedEvents.some((confirmedEvent) => EventId.isEqual(event.id, confirmedEvent.id)),
|
747
737
|
)
|
748
|
-
yield*
|
738
|
+
yield* Eventlog.updateSyncMetadata(confirmedNewEvents)
|
749
739
|
}
|
750
740
|
}
|
751
741
|
|
@@ -754,7 +744,7 @@ const backgroundBackendPulling = ({
|
|
754
744
|
|
755
745
|
advancePushHead(mergeResult.newSyncState.localHead)
|
756
746
|
|
757
|
-
yield*
|
747
|
+
yield* applyEventsBatch({ batchItems: mergeResult.newEvents, deferreds: undefined })
|
758
748
|
|
759
749
|
yield* SubscriptionRef.set(syncStateSref, mergeResult.newSyncState)
|
760
750
|
|
@@ -764,7 +754,7 @@ const backgroundBackendPulling = ({
|
|
764
754
|
}
|
765
755
|
})
|
766
756
|
|
767
|
-
const cursorInfo = yield*
|
757
|
+
const cursorInfo = yield* Eventlog.getSyncBackendCursorInfo(initialBackendHead)
|
768
758
|
|
769
759
|
yield* syncBackend.pull(cursorInfo).pipe(
|
770
760
|
// TODO only take from queue while connected
|
@@ -777,13 +767,13 @@ const backgroundBackendPulling = ({
|
|
777
767
|
// },
|
778
768
|
// })
|
779
769
|
|
780
|
-
// NOTE we only want to take process
|
770
|
+
// NOTE we only want to take process events when the sync backend is connected
|
781
771
|
// (e.g. needed for simulating being offline)
|
782
772
|
// TODO remove when there's a better way to handle this in stream above
|
783
773
|
yield* SubscriptionRef.waitUntil(syncBackend.isConnected, (isConnected) => isConnected === true)
|
784
774
|
|
785
775
|
yield* onNewPullChunk(
|
786
|
-
batch.map((_) =>
|
776
|
+
batch.map((_) => LiveStoreEvent.EncodedWithMeta.fromGlobal(_.eventEncoded, _.metadata)),
|
787
777
|
remaining,
|
788
778
|
)
|
789
779
|
|
@@ -801,7 +791,7 @@ const backgroundBackendPushing = ({
|
|
801
791
|
devtoolsLatch,
|
802
792
|
backendPushBatchSize,
|
803
793
|
}: {
|
804
|
-
syncBackendPushQueue: BucketQueue.BucketQueue<
|
794
|
+
syncBackendPushQueue: BucketQueue.BucketQueue<LiveStoreEvent.EncodedWithMeta>
|
805
795
|
otelSpan: otel.Span | undefined
|
806
796
|
devtoolsLatch: Effect.Latch | undefined
|
807
797
|
backendPushBatchSize: number
|
@@ -920,7 +910,7 @@ const getMergeCounterFromDb = (dbReadModel: SqliteDb) =>
|
|
920
910
|
return result[0]?.mergeCounter ?? 0
|
921
911
|
})
|
922
912
|
|
923
|
-
const validatePushBatch = (batch: ReadonlyArray<
|
913
|
+
const validatePushBatch = (batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>, pushHead: EventId.EventId) =>
|
924
914
|
Effect.gen(function* () {
|
925
915
|
if (batch.length === 0) {
|
926
916
|
return
|
@@ -1,68 +1,66 @@
|
|
1
|
-
import { LS_DEV,
|
1
|
+
import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
|
2
2
|
import { Effect, ReadonlyArray, Schema } from '@livestore/utils/effect'
|
3
3
|
|
4
4
|
import type { SqliteDb } from '../adapter-types.js'
|
5
|
-
import {
|
6
|
-
import type { LiveStoreSchema,
|
5
|
+
import { getExecArgsFromEvent } from '../materializer-helper.js'
|
6
|
+
import type { LiveStoreSchema, SessionChangesetMetaRow } from '../schema/mod.js'
|
7
7
|
import {
|
8
8
|
EventId,
|
9
|
-
|
10
|
-
|
9
|
+
EVENTLOG_META_TABLE,
|
10
|
+
getEventDef,
|
11
11
|
SESSION_CHANGESET_META_TABLE,
|
12
12
|
sessionChangesetMetaTable,
|
13
13
|
} from '../schema/mod.js'
|
14
14
|
import { insertRow } from '../sql-queries/index.js'
|
15
15
|
import { sql } from '../util.js'
|
16
16
|
import { execSql, execSqlPrepared } from './connection.js'
|
17
|
-
import * as
|
18
|
-
import type {
|
17
|
+
import * as Eventlog from './eventlog.js'
|
18
|
+
import type { ApplyEvent } from './types.js'
|
19
19
|
|
20
|
-
export const
|
20
|
+
export const makeApplyEvent = ({
|
21
21
|
schema,
|
22
22
|
dbReadModel: db,
|
23
|
-
|
23
|
+
dbEventlog,
|
24
24
|
}: {
|
25
25
|
schema: LiveStoreSchema
|
26
26
|
dbReadModel: SqliteDb
|
27
|
-
|
28
|
-
}): Effect.Effect<
|
27
|
+
dbEventlog: SqliteDb
|
28
|
+
}): Effect.Effect<ApplyEvent, never> =>
|
29
29
|
Effect.gen(function* () {
|
30
|
-
const
|
31
|
-
|
32
|
-
const mutationDefSchemaHashMap = new Map(
|
30
|
+
const eventDefSchemaHashMap = new Map(
|
33
31
|
// TODO Running `Schema.hash` can be a bottleneck for larger schemas. There is an opportunity to run this
|
34
32
|
// at build time and lookup the pre-computed hash at runtime.
|
35
33
|
// Also see https://github.com/Effect-TS/effect/issues/2719
|
36
|
-
[...schema.
|
34
|
+
[...schema.eventsDefsMap.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
|
37
35
|
)
|
38
36
|
|
39
|
-
return (
|
37
|
+
return (eventEncoded, options) =>
|
40
38
|
Effect.gen(function* () {
|
41
|
-
const
|
39
|
+
const skipEventlog = options?.skipEventlog ?? false
|
42
40
|
|
43
|
-
const
|
44
|
-
const
|
41
|
+
const eventName = eventEncoded.name
|
42
|
+
const eventDef = getEventDef(schema, eventName)
|
45
43
|
|
46
|
-
const execArgsArr =
|
47
|
-
|
48
|
-
|
44
|
+
const execArgsArr = getExecArgsFromEvent({
|
45
|
+
eventDef,
|
46
|
+
event: { decoded: undefined, encoded: eventEncoded },
|
49
47
|
})
|
50
48
|
|
51
|
-
// NOTE we might want to bring this back if we want to debug no-op
|
49
|
+
// NOTE we might want to bring this back if we want to debug no-op events
|
52
50
|
// const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
|
53
51
|
// onRowsChanged: (rowsChanged: number) => {
|
54
52
|
// if (rowsChanged === 0) {
|
55
|
-
// console.warn(`
|
53
|
+
// console.warn(`Event "${eventDef.name}" did not affect any rows:`, statementSql, bindValues)
|
56
54
|
// }
|
57
55
|
// },
|
58
56
|
// })
|
59
57
|
|
60
|
-
// console.group('[@livestore/common:leader-thread:
|
58
|
+
// console.group('[@livestore/common:leader-thread:applyEvent]', { eventName })
|
61
59
|
|
62
60
|
const session = db.session()
|
63
61
|
|
64
62
|
for (const { statementSql, bindValues } of execArgsArr) {
|
65
|
-
// console.debug(
|
63
|
+
// console.debug(eventName, statementSql, bindValues)
|
66
64
|
// TODO use cached prepared statements instead of exec
|
67
65
|
yield* execSqlPrepared(db, statementSql, bindValues)
|
68
66
|
}
|
@@ -77,9 +75,9 @@ export const makeApplyMutation = ({
|
|
77
75
|
tableName: SESSION_CHANGESET_META_TABLE,
|
78
76
|
columns: sessionChangesetMetaTable.sqliteDef.columns,
|
79
77
|
values: {
|
80
|
-
idGlobal:
|
81
|
-
idClient:
|
82
|
-
// NOTE the changeset will be empty (i.e. null) for no-op
|
78
|
+
idGlobal: eventEncoded.id.global,
|
79
|
+
idClient: eventEncoded.id.client,
|
80
|
+
// NOTE the changeset will be empty (i.e. null) for no-op events
|
83
81
|
changeset: changeset ?? null,
|
84
82
|
debug: LS_DEV ? execArgsArr : null,
|
85
83
|
},
|
@@ -88,22 +86,21 @@ export const makeApplyMutation = ({
|
|
88
86
|
|
89
87
|
// console.groupEnd()
|
90
88
|
|
91
|
-
// write to
|
92
|
-
|
93
|
-
|
94
|
-
const
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
mutationEventEncoded.sessionId,
|
89
|
+
// write to eventlog
|
90
|
+
if (skipEventlog === false) {
|
91
|
+
const eventName = eventEncoded.name
|
92
|
+
const eventDefSchemaHash =
|
93
|
+
eventDefSchemaHashMap.get(eventName) ?? shouldNeverHappen(`Unknown event definition: ${eventName}`)
|
94
|
+
|
95
|
+
yield* Eventlog.insertIntoEventlog(
|
96
|
+
eventEncoded,
|
97
|
+
dbEventlog,
|
98
|
+
eventDefSchemaHash,
|
99
|
+
eventEncoded.clientId,
|
100
|
+
eventEncoded.sessionId,
|
104
101
|
)
|
105
102
|
} else {
|
106
|
-
// console.debug('[@livestore/common:leader-thread] skipping
|
103
|
+
// console.debug('[@livestore/common:leader-thread] skipping eventlog write', mutation, statementSql, bindValues)
|
107
104
|
}
|
108
105
|
|
109
106
|
return {
|
@@ -116,24 +113,24 @@ export const makeApplyMutation = ({
|
|
116
113
|
: { _tag: 'no-op' as const },
|
117
114
|
}
|
118
115
|
}).pipe(
|
119
|
-
Effect.withSpan(`@livestore/common:leader-thread:
|
116
|
+
Effect.withSpan(`@livestore/common:leader-thread:applyEvent`, {
|
120
117
|
attributes: {
|
121
|
-
|
122
|
-
mutationId:
|
123
|
-
'span.label': `${EventId.toString(
|
118
|
+
eventName: eventEncoded.name,
|
119
|
+
mutationId: eventEncoded.id,
|
120
|
+
'span.label': `${EventId.toString(eventEncoded.id)} ${eventEncoded.name}`,
|
124
121
|
},
|
125
122
|
}),
|
126
|
-
// Effect.logDuration('@livestore/common:leader-thread:
|
123
|
+
// Effect.logDuration('@livestore/common:leader-thread:applyEvent'),
|
127
124
|
)
|
128
125
|
})
|
129
126
|
|
130
127
|
export const rollback = ({
|
131
128
|
db,
|
132
|
-
|
129
|
+
dbEventlog,
|
133
130
|
eventIdsToRollback,
|
134
131
|
}: {
|
135
132
|
db: SqliteDb
|
136
|
-
|
133
|
+
dbEventlog: SqliteDb
|
137
134
|
eventIdsToRollback: EventId.EventId[]
|
138
135
|
}) =>
|
139
136
|
Effect.gen(function* () {
|
@@ -163,10 +160,10 @@ export const rollback = ({
|
|
163
160
|
)
|
164
161
|
}
|
165
162
|
|
166
|
-
// Delete the
|
163
|
+
// Delete the eventlog rows
|
167
164
|
for (const eventIdPairChunk of eventIdPairChunks) {
|
168
|
-
|
169
|
-
sql`DELETE FROM ${
|
165
|
+
dbEventlog.execute(
|
166
|
+
sql`DELETE FROM ${EVENTLOG_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdPairChunk.join(', ')})`,
|
170
167
|
)
|
171
168
|
}
|
172
169
|
}).pipe(
|
@@ -174,24 +171,3 @@ export const rollback = ({
|
|
174
171
|
attributes: { count: eventIdsToRollback.length },
|
175
172
|
}),
|
176
173
|
)
|
177
|
-
|
178
|
-
// TODO let's consider removing this "should exclude" mechanism in favour of log compaction etc
|
179
|
-
const makeShouldExcludeMutationFromLog = memoizeByRef((schema: LiveStoreSchema) => {
|
180
|
-
const migrationOptions = schema.migrationOptions
|
181
|
-
const mutationLogExclude =
|
182
|
-
migrationOptions.strategy === 'from-mutation-log'
|
183
|
-
? (migrationOptions.excludeMutations ?? new Set(['livestore.RawSql']))
|
184
|
-
: new Set(['livestore.RawSql'])
|
185
|
-
|
186
|
-
return (mutationName: string, mutationEventEncoded: MutationEvent.AnyEncoded): boolean => {
|
187
|
-
if (mutationLogExclude.has(mutationName)) return true
|
188
|
-
|
189
|
-
const mutationDef = getMutationDef(schema, mutationName)
|
190
|
-
const execArgsArr = getExecArgsFromMutation({
|
191
|
-
mutationDef,
|
192
|
-
mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
|
193
|
-
})
|
194
|
-
|
195
|
-
return execArgsArr.some((_) => _.statementSql.includes('__livestore'))
|
196
|
-
}
|
197
|
-
})
|