@livestore/common 0.3.0-dev.11 → 0.3.0-dev.13
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 +21 -21
- package/dist/adapter-types.d.ts +41 -18
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +12 -0
- package/dist/adapter-types.js.map +1 -1
- package/dist/db-schema/ast/sqlite.d.ts +69 -0
- package/dist/db-schema/ast/sqlite.d.ts.map +1 -0
- package/dist/db-schema/ast/sqlite.js +71 -0
- package/dist/db-schema/ast/sqlite.js.map +1 -0
- package/dist/db-schema/ast/validate.d.ts +3 -0
- package/dist/db-schema/ast/validate.d.ts.map +1 -0
- package/dist/db-schema/ast/validate.js +12 -0
- package/dist/db-schema/ast/validate.js.map +1 -0
- package/dist/db-schema/dsl/field-defs.d.ts +90 -0
- package/dist/db-schema/dsl/field-defs.d.ts.map +1 -0
- package/dist/db-schema/dsl/field-defs.js +87 -0
- package/dist/db-schema/dsl/field-defs.js.map +1 -0
- package/dist/db-schema/dsl/field-defs.test.d.ts +2 -0
- package/dist/db-schema/dsl/field-defs.test.d.ts.map +1 -0
- package/dist/db-schema/dsl/field-defs.test.js +29 -0
- package/dist/db-schema/dsl/field-defs.test.js.map +1 -0
- package/dist/db-schema/dsl/index.d.ts +88 -0
- package/dist/db-schema/dsl/index.d.ts.map +1 -0
- package/dist/db-schema/dsl/index.js +35 -0
- package/dist/db-schema/dsl/index.js.map +1 -0
- package/dist/db-schema/dsl/mod.d.ts +90 -0
- package/dist/db-schema/dsl/mod.d.ts.map +1 -0
- package/dist/db-schema/dsl/mod.js +35 -0
- package/dist/db-schema/dsl/mod.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.d.ts +90 -0
- package/dist/db-schema/dsl/sqlite/field-defs.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.js +86 -0
- package/dist/db-schema/dsl/sqlite/field-defs.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.d.ts +2 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.js +29 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/index.d.ts +88 -0
- package/dist/db-schema/dsl/sqlite/index.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/index.js +35 -0
- package/dist/db-schema/dsl/sqlite/index.js.map +1 -0
- package/dist/db-schema/hash.d.ts +2 -0
- package/dist/db-schema/hash.d.ts.map +1 -0
- package/dist/db-schema/hash.js +14 -0
- package/dist/db-schema/hash.js.map +1 -0
- package/dist/db-schema/index.d.ts +4 -0
- package/dist/db-schema/index.d.ts.map +1 -0
- package/dist/db-schema/index.js +6 -0
- package/dist/db-schema/index.js.map +1 -0
- package/dist/db-schema/mod.d.ts +3 -0
- package/dist/db-schema/mod.d.ts.map +1 -0
- package/dist/db-schema/mod.js +3 -0
- package/dist/db-schema/mod.js.map +1 -0
- package/dist/derived-mutations.d.ts +1 -1
- package/dist/derived-mutations.d.ts.map +1 -1
- package/dist/derived-mutations.js +3 -3
- package/dist/derived-mutations.js.map +1 -1
- package/dist/devtools/devtools-bridge.d.ts +10 -7
- package/dist/devtools/devtools-bridge.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +101 -28
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +19 -3
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +24 -32
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +19 -10
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +220 -56
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +57 -9
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-messages.d.ts +2 -2
- package/dist/devtools/devtools-messages.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.js +2 -2
- package/dist/devtools/devtools-messages.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +50 -35
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
- package/dist/leader-thread/apply-mutation.js +8 -6
- package/dist/leader-thread/apply-mutation.js.map +1 -1
- package/dist/leader-thread/connection.d.ts +31 -3
- package/dist/leader-thread/connection.d.ts.map +1 -1
- package/dist/leader-thread/connection.js +18 -3
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +56 -31
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +23 -6
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/mutationlog.d.ts +1 -1
- package/dist/leader-thread/mutationlog.d.ts.map +1 -1
- package/dist/leader-thread/mutationlog.js +7 -5
- package/dist/leader-thread/mutationlog.js.map +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts +4 -2
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +13 -8
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +22 -15
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +1 -3
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/query-builder/api.d.ts +3 -3
- package/dist/query-builder/api.d.ts.map +1 -1
- package/dist/query-builder/impl.js.map +1 -1
- package/dist/query-builder/impl.test.js +16 -1
- package/dist/query-builder/impl.test.js.map +1 -1
- package/dist/query-info.d.ts +3 -3
- package/dist/query-info.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.js +8 -6
- package/dist/rehydrate-from-mutationlog.js.map +1 -1
- package/dist/schema/EventId.d.ts +10 -9
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +14 -11
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/EventId.test.js +3 -3
- package/dist/schema/EventId.test.js.map +1 -1
- package/dist/schema/MutationEvent.d.ts +37 -12
- package/dist/schema/MutationEvent.d.ts.map +1 -1
- package/dist/schema/MutationEvent.js +20 -4
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
- package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
- package/dist/schema/db-schema/ast/sqlite.js +71 -0
- package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
- package/dist/schema/db-schema/ast/validate.d.ts +3 -0
- package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
- package/dist/schema/db-schema/ast/validate.js +12 -0
- package/dist/schema/db-schema/ast/validate.js.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
- package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.js +87 -0
- package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
- package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
- package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
- package/dist/schema/db-schema/dsl/mod.d.ts +88 -0
- package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/mod.js +35 -0
- package/dist/schema/db-schema/dsl/mod.js.map +1 -0
- package/dist/schema/db-schema/hash.d.ts +2 -0
- package/dist/schema/db-schema/hash.d.ts.map +1 -0
- package/dist/schema/db-schema/hash.js +14 -0
- package/dist/schema/db-schema/hash.js.map +1 -0
- package/dist/schema/db-schema/mod.d.ts +3 -0
- package/dist/schema/db-schema/mod.d.ts.map +1 -0
- package/dist/schema/db-schema/mod.js +3 -0
- package/dist/schema/db-schema/mod.js.map +1 -0
- package/dist/schema/mod.d.ts +1 -0
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +1 -0
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/mutations.d.ts +4 -8
- package/dist/schema/mutations.d.ts.map +1 -1
- package/dist/schema/mutations.js +2 -2
- package/dist/schema/mutations.js.map +1 -1
- package/dist/schema/schema-helpers.js +1 -1
- package/dist/schema/schema-helpers.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/system-tables.d.ts +47 -29
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +10 -7
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/schema/table-def.d.ts +18 -14
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js +3 -4
- package/dist/schema/table-def.js.map +1 -1
- package/dist/schema-management/migrations.d.ts +3 -3
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +7 -2
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts +1 -1
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
- package/dist/sql-queries/sql-query-builder.js.map +1 -1
- package/dist/sql-queries/types.d.ts +2 -1
- package/dist/sql-queries/types.d.ts.map +1 -1
- package/dist/sql-queries/types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +3 -5
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +38 -12
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/next/facts.js +1 -1
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +2 -0
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +3 -1
- 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 +1 -1
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +3 -1
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +5 -3
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +12 -12
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +43 -43
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.d.ts +11 -11
- package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.js +12 -10
- package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -2
- package/dist/sync/syncstate.d.ts +9 -9
- package/dist/sync/syncstate.js +6 -6
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +18 -16
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -3
- package/src/adapter-types.ts +35 -17
- package/src/derived-mutations.ts +4 -4
- package/src/devtools/devtools-bridge.ts +10 -7
- package/src/devtools/devtools-messages-client-session.ts +26 -10
- package/src/devtools/devtools-messages-common.ts +37 -8
- package/src/devtools/devtools-messages-leader.ts +78 -16
- package/src/devtools/devtools-messages.ts +2 -2
- package/src/index.ts +1 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +59 -38
- package/src/leader-thread/apply-mutation.ts +15 -5
- package/src/leader-thread/connection.ts +48 -3
- package/src/leader-thread/leader-worker-devtools.ts +85 -35
- package/src/leader-thread/make-leader-thread-layer.ts +29 -9
- package/src/leader-thread/mutationlog.ts +8 -6
- package/src/leader-thread/recreate-db.ts +19 -10
- package/src/leader-thread/types.ts +22 -15
- package/src/query-builder/api.ts +4 -4
- package/src/query-builder/impl.test.ts +22 -1
- package/src/query-builder/impl.ts +2 -2
- package/src/query-info.ts +3 -3
- package/src/rehydrate-from-mutationlog.ts +8 -6
- package/src/schema/EventId.test.ts +3 -3
- package/src/schema/EventId.ts +20 -16
- package/src/schema/MutationEvent.ts +31 -6
- package/src/schema/db-schema/ast/sqlite.ts +142 -0
- package/src/schema/db-schema/ast/validate.ts +13 -0
- package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
- package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
- package/src/schema/db-schema/dsl/field-defs.ts +242 -0
- package/src/schema/db-schema/dsl/mod.ts +195 -0
- package/src/schema/db-schema/hash.ts +14 -0
- package/src/schema/db-schema/mod.ts +2 -0
- package/src/schema/mod.ts +1 -0
- package/src/schema/mutations.ts +6 -19
- package/src/schema/schema-helpers.ts +1 -1
- package/src/schema/schema.ts +2 -2
- package/src/schema/system-tables.ts +10 -7
- package/src/schema/table-def.ts +17 -16
- package/src/schema-management/migrations.ts +10 -6
- package/src/sql-queries/sql-queries.ts +1 -1
- package/src/sql-queries/sql-query-builder.ts +1 -2
- package/src/sql-queries/types.ts +3 -1
- package/src/sync/ClientSessionSyncProcessor.ts +44 -14
- package/src/sync/next/facts.ts +1 -1
- package/src/sync/next/history-dag-common.ts +5 -1
- package/src/sync/next/history-dag.ts +1 -1
- package/src/sync/next/rebase-events.ts +8 -2
- package/src/sync/next/test/compact-events.calculator.test.ts +12 -12
- package/src/sync/next/test/compact-events.test.ts +43 -43
- package/src/sync/next/test/mutation-fixtures.ts +16 -12
- package/src/sync/syncstate.test.ts +19 -17
- package/src/sync/syncstate.ts +6 -6
- package/src/version.ts +1 -1
- package/tsconfig.json +1 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
import { isNotUndefined, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
|
1
|
+
import { isNotUndefined, LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
|
2
2
|
import type { HttpClient, Scope, Tracer } from '@livestore/utils/effect'
|
3
3
|
import {
|
4
4
|
BucketQueue,
|
@@ -32,7 +32,7 @@ import * as SyncState from '../sync/syncstate.js'
|
|
32
32
|
import { sql } from '../util.js'
|
33
33
|
import { makeApplyMutation } from './apply-mutation.js'
|
34
34
|
import { execSql } from './connection.js'
|
35
|
-
import { getBackendHeadFromDb,
|
35
|
+
import { getBackendHeadFromDb, getClientHeadFromDb, getMutationEventsSince, updateBackendHead } from './mutationlog.js'
|
36
36
|
import type { InitialBlockingSyncContext, InitialSyncInfo, LeaderSyncProcessor } from './types.js'
|
37
37
|
import { LeaderThreadCtx } from './types.js'
|
38
38
|
|
@@ -83,7 +83,7 @@ export const makeLeaderSyncProcessor = ({
|
|
83
83
|
|
84
84
|
const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) => {
|
85
85
|
const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
|
86
|
-
return mutationDef.options.
|
86
|
+
return mutationDef.options.clientOnly
|
87
87
|
}
|
88
88
|
|
89
89
|
// This context depends on data from `boot`, we should find a better implementation to avoid this ref indirection.
|
@@ -93,8 +93,7 @@ export const makeLeaderSyncProcessor = ({
|
|
93
93
|
| {
|
94
94
|
otelSpan: otel.Span | undefined
|
95
95
|
span: Tracer.Span
|
96
|
-
|
97
|
-
devtoolsPushLatch: Effect.Latch | undefined
|
96
|
+
devtoolsLatch: Effect.Latch | undefined
|
98
97
|
},
|
99
98
|
}
|
100
99
|
|
@@ -107,10 +106,6 @@ export const makeLeaderSyncProcessor = ({
|
|
107
106
|
// TODO validate batch
|
108
107
|
if (newEvents.length === 0) return
|
109
108
|
|
110
|
-
if (ctxRef.current?.devtoolsPushLatch !== undefined) {
|
111
|
-
yield* ctxRef.current.devtoolsPushLatch.await
|
112
|
-
}
|
113
|
-
|
114
109
|
const waitForProcessing = options?.waitForProcessing ?? false
|
115
110
|
|
116
111
|
if (waitForProcessing) {
|
@@ -137,18 +132,24 @@ export const makeLeaderSyncProcessor = ({
|
|
137
132
|
}),
|
138
133
|
)
|
139
134
|
|
140
|
-
const pushPartial: LeaderSyncProcessor['pushPartial'] = (
|
135
|
+
const pushPartial: LeaderSyncProcessor['pushPartial'] = ({
|
136
|
+
mutationEvent: partialMutationEvent,
|
137
|
+
clientId,
|
138
|
+
sessionId,
|
139
|
+
}) =>
|
141
140
|
Effect.gen(function* () {
|
142
141
|
const syncState = yield* syncStateSref
|
143
142
|
if (syncState === undefined) return shouldNeverHappen('Not initialized')
|
144
143
|
|
145
144
|
const mutationDef =
|
146
|
-
schema.mutations.get(
|
147
|
-
shouldNeverHappen(`Unknown mutation: ${
|
145
|
+
schema.mutations.get(partialMutationEvent.mutation) ??
|
146
|
+
shouldNeverHappen(`Unknown mutation: ${partialMutationEvent.mutation}`)
|
148
147
|
|
149
148
|
const mutationEventEncoded = new MutationEvent.EncodedWithMeta({
|
150
|
-
...
|
151
|
-
|
149
|
+
...partialMutationEvent,
|
150
|
+
clientId,
|
151
|
+
sessionId,
|
152
|
+
...EventId.nextPair(syncState.localHead, mutationDef.options.clientOnly),
|
152
153
|
})
|
153
154
|
|
154
155
|
yield* push([mutationEventEncoded])
|
@@ -164,12 +165,11 @@ export const makeLeaderSyncProcessor = ({
|
|
164
165
|
ctxRef.current = {
|
165
166
|
otelSpan,
|
166
167
|
span,
|
167
|
-
|
168
|
-
devtoolsPushLatch: devtools.enabled ? devtools.syncBackendPushLatch : undefined,
|
168
|
+
devtoolsLatch: devtools.enabled ? devtools.syncBackendLatch : undefined,
|
169
169
|
}
|
170
170
|
|
171
171
|
const initialBackendHead = dbMissing ? EventId.ROOT.global : getBackendHeadFromDb(dbMutationLog)
|
172
|
-
const initialLocalHead = dbMissing ? EventId.ROOT :
|
172
|
+
const initialLocalHead = dbMissing ? EventId.ROOT : getClientHeadFromDb(dbMutationLog)
|
173
173
|
|
174
174
|
if (initialBackendHead > initialLocalHead.global) {
|
175
175
|
return shouldNeverHappen(
|
@@ -179,14 +179,14 @@ export const makeLeaderSyncProcessor = ({
|
|
179
179
|
|
180
180
|
const pendingMutationEvents = yield* getMutationEventsSince({
|
181
181
|
global: initialBackendHead,
|
182
|
-
|
182
|
+
client: EventId.clientDefault,
|
183
183
|
}).pipe(Effect.map(ReadonlyArray.map((_) => new MutationEvent.EncodedWithMeta(_))))
|
184
184
|
|
185
185
|
const initialSyncState = new SyncState.SyncState({
|
186
186
|
pending: pendingMutationEvents,
|
187
187
|
// On the leader we don't need a rollback tail beyond `pending` items
|
188
188
|
rollbackTail: [],
|
189
|
-
upstreamHead: { global: initialBackendHead,
|
189
|
+
upstreamHead: { global: initialBackendHead, client: EventId.clientDefault },
|
190
190
|
localHead: initialLocalHead,
|
191
191
|
})
|
192
192
|
|
@@ -196,10 +196,10 @@ export const makeLeaderSyncProcessor = ({
|
|
196
196
|
// Rehydrate sync queue
|
197
197
|
if (pendingMutationEvents.length > 0) {
|
198
198
|
const filteredBatch = pendingMutationEvents
|
199
|
-
// Don't sync
|
199
|
+
// Don't sync clientOnly mutations
|
200
200
|
.filter((mutationEventEncoded) => {
|
201
201
|
const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
|
202
|
-
return mutationDef.options.
|
202
|
+
return mutationDef.options.clientOnly === false
|
203
203
|
})
|
204
204
|
|
205
205
|
yield* BucketQueue.offerAll(syncBackendQueue, filteredBatch)
|
@@ -220,7 +220,12 @@ export const makeLeaderSyncProcessor = ({
|
|
220
220
|
|
221
221
|
yield* FiberHandle.run(
|
222
222
|
backendPushingFiberHandle,
|
223
|
-
backgroundBackendPushing({
|
223
|
+
backgroundBackendPushing({
|
224
|
+
dbReady,
|
225
|
+
syncBackendQueue,
|
226
|
+
otelSpan,
|
227
|
+
devtoolsLatch: ctxRef.current?.devtoolsLatch,
|
228
|
+
}).pipe(Effect.tapCauseLogPretty),
|
224
229
|
)
|
225
230
|
|
226
231
|
yield* backgroundBackendPulling({
|
@@ -239,7 +244,12 @@ export const makeLeaderSyncProcessor = ({
|
|
239
244
|
// Restart pushing fiber
|
240
245
|
yield* FiberHandle.run(
|
241
246
|
backendPushingFiberHandle,
|
242
|
-
backgroundBackendPushing({
|
247
|
+
backgroundBackendPushing({
|
248
|
+
dbReady,
|
249
|
+
syncBackendQueue,
|
250
|
+
otelSpan,
|
251
|
+
devtoolsLatch: ctxRef.current?.devtoolsLatch,
|
252
|
+
}).pipe(Effect.tapCauseLogPretty),
|
243
253
|
)
|
244
254
|
}),
|
245
255
|
syncStateSref,
|
@@ -247,8 +257,10 @@ export const makeLeaderSyncProcessor = ({
|
|
247
257
|
pullLatch,
|
248
258
|
otelSpan,
|
249
259
|
initialBlockingSyncContext,
|
250
|
-
|
260
|
+
devtoolsLatch: ctxRef.current?.devtoolsLatch,
|
251
261
|
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
262
|
+
|
263
|
+
return { initialLeaderHead: initialLocalHead }
|
252
264
|
}).pipe(Effect.withSpanScoped('@livestore/common:leader-thread:syncing'))
|
253
265
|
|
254
266
|
return {
|
@@ -357,10 +369,10 @@ const backgroundApplyLocalPushes = ({
|
|
357
369
|
updateResult: TRACE_VERBOSE ? JSON.stringify(updateResult) : undefined,
|
358
370
|
})
|
359
371
|
|
360
|
-
// Don't sync
|
372
|
+
// Don't sync clientOnly mutations
|
361
373
|
const filteredBatch = updateResult.newEvents.filter((mutationEventEncoded) => {
|
362
374
|
const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
|
363
|
-
return mutationDef.options.
|
375
|
+
return mutationDef.options.clientOnly === false
|
364
376
|
})
|
365
377
|
|
366
378
|
yield* BucketQueue.offerAll(syncBackendQueue, filteredBatch)
|
@@ -431,7 +443,7 @@ const backgroundBackendPulling = ({
|
|
431
443
|
syncStateSref,
|
432
444
|
localPushesLatch,
|
433
445
|
pullLatch,
|
434
|
-
|
446
|
+
devtoolsLatch,
|
435
447
|
initialBlockingSyncContext,
|
436
448
|
}: {
|
437
449
|
dbReady: Deferred.Deferred<void>
|
@@ -444,7 +456,7 @@ const backgroundBackendPulling = ({
|
|
444
456
|
syncStateSref: SubscriptionRef.SubscriptionRef<SyncState.SyncState | undefined>
|
445
457
|
localPushesLatch: Effect.Latch
|
446
458
|
pullLatch: Effect.Latch
|
447
|
-
|
459
|
+
devtoolsLatch: Effect.Latch | undefined
|
448
460
|
initialBlockingSyncContext: InitialBlockingSyncContext
|
449
461
|
}) =>
|
450
462
|
Effect.gen(function* () {
|
@@ -466,8 +478,8 @@ const backgroundBackendPulling = ({
|
|
466
478
|
Effect.gen(function* () {
|
467
479
|
if (newEvents.length === 0) return
|
468
480
|
|
469
|
-
if (
|
470
|
-
yield*
|
481
|
+
if (devtoolsLatch !== undefined) {
|
482
|
+
yield* devtoolsLatch.await
|
471
483
|
}
|
472
484
|
|
473
485
|
// Prevent more local pushes from being processed until this pull is finished
|
@@ -507,7 +519,7 @@ const backgroundBackendPulling = ({
|
|
507
519
|
|
508
520
|
const filteredRebasedPending = updateResult.newSyncState.pending.filter((mutationEvent) => {
|
509
521
|
const mutationDef = schema.mutations.get(mutationEvent.mutation)!
|
510
|
-
return mutationDef.options.
|
522
|
+
return mutationDef.options.clientOnly === false
|
511
523
|
})
|
512
524
|
yield* restartBackendPushing(filteredRebasedPending)
|
513
525
|
|
@@ -592,9 +604,9 @@ const rollback = ({
|
|
592
604
|
Effect.gen(function* () {
|
593
605
|
const rollbackEvents = db
|
594
606
|
.select<SessionChangesetMetaRow>(
|
595
|
-
sql`SELECT * FROM ${SESSION_CHANGESET_META_TABLE} WHERE (idGlobal,
|
607
|
+
sql`SELECT * FROM ${SESSION_CHANGESET_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdsToRollback.map((id) => `(${id.global}, ${id.client})`).join(', ')})`,
|
596
608
|
)
|
597
|
-
.map((_) => ({ id: { global: _.idGlobal,
|
609
|
+
.map((_) => ({ id: { global: _.idGlobal, client: _.idClient }, changeset: _.changeset, debug: _.debug }))
|
598
610
|
.toSorted((a, b) => EventId.compare(a.id, b.id))
|
599
611
|
|
600
612
|
// Apply changesets in reverse order
|
@@ -607,12 +619,12 @@ const rollback = ({
|
|
607
619
|
|
608
620
|
// Delete the changeset rows
|
609
621
|
db.execute(
|
610
|
-
sql`DELETE FROM ${SESSION_CHANGESET_META_TABLE} WHERE (idGlobal,
|
622
|
+
sql`DELETE FROM ${SESSION_CHANGESET_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdsToRollback.map((id) => `(${id.global}, ${id.client})`).join(', ')})`,
|
611
623
|
)
|
612
624
|
|
613
625
|
// Delete the mutation log rows
|
614
626
|
dbMutationLog.execute(
|
615
|
-
sql`DELETE FROM ${MUTATION_LOG_META_TABLE} WHERE (idGlobal,
|
627
|
+
sql`DELETE FROM ${MUTATION_LOG_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdsToRollback.map((id) => `(${id.global}, ${id.client})`).join(', ')})`,
|
616
628
|
)
|
617
629
|
}).pipe(
|
618
630
|
Effect.withSpan('@livestore/common:leader-thread:syncing:rollback', {
|
@@ -632,12 +644,12 @@ const getCursorInfo = (remoteHead: EventId.GlobalEventId) =>
|
|
632
644
|
|
633
645
|
const syncMetadataOption = yield* Effect.sync(() =>
|
634
646
|
dbMutationLog.select<{ syncMetadataJson: string }>(
|
635
|
-
sql`SELECT syncMetadataJson FROM ${MUTATION_LOG_META_TABLE} WHERE idGlobal = ${remoteHead} ORDER BY
|
647
|
+
sql`SELECT syncMetadataJson FROM ${MUTATION_LOG_META_TABLE} WHERE idGlobal = ${remoteHead} ORDER BY idClient ASC LIMIT 1`,
|
636
648
|
),
|
637
649
|
).pipe(Effect.andThen(Schema.decode(MutationlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
|
638
650
|
|
639
651
|
return Option.some({
|
640
|
-
cursor: { global: remoteHead,
|
652
|
+
cursor: { global: remoteHead, client: EventId.clientDefault },
|
641
653
|
metadata: syncMetadataOption,
|
642
654
|
}) satisfies InitialSyncInfo
|
643
655
|
}).pipe(Effect.withSpan('@livestore/common:leader-thread:syncing:getCursorInfo', { attributes: { remoteHead } }))
|
@@ -646,10 +658,12 @@ const backgroundBackendPushing = ({
|
|
646
658
|
dbReady,
|
647
659
|
syncBackendQueue,
|
648
660
|
otelSpan,
|
661
|
+
devtoolsLatch,
|
649
662
|
}: {
|
650
663
|
dbReady: Deferred.Deferred<void>
|
651
664
|
syncBackendQueue: BucketQueue.BucketQueue<MutationEvent.EncodedWithMeta>
|
652
665
|
otelSpan: otel.Span | undefined
|
666
|
+
devtoolsLatch: Effect.Latch | undefined
|
653
667
|
}) =>
|
654
668
|
Effect.gen(function* () {
|
655
669
|
const { syncBackend, dbMutationLog } = yield* LeaderThreadCtx
|
@@ -665,6 +679,10 @@ const backgroundBackendPushing = ({
|
|
665
679
|
|
666
680
|
yield* SubscriptionRef.waitUntil(syncBackend.isConnected, (isConnected) => isConnected === true)
|
667
681
|
|
682
|
+
if (devtoolsLatch !== undefined) {
|
683
|
+
yield* devtoolsLatch.await
|
684
|
+
}
|
685
|
+
|
668
686
|
otelSpan?.addEvent('backend-push', {
|
669
687
|
batchSize: queueItems.length,
|
670
688
|
batch: TRACE_VERBOSE ? JSON.stringify(queueItems) : undefined,
|
@@ -674,6 +692,9 @@ const backgroundBackendPushing = ({
|
|
674
692
|
const pushResult = yield* syncBackend.push(queueItems.map((_) => _.toGlobal())).pipe(Effect.either)
|
675
693
|
|
676
694
|
if (pushResult._tag === 'Left') {
|
695
|
+
if (LS_DEV) {
|
696
|
+
yield* Effect.logDebug('backend-push-error', { error: pushResult.left.toString() })
|
697
|
+
}
|
677
698
|
otelSpan?.addEvent('backend-push-error', { error: pushResult.left.toString() })
|
678
699
|
// wait for interrupt caused by background pulling which will then restart pushing
|
679
700
|
return yield* Effect.never
|
@@ -689,7 +710,7 @@ const backgroundBackendPushing = ({
|
|
689
710
|
...updateRows({
|
690
711
|
tableName: MUTATION_LOG_META_TABLE,
|
691
712
|
columns: mutationLogMetaTable.sqliteDef.columns,
|
692
|
-
where: { idGlobal: mutationEventEncoded.id.global,
|
713
|
+
where: { idGlobal: mutationEventEncoded.id.global, idClient: mutationEventEncoded.id.client },
|
693
714
|
updateValues: { syncMetadataJson: metadata[i]! },
|
694
715
|
}),
|
695
716
|
)
|
@@ -79,7 +79,7 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
|
|
79
79
|
columns: sessionChangesetMetaTable.sqliteDef.columns,
|
80
80
|
values: {
|
81
81
|
idGlobal: mutationEventEncoded.id.global,
|
82
|
-
|
82
|
+
idClient: mutationEventEncoded.id.client,
|
83
83
|
// NOTE the changeset will be empty (i.e. null) for no-op mutations
|
84
84
|
changeset: changeset ?? null,
|
85
85
|
debug: execArgsArr,
|
@@ -92,7 +92,13 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
|
|
92
92
|
// write to mutation_log
|
93
93
|
const excludeFromMutationLog = shouldExcludeMutationFromLog(mutationName, mutationEventEncoded)
|
94
94
|
if (skipMutationLog === false && excludeFromMutationLog === false) {
|
95
|
-
yield* insertIntoMutationLog(
|
95
|
+
yield* insertIntoMutationLog(
|
96
|
+
mutationEventEncoded,
|
97
|
+
dbMutationLog,
|
98
|
+
mutationDefSchemaHashMap,
|
99
|
+
mutationEventEncoded.clientId,
|
100
|
+
mutationEventEncoded.sessionId,
|
101
|
+
)
|
96
102
|
} else {
|
97
103
|
// console.debug('[@livestore/common:leader-thread] skipping mutation log write', mutation, statementSql, bindValues)
|
98
104
|
}
|
@@ -101,7 +107,7 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
|
|
101
107
|
attributes: {
|
102
108
|
mutationName: mutationEventEncoded.mutation,
|
103
109
|
mutationId: mutationEventEncoded.id,
|
104
|
-
'span.label': `(${mutationEventEncoded.id.global},${mutationEventEncoded.id.
|
110
|
+
'span.label': `(${mutationEventEncoded.id.global},${mutationEventEncoded.id.client}) ${mutationEventEncoded.mutation}`,
|
105
111
|
},
|
106
112
|
}),
|
107
113
|
// Effect.logDuration('@livestore/common:leader-thread:applyMutation'),
|
@@ -113,6 +119,8 @@ const insertIntoMutationLog = (
|
|
113
119
|
mutationEventEncoded: MutationEvent.AnyEncoded,
|
114
120
|
dbMutationLog: SqliteDb,
|
115
121
|
mutationDefSchemaHashMap: Map<string, number>,
|
122
|
+
clientId: string,
|
123
|
+
sessionId: string | undefined,
|
116
124
|
) =>
|
117
125
|
Effect.gen(function* () {
|
118
126
|
const mutationName = mutationEventEncoded.mutation
|
@@ -127,11 +135,13 @@ const insertIntoMutationLog = (
|
|
127
135
|
columns: mutationLogMetaTable.sqliteDef.columns,
|
128
136
|
values: {
|
129
137
|
idGlobal: mutationEventEncoded.id.global,
|
130
|
-
|
138
|
+
idClient: mutationEventEncoded.id.client,
|
131
139
|
parentIdGlobal: mutationEventEncoded.parentId.global,
|
132
|
-
|
140
|
+
parentIdClient: mutationEventEncoded.parentId.client,
|
133
141
|
mutation: mutationEventEncoded.mutation,
|
134
142
|
argsJson: mutationEventEncoded.args ?? {},
|
143
|
+
clientId,
|
144
|
+
sessionId: sessionId ?? null,
|
135
145
|
schemaHash: mutationDefSchemaHash,
|
136
146
|
syncMetadataJson: Option.none(),
|
137
147
|
},
|
@@ -12,13 +12,58 @@ namespace WaSqlite {
|
|
12
12
|
export type SQLiteError = any
|
13
13
|
}
|
14
14
|
|
15
|
-
|
15
|
+
type ConnectionOptions = {
|
16
|
+
/**
|
17
|
+
* The database connection locking mode.
|
18
|
+
*
|
19
|
+
* @remarks
|
20
|
+
*
|
21
|
+
* This **option is ignored** when used on an **in-memory database** as they can only operate in exclusive locking mode.
|
22
|
+
* In-memory databases can’t share state between connections (unless using a
|
23
|
+
* {@link https://www.sqlite.org/sharedcache.html#shared_cache_and_in_memory_databases|shared cache}),
|
24
|
+
* making concurrent access impossible. This is functionally equivalent to exclusive locking.
|
25
|
+
*
|
26
|
+
* @defaultValue
|
27
|
+
* The default is `"NORMAL"` unless it was unless overridden at compile-time using `SQLITE_DEFAULT_LOCKING_MODE`.
|
28
|
+
*
|
29
|
+
* @see {@link https://www.sqlite.org/pragma.html#pragma_locking_mode|`locking_mode` pragma}
|
30
|
+
*/
|
31
|
+
lockingMode?: 'NORMAL' | 'EXCLUSIVE'
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Whether to enforce foreign key constraints.
|
35
|
+
*
|
36
|
+
* @privateRemarks
|
37
|
+
*
|
38
|
+
* We require a value for this option to minimize future problems, as the default value might change in future
|
39
|
+
* versions of SQLite.
|
40
|
+
*
|
41
|
+
* @see {@link https://www.sqlite.org/pragma.html#pragma_foreign_keys|`foreign_keys` pragma}
|
42
|
+
*/
|
43
|
+
foreignKeys: boolean
|
44
|
+
}
|
45
|
+
|
46
|
+
export const configureConnection = (sqliteDb: SqliteDb, { foreignKeys, lockingMode }: ConnectionOptions) =>
|
16
47
|
execSql(
|
17
48
|
sqliteDb,
|
49
|
+
// We use the WAL journal mode is significantly faster in most scenarios than the traditional rollback journal mode.
|
50
|
+
// It specifically significantly improves write performance. However, when using the WAL journal mode, transactions
|
51
|
+
// that involve changes against multiple ATTACHed databases are atomic for each database but are not atomic
|
52
|
+
// across all databases as a set. Additionally, it is not possible to change the page size after entering WAL mode,
|
53
|
+
// whether on an empty database or by using VACUUM or the backup API. To change the page size, we must switch to the
|
54
|
+
// rollback journal mode.
|
55
|
+
//
|
56
|
+
// When connected to an in-memory database, the WAL journal mode option is ignored because an in-memory database can
|
57
|
+
// only be in either the MEMORY or OFF options. By default, an in-memory database is in the MEMORY option, which
|
58
|
+
// means that it stores the rollback journal in volatile RAM. This saves disk I/O but at the expense of safety and
|
59
|
+
// integrity. If the thread using SQLite crashes in the middle of a transaction, then the database file will very
|
60
|
+
// likely go corrupt.
|
18
61
|
sql`
|
62
|
+
-- disable WAL until we have it working properly
|
63
|
+
-- PRAGMA journal_mode=WAL;
|
19
64
|
PRAGMA page_size=8192;
|
20
|
-
PRAGMA
|
21
|
-
${
|
65
|
+
PRAGMA foreign_keys=${foreignKeys ? 'ON' : 'OFF'};
|
66
|
+
${lockingMode === undefined ? '' : sql`PRAGMA locking_mode=${lockingMode};`}
|
22
67
|
`,
|
23
68
|
{},
|
24
69
|
)
|
@@ -5,7 +5,7 @@ import { MUTATION_LOG_META_TABLE, SCHEMA_META_TABLE, SCHEMA_MUTATIONS_META_TABLE
|
|
5
5
|
import type { DevtoolsOptions, PersistenceInfoPair } from './types.js'
|
6
6
|
import { LeaderThreadCtx } from './types.js'
|
7
7
|
|
8
|
-
type SendMessageToDevtools = (message: Devtools.
|
8
|
+
type SendMessageToDevtools = (message: Devtools.Leader.MessageFromApp) => Effect.Effect<void>
|
9
9
|
|
10
10
|
// TODO bind scope to the webchannel lifetime
|
11
11
|
export const bootDevtools = (options: DevtoolsOptions) =>
|
@@ -38,18 +38,7 @@ export const bootDevtools = (options: DevtoolsOptions) =>
|
|
38
38
|
const pullQueue = yield* connectedClientSessionPullQueues.makeQueue(localHead)
|
39
39
|
|
40
40
|
yield* Stream.fromQueue(pullQueue).pipe(
|
41
|
-
Stream.tap((msg) =>
|
42
|
-
Effect.gen(function* () {
|
43
|
-
if (msg.payload._tag === 'upstream-advance') {
|
44
|
-
for (const mutationEventEncoded of msg.payload.newEvents) {
|
45
|
-
// TODO refactor with push semantics
|
46
|
-
yield* sendMessage(Devtools.MutationBroadcast.make({ mutationEventEncoded, liveStoreVersion }))
|
47
|
-
}
|
48
|
-
} else {
|
49
|
-
yield* Effect.logWarning('TODO implement rebases in devtools')
|
50
|
-
}
|
51
|
-
}),
|
52
|
-
),
|
41
|
+
Stream.tap((msg) => sendMessage(Devtools.Leader.SyncPull.make({ payload: msg.payload, liveStoreVersion }))),
|
53
42
|
Stream.runDrain,
|
54
43
|
Effect.forkScoped,
|
55
44
|
)
|
@@ -66,7 +55,7 @@ const listenToDevtools = ({
|
|
66
55
|
sendMessage,
|
67
56
|
persistenceInfo,
|
68
57
|
}: {
|
69
|
-
incomingMessages: Stream.Stream<Devtools.
|
58
|
+
incomingMessages: Stream.Stream<Devtools.Leader.MessageToApp>
|
70
59
|
sendMessage: SendMessageToDevtools
|
71
60
|
persistenceInfo?: PersistenceInfoPair
|
72
61
|
}) =>
|
@@ -79,6 +68,8 @@ const listenToDevtools = ({
|
|
79
68
|
shutdownStateSubRef,
|
80
69
|
shutdownChannel,
|
81
70
|
syncProcessor,
|
71
|
+
clientId,
|
72
|
+
devtools,
|
82
73
|
} = yield* LeaderThreadCtx
|
83
74
|
|
84
75
|
type RequestId = string
|
@@ -89,22 +80,22 @@ const listenToDevtools = ({
|
|
89
80
|
Effect.gen(function* () {
|
90
81
|
// yield* Effect.logDebug('[@livestore/common:leader-thread:devtools] incomingMessage', decodedEvent)
|
91
82
|
|
92
|
-
if (decodedEvent._tag === 'LSD.Disconnect') {
|
83
|
+
if (decodedEvent._tag === 'LSD.Leader.Disconnect') {
|
93
84
|
return
|
94
85
|
}
|
95
86
|
|
96
87
|
const { requestId } = decodedEvent
|
97
|
-
const reqPayload = { requestId, liveStoreVersion }
|
88
|
+
const reqPayload = { requestId, liveStoreVersion, clientId }
|
98
89
|
|
99
90
|
switch (decodedEvent._tag) {
|
100
|
-
case 'LSD.Ping': {
|
101
|
-
yield* sendMessage(Devtools.Pong.make({ ...reqPayload }))
|
91
|
+
case 'LSD.Leader.Ping': {
|
92
|
+
yield* sendMessage(Devtools.Leader.Pong.make({ ...reqPayload }))
|
102
93
|
return
|
103
94
|
}
|
104
95
|
case 'LSD.Leader.SnapshotReq': {
|
105
96
|
const snapshot = dbReadModel.export()
|
106
97
|
|
107
|
-
yield* sendMessage(Devtools.SnapshotRes.make({ snapshot, ...reqPayload }))
|
98
|
+
yield* sendMessage(Devtools.Leader.SnapshotRes.make({ snapshot, ...reqPayload }))
|
108
99
|
|
109
100
|
return
|
110
101
|
}
|
@@ -125,7 +116,9 @@ const listenToDevtools = ({
|
|
125
116
|
tmpDb.close()
|
126
117
|
} catch (e) {
|
127
118
|
yield* Effect.logError(`Error importing database file`, e)
|
128
|
-
yield* sendMessage(
|
119
|
+
yield* sendMessage(
|
120
|
+
Devtools.Leader.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-file' }),
|
121
|
+
)
|
129
122
|
|
130
123
|
return
|
131
124
|
}
|
@@ -143,17 +136,19 @@ const listenToDevtools = ({
|
|
143
136
|
|
144
137
|
dbMutationLog.destroy()
|
145
138
|
} else {
|
146
|
-
yield* sendMessage(
|
139
|
+
yield* sendMessage(
|
140
|
+
Devtools.Leader.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-database' }),
|
141
|
+
)
|
147
142
|
return
|
148
143
|
}
|
149
144
|
|
150
|
-
yield* sendMessage(Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'ok' }))
|
145
|
+
yield* sendMessage(Devtools.Leader.LoadDatabaseFileRes.make({ ...reqPayload, status: 'ok' }))
|
151
146
|
|
152
147
|
yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-import' })) ?? Effect.void
|
153
148
|
|
154
149
|
return
|
155
150
|
}
|
156
|
-
case 'LSD.Leader.
|
151
|
+
case 'LSD.Leader.ResetAllData.Request': {
|
157
152
|
const { mode } = decodedEvent
|
158
153
|
|
159
154
|
yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
|
@@ -164,7 +159,7 @@ const listenToDevtools = ({
|
|
164
159
|
dbMutationLog.destroy()
|
165
160
|
}
|
166
161
|
|
167
|
-
yield* sendMessage(Devtools.
|
162
|
+
yield* sendMessage(Devtools.Leader.ResetAllData.Response.make({ ...reqPayload }))
|
168
163
|
|
169
164
|
yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-reset' })) ?? Effect.void
|
170
165
|
|
@@ -181,7 +176,7 @@ const listenToDevtools = ({
|
|
181
176
|
const mutationLogFileSize = dbMutationLog.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
|
182
177
|
|
183
178
|
yield* sendMessage(
|
184
|
-
Devtools.DatabaseFileInfoRes.make({
|
179
|
+
Devtools.Leader.DatabaseFileInfoRes.make({
|
185
180
|
readModel: { fileSize: dbFileSize, persistenceInfo: persistenceInfo.readModel },
|
186
181
|
mutationLog: { fileSize: mutationLogFileSize, persistenceInfo: persistenceInfo.mutationLog },
|
187
182
|
...reqPayload,
|
@@ -193,14 +188,18 @@ const listenToDevtools = ({
|
|
193
188
|
case 'LSD.Leader.MutationLogReq': {
|
194
189
|
const mutationLog = dbMutationLog.export()
|
195
190
|
|
196
|
-
yield* sendMessage(Devtools.MutationLogRes.make({ mutationLog, ...reqPayload }))
|
191
|
+
yield* sendMessage(Devtools.Leader.MutationLogRes.make({ mutationLog, ...reqPayload }))
|
197
192
|
|
198
193
|
return
|
199
194
|
}
|
200
195
|
case 'LSD.Leader.RunMutationReq': {
|
201
|
-
yield* syncProcessor.pushPartial(
|
196
|
+
yield* syncProcessor.pushPartial({
|
197
|
+
mutationEvent: decodedEvent.mutationEventEncoded,
|
198
|
+
clientId: `devtools-${clientId}`,
|
199
|
+
sessionId: undefined,
|
200
|
+
})
|
202
201
|
|
203
|
-
yield* sendMessage(Devtools.RunMutationRes.make({ ...reqPayload }))
|
202
|
+
yield* sendMessage(Devtools.Leader.RunMutationRes.make({ ...reqPayload }))
|
204
203
|
|
205
204
|
return
|
206
205
|
}
|
@@ -213,7 +212,7 @@ const listenToDevtools = ({
|
|
213
212
|
Stream.map((_) => _.batch),
|
214
213
|
Stream.flattenIterables,
|
215
214
|
Stream.tap(({ mutationEventEncoded, metadata }) =>
|
216
|
-
sendMessage(Devtools.SyncHistoryRes.make({ mutationEventEncoded, metadata, ...reqPayload })),
|
215
|
+
sendMessage(Devtools.Leader.SyncHistoryRes.make({ mutationEventEncoded, metadata, ...reqPayload })),
|
217
216
|
),
|
218
217
|
Stream.runDrain,
|
219
218
|
Effect.acquireRelease(() => Effect.log('syncHistorySubscribe done')),
|
@@ -234,12 +233,12 @@ const listenToDevtools = ({
|
|
234
233
|
return
|
235
234
|
}
|
236
235
|
case 'LSD.Leader.SyncingInfoReq': {
|
237
|
-
const syncingInfo = Devtools.SyncingInfo.make({
|
236
|
+
const syncingInfo = Devtools.Leader.SyncingInfo.make({
|
238
237
|
enabled: syncBackend !== undefined,
|
239
238
|
metadata: {},
|
240
239
|
})
|
241
240
|
|
242
|
-
yield* sendMessage(Devtools.SyncingInfoRes.make({ syncingInfo, ...reqPayload }))
|
241
|
+
yield* sendMessage(Devtools.Leader.SyncingInfoRes.make({ syncingInfo, ...reqPayload }))
|
243
242
|
|
244
243
|
return
|
245
244
|
}
|
@@ -252,11 +251,14 @@ const listenToDevtools = ({
|
|
252
251
|
// This is probably the same "flaky databrowser loading" bug as we're seeing in the playwright tests
|
253
252
|
yield* Effect.sleep(1000)
|
254
253
|
|
255
|
-
yield*
|
256
|
-
|
254
|
+
yield* Stream.zipLatest(
|
255
|
+
syncBackend.isConnected.changes,
|
256
|
+
devtools.enabled ? devtools.syncBackendLatchState.changes : Stream.make({ latchClosed: false }),
|
257
|
+
).pipe(
|
258
|
+
Stream.tap(([isConnected, { latchClosed }]) =>
|
257
259
|
sendMessage(
|
258
|
-
Devtools.NetworkStatusRes.make({
|
259
|
-
networkStatus: { isConnected, timestampMs: Date.now() },
|
260
|
+
Devtools.Leader.NetworkStatusRes.make({
|
261
|
+
networkStatus: { isConnected, timestampMs: Date.now(), latchClosed },
|
260
262
|
...reqPayload,
|
261
263
|
}),
|
262
264
|
),
|
@@ -277,6 +279,54 @@ const listenToDevtools = ({
|
|
277
279
|
|
278
280
|
return
|
279
281
|
}
|
282
|
+
case 'LSD.Leader.SyncHeadSubscribe': {
|
283
|
+
const { requestId } = decodedEvent
|
284
|
+
|
285
|
+
yield* syncProcessor.syncState.changes.pipe(
|
286
|
+
Stream.tap((syncState) =>
|
287
|
+
sendMessage(
|
288
|
+
Devtools.Leader.SyncHeadRes.make({
|
289
|
+
local: syncState.localHead,
|
290
|
+
upstream: syncState.upstreamHead,
|
291
|
+
...reqPayload,
|
292
|
+
}),
|
293
|
+
),
|
294
|
+
),
|
295
|
+
Stream.runDrain,
|
296
|
+
Effect.interruptible,
|
297
|
+
Effect.tapCauseLogPretty,
|
298
|
+
FiberMap.run(subscriptionFiberMap, requestId),
|
299
|
+
)
|
300
|
+
|
301
|
+
return
|
302
|
+
}
|
303
|
+
case 'LSD.Leader.SyncHeadUnsubscribe': {
|
304
|
+
const { requestId } = decodedEvent
|
305
|
+
|
306
|
+
yield* FiberMap.remove(subscriptionFiberMap, requestId)
|
307
|
+
|
308
|
+
return
|
309
|
+
}
|
310
|
+
case 'LSD.Leader.SetSyncLatch.Request': {
|
311
|
+
const { closeLatch } = decodedEvent
|
312
|
+
|
313
|
+
if (devtools.enabled === false) return
|
314
|
+
|
315
|
+
if (closeLatch === true) {
|
316
|
+
yield* devtools.syncBackendLatch.close
|
317
|
+
} else {
|
318
|
+
yield* devtools.syncBackendLatch.open
|
319
|
+
}
|
320
|
+
|
321
|
+
yield* SubscriptionRef.set(devtools.syncBackendLatchState, { latchClosed: closeLatch })
|
322
|
+
|
323
|
+
yield* sendMessage(Devtools.Leader.SetSyncLatch.Response.make({ ...reqPayload }))
|
324
|
+
|
325
|
+
return
|
326
|
+
}
|
327
|
+
default: {
|
328
|
+
yield* Effect.logWarning(`TODO implement devtools message`, decodedEvent)
|
329
|
+
}
|
280
330
|
}
|
281
331
|
}).pipe(Effect.withSpan(`@livestore/common:leader-thread:onDevtoolsMessage:${decodedEvent._tag}`)),
|
282
332
|
),
|