@livestore/common 0.3.0-dev.47 → 0.3.0-dev.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapter-types.d.ts +8 -6
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +2 -2
- package/dist/adapter-types.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +25 -25
- package/dist/devtools/devtools-messages-client-session.js +3 -3
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +30 -30
- package/dist/devtools/devtools-messages-leader.js +3 -3
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +27 -25
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +10 -10
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +24 -24
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +1 -1
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/materialize-event.d.ts +3 -3
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +19 -15
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/types.d.ts +4 -4
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/make-client-session.d.ts +1 -1
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +2 -1
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +4 -2
- package/dist/materializer-helper.js.map +1 -1
- package/dist/rematerialize-from-eventlog.js +9 -9
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventId.d.ts +28 -28
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +9 -9
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/EventId.test.js +5 -5
- package/dist/schema/EventId.test.js.map +1 -1
- package/dist/schema/EventNumber.d.ts +57 -0
- package/dist/schema/EventNumber.d.ts.map +1 -0
- package/dist/schema/EventNumber.js +82 -0
- package/dist/schema/EventNumber.js.map +1 -0
- package/dist/schema/EventNumber.test.d.ts +2 -0
- package/dist/schema/EventNumber.test.d.ts.map +1 -0
- package/dist/schema/EventNumber.test.js +11 -0
- package/dist/schema/EventNumber.test.js.map +1 -0
- package/dist/schema/EventSequenceNumber.d.ts +57 -0
- package/dist/schema/EventSequenceNumber.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber.js +82 -0
- package/dist/schema/EventSequenceNumber.js.map +1 -0
- package/dist/schema/EventSequenceNumber.test.d.ts +2 -0
- package/dist/schema/EventSequenceNumber.test.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber.test.js +11 -0
- package/dist/schema/EventSequenceNumber.test.js.map +1 -0
- package/dist/schema/LiveStoreEvent.d.ts +81 -79
- package/dist/schema/LiveStoreEvent.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent.js +31 -32
- package/dist/schema/LiveStoreEvent.js.map +1 -1
- package/dist/schema/mod.d.ts +1 -1
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +1 -1
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +2 -2
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +3 -3
- package/dist/schema/state/sqlite/query-builder/impl.test.js +9 -0
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables.d.ts +52 -52
- package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -1
- package/dist/schema/state/sqlite/system-tables.js +11 -10
- package/dist/schema/state/sqlite/system-tables.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +6 -6
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/next/compact-events.js +38 -35
- package/dist/sync/next/compact-events.js.map +1 -1
- package/dist/sync/next/facts.d.ts +4 -4
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +8 -8
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +4 -4
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +7 -4
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.d.ts +0 -2
- package/dist/sync/next/history-dag.d.ts.map +1 -1
- package/dist/sync/next/history-dag.js +15 -13
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +10 -4
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +13 -13
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +31 -31
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts +10 -0
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +19 -13
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync.d.ts +11 -11
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js +5 -5
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +18 -18
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +46 -47
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +110 -110
- 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 +4 -4
- package/dist/sync/validate-push-payload.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/package.json +4 -4
- package/src/adapter-types.ts +6 -4
- package/src/devtools/devtools-messages-client-session.ts +3 -3
- package/src/devtools/devtools-messages-leader.ts +3 -3
- package/src/leader-thread/LeaderSyncProcessor.ts +36 -29
- package/src/leader-thread/eventlog.ts +36 -31
- package/src/leader-thread/leader-worker-devtools.ts +1 -1
- package/src/leader-thread/materialize-event.ts +21 -17
- package/src/leader-thread/types.ts +4 -4
- package/src/make-client-session.ts +2 -0
- package/src/materializer-helper.ts +5 -2
- package/src/rematerialize-from-eventlog.ts +10 -10
- package/src/schema/EventSequenceNumber.test.ts +12 -0
- package/src/schema/EventSequenceNumber.ts +121 -0
- package/src/schema/LiveStoreEvent.ts +66 -65
- package/src/schema/mod.ts +1 -1
- package/src/schema/state/sqlite/query-builder/impl.test.ts +9 -0
- package/src/schema/state/sqlite/query-builder/impl.ts +3 -2
- package/src/schema/state/sqlite/system-tables.ts +11 -10
- package/src/sync/ClientSessionSyncProcessor.ts +6 -6
- package/src/sync/next/compact-events.ts +38 -35
- package/src/sync/next/facts.ts +12 -9
- package/src/sync/next/history-dag-common.ts +9 -6
- package/src/sync/next/history-dag.ts +15 -16
- package/src/sync/next/rebase-events.ts +10 -4
- package/src/sync/next/test/compact-events.calculator.test.ts +13 -13
- package/src/sync/next/test/compact-events.test.ts +31 -31
- package/src/sync/next/test/event-fixtures.ts +20 -13
- package/src/sync/sync.ts +7 -7
- package/src/sync/syncstate.test.ts +112 -112
- package/src/sync/syncstate.ts +58 -48
- package/src/sync/validate-push-payload.ts +5 -5
- package/src/version.ts +2 -2
- package/src/schema/EventId.test.ts +0 -12
- package/src/schema/EventId.ts +0 -106
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"validate-push-payload.js","sourceRoot":"","sources":["../../src/sync/validate-push-payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,+BAA+B;AAC/B,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,KAAqD,EACrD,
|
1
|
+
{"version":3,"file":"validate-push-payload.js","sourceRoot":"","sources":["../../src/sync/validate-push-payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,+BAA+B;AAC/B,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,KAAqD,EACrD,0BAAyE,EACzE,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM,IAAI,0BAA0B,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC;YAClC,MAAM,EAAE;gBACN,IAAI,EAAE,aAAa;gBACnB,kBAAkB,EAAE,0BAA0B,GAAG,CAAC;gBAClD,WAAW,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM;aAC9B;SACF,CAAC,CAAA;IACJ,CAAC;AACH,CAAC,CAAC,CAAA"}
|
package/dist/version.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
export declare const liveStoreVersion: "0.3.0-dev.
|
1
|
+
export declare const liveStoreVersion: "0.3.0-dev.48";
|
2
2
|
/**
|
3
3
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|
4
4
|
* Whenever this version changes, LiveStore will start with fresh database files. Old database files are not deleted.
|
@@ -6,5 +6,5 @@ export declare const liveStoreVersion: "0.3.0-dev.47";
|
|
6
6
|
* While LiveStore is in alpha, this might happen more frequently.
|
7
7
|
* In the future, LiveStore will provide a migration path for older database files to avoid the impression of data loss.
|
8
8
|
*/
|
9
|
-
export declare const liveStoreStorageFormatVersion =
|
9
|
+
export declare const liveStoreStorageFormatVersion = 4;
|
10
10
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// TODO bring back when Expo and Playwright supports `with` imports
|
2
2
|
// import packageJson from '../package.json' with { type: 'json' }
|
3
3
|
// export const liveStoreVersion = packageJson.version
|
4
|
-
export const liveStoreVersion = '0.3.0-dev.
|
4
|
+
export const liveStoreVersion = '0.3.0-dev.48';
|
5
5
|
/**
|
6
6
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|
7
7
|
* Whenever this version changes, LiveStore will start with fresh database files. Old database files are not deleted.
|
@@ -9,5 +9,5 @@ export const liveStoreVersion = '0.3.0-dev.47';
|
|
9
9
|
* While LiveStore is in alpha, this might happen more frequently.
|
10
10
|
* In the future, LiveStore will provide a migration path for older database files to avoid the impression of data loss.
|
11
11
|
*/
|
12
|
-
export const liveStoreStorageFormatVersion =
|
12
|
+
export const liveStoreStorageFormatVersion = 4;
|
13
13
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@livestore/common",
|
3
|
-
"version": "0.3.0-dev.
|
3
|
+
"version": "0.3.0-dev.48",
|
4
4
|
"type": "module",
|
5
5
|
"sideEffects": false,
|
6
6
|
"exports": {
|
@@ -54,12 +54,12 @@
|
|
54
54
|
"graphology": "0.26.0-alpha1",
|
55
55
|
"graphology-dag": "0.4.1",
|
56
56
|
"graphology-types": "0.24.8",
|
57
|
-
"@livestore/utils": "0.3.0-dev.
|
58
|
-
"@livestore/webmesh": "0.3.0-dev.
|
57
|
+
"@livestore/utils": "0.3.0-dev.48",
|
58
|
+
"@livestore/webmesh": "0.3.0-dev.48"
|
59
59
|
},
|
60
60
|
"devDependencies": {
|
61
61
|
"vitest": "^3.1.2",
|
62
|
-
"@livestore/utils-dev": "0.3.0-dev.
|
62
|
+
"@livestore/utils-dev": "0.3.0-dev.48"
|
63
63
|
},
|
64
64
|
"files": [
|
65
65
|
"package.json",
|
package/src/adapter-types.ts
CHANGED
@@ -2,7 +2,7 @@ import type { Cause, Queue, Scope, SubscriptionRef, WebChannel } from '@livestor
|
|
2
2
|
import { Effect, Schema, Stream } from '@livestore/utils/effect'
|
3
3
|
|
4
4
|
import type * as Devtools from './devtools/mod.js'
|
5
|
-
import * as
|
5
|
+
import * as EventSequenceNumber from './schema/EventSequenceNumber.js'
|
6
6
|
import type { LiveStoreEvent, LiveStoreSchema } from './schema/mod.js'
|
7
7
|
import type { LeaderAheadError } from './sync/sync.js'
|
8
8
|
import type { PayloadUpstream, SyncState } from './sync/syncstate.js'
|
@@ -37,11 +37,13 @@ export interface ClientSession {
|
|
37
37
|
shutdown: (cause: Cause.Cause<UnexpectedError | IntentionalShutdownCause>) => Effect.Effect<void>
|
38
38
|
/** A proxy API to communicate with the leader thread */
|
39
39
|
leaderThread: ClientSessionLeaderThreadProxy
|
40
|
+
/** A unique identifier for the current instance of the client session. Used for debugging purposes. */
|
41
|
+
debugInstanceId: string
|
40
42
|
}
|
41
43
|
|
42
44
|
export const LeaderPullCursor = Schema.Struct({
|
43
45
|
mergeCounter: Schema.Number,
|
44
|
-
|
46
|
+
eventNum: EventSequenceNumber.EventSequenceNumber,
|
45
47
|
})
|
46
48
|
|
47
49
|
export type LeaderPullCursor = typeof LeaderPullCursor.Type
|
@@ -56,8 +58,8 @@ export interface ClientSessionLeaderThreadProxy {
|
|
56
58
|
}
|
57
59
|
/** The initial state after the leader thread has booted */
|
58
60
|
readonly initialState: {
|
59
|
-
/** The latest
|
60
|
-
readonly leaderHead:
|
61
|
+
/** The latest event sequence number during boot. Used for the client session to resume syncing. */
|
62
|
+
readonly leaderHead: EventSequenceNumber.EventSequenceNumber
|
61
63
|
/** The migrations report from the leader thread */
|
62
64
|
readonly migrationsReport: MigrationsReport
|
63
65
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Schema } from '@livestore/utils/effect'
|
2
2
|
|
3
3
|
import { DebugInfo } from '../debug-info.js'
|
4
|
-
import {
|
4
|
+
import { EventSequenceNumber } from '../schema/mod.js'
|
5
5
|
import { PreparedBindValues } from '../util.js'
|
6
6
|
import { LSDClientSessionChannelMessage, LSDClientSessionReqResMessage } from './devtools-messages-common.js'
|
7
7
|
|
@@ -52,8 +52,8 @@ export class SyncHeadUnsubscribe extends LSDClientSessionReqResMessage('LSD.Clie
|
|
52
52
|
subscriptionId: Schema.String,
|
53
53
|
}) {}
|
54
54
|
export class SyncHeadRes extends LSDClientSessionReqResMessage('LSD.ClientSession.SyncHeadRes', {
|
55
|
-
local:
|
56
|
-
upstream:
|
55
|
+
local: EventSequenceNumber.EventSequenceNumber,
|
56
|
+
upstream: EventSequenceNumber.EventSequenceNumber,
|
57
57
|
subscriptionId: Schema.String,
|
58
58
|
}) {}
|
59
59
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Schema, Transferable } from '@livestore/utils/effect'
|
2
2
|
|
3
3
|
import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
|
4
|
-
import {
|
4
|
+
import { EventSequenceNumber } from '../schema/mod.js'
|
5
5
|
import * as SyncState from '../sync/syncstate.js'
|
6
6
|
import { LeaderReqResMessage, LSDMessage, LSDReqResMessage, NetworkStatus } from './devtools-messages-common.js'
|
7
7
|
|
@@ -63,8 +63,8 @@ export class SyncHeadUnsubscribe extends LSDReqResMessage('LSD.Leader.SyncHeadUn
|
|
63
63
|
subscriptionId: Schema.String,
|
64
64
|
}) {}
|
65
65
|
export class SyncHeadRes extends LSDReqResMessage('LSD.Leader.SyncHeadRes', {
|
66
|
-
local:
|
67
|
-
upstream:
|
66
|
+
local: EventSequenceNumber.EventSequenceNumber,
|
67
|
+
upstream: EventSequenceNumber.EventSequenceNumber,
|
68
68
|
subscriptionId: Schema.String,
|
69
69
|
}) {}
|
70
70
|
|
@@ -18,7 +18,7 @@ import type * as otel from '@opentelemetry/api'
|
|
18
18
|
import type { SqliteDb } from '../adapter-types.js'
|
19
19
|
import { UnexpectedError } from '../adapter-types.js'
|
20
20
|
import type { LiveStoreSchema } from '../schema/mod.js'
|
21
|
-
import {
|
21
|
+
import { EventSequenceNumber, getEventDef, LiveStoreEvent, SystemTables } from '../schema/mod.js'
|
22
22
|
import { LeaderAheadError } from '../sync/sync.js'
|
23
23
|
import * as SyncState from '../sync/syncstate.js'
|
24
24
|
import { sql } from '../util.js'
|
@@ -118,7 +118,7 @@ export const makeLeaderSyncProcessor = ({
|
|
118
118
|
* If a local-push batch is rejected, all subsequent push queue items with the same generation are also rejected,
|
119
119
|
* even if they would be valid on their own.
|
120
120
|
*/
|
121
|
-
// TODO get rid of this in favour of the `mergeGeneration` event
|
121
|
+
// TODO get rid of this in favour of the `mergeGeneration` event sequence number field
|
122
122
|
const currentLocalPushGenerationRef = { current: 0 }
|
123
123
|
|
124
124
|
type MergeCounter = number
|
@@ -150,9 +150,9 @@ export const makeLeaderSyncProcessor = ({
|
|
150
150
|
*
|
151
151
|
* Thus the purpoe of the pushHeadRef is the guard the integrity of the local push queue
|
152
152
|
*/
|
153
|
-
const pushHeadRef = { current:
|
154
|
-
const advancePushHead = (
|
155
|
-
pushHeadRef.current =
|
153
|
+
const pushHeadRef = { current: EventSequenceNumber.ROOT }
|
154
|
+
const advancePushHead = (eventNum: EventSequenceNumber.EventSequenceNumber) => {
|
155
|
+
pushHeadRef.current = EventSequenceNumber.max(pushHeadRef.current, eventNum)
|
156
156
|
}
|
157
157
|
|
158
158
|
// NOTE: New events are only pushed to sync backend after successful local push processing
|
@@ -162,7 +162,7 @@ export const makeLeaderSyncProcessor = ({
|
|
162
162
|
|
163
163
|
yield* validatePushBatch(newEvents, pushHeadRef.current)
|
164
164
|
|
165
|
-
advancePushHead(newEvents.at(-1)!.
|
165
|
+
advancePushHead(newEvents.at(-1)!.seqNum)
|
166
166
|
|
167
167
|
const waitForProcessing = options?.waitForProcessing ?? false
|
168
168
|
const generation = currentLocalPushGenerationRef.current
|
@@ -203,7 +203,7 @@ export const makeLeaderSyncProcessor = ({
|
|
203
203
|
args,
|
204
204
|
clientId,
|
205
205
|
sessionId,
|
206
|
-
...
|
206
|
+
...EventSequenceNumber.nextPair(syncState.localHead, eventDef.options.clientOnly),
|
207
207
|
})
|
208
208
|
|
209
209
|
yield* push([eventEncoded])
|
@@ -223,9 +223,11 @@ export const makeLeaderSyncProcessor = ({
|
|
223
223
|
runtime,
|
224
224
|
}
|
225
225
|
|
226
|
-
const initialLocalHead = dbEventlogMissing ?
|
226
|
+
const initialLocalHead = dbEventlogMissing ? EventSequenceNumber.ROOT : Eventlog.getClientHeadFromDb(dbEventlog)
|
227
227
|
|
228
|
-
const initialBackendHead = dbEventlogMissing
|
228
|
+
const initialBackendHead = dbEventlogMissing
|
229
|
+
? EventSequenceNumber.ROOT.global
|
230
|
+
: Eventlog.getBackendHeadFromDb(dbEventlog)
|
229
231
|
|
230
232
|
if (initialBackendHead > initialLocalHead.global) {
|
231
233
|
return shouldNeverHappen(
|
@@ -235,11 +237,11 @@ export const makeLeaderSyncProcessor = ({
|
|
235
237
|
|
236
238
|
const pendingEvents = dbEventlogMissing
|
237
239
|
? []
|
238
|
-
: yield* Eventlog.getEventsSince({ global: initialBackendHead, client:
|
240
|
+
: yield* Eventlog.getEventsSince({ global: initialBackendHead, client: EventSequenceNumber.clientDefault })
|
239
241
|
|
240
242
|
const initialSyncState = new SyncState.SyncState({
|
241
243
|
pending: pendingEvents,
|
242
|
-
upstreamHead: { global: initialBackendHead, client:
|
244
|
+
upstreamHead: { global: initialBackendHead, client: EventSequenceNumber.clientDefault },
|
243
245
|
localHead: initialLocalHead,
|
244
246
|
})
|
245
247
|
|
@@ -347,7 +349,7 @@ export const makeLeaderSyncProcessor = ({
|
|
347
349
|
payload: {
|
348
350
|
_tag: 'upstream-advance' as const,
|
349
351
|
newEvents: ReadonlyArray.dropWhile(payload.newEvents, (eventEncoded) =>
|
350
|
-
|
352
|
+
EventSequenceNumber.isGreaterThanOrEqual(cursor.eventNum, eventEncoded.seqNum),
|
351
353
|
),
|
352
354
|
},
|
353
355
|
mergeCounter,
|
@@ -479,7 +481,7 @@ const backgroundApplyLocalPushes = ({
|
|
479
481
|
|
480
482
|
const nextGeneration = currentLocalPushGenerationRef.current
|
481
483
|
|
482
|
-
const
|
484
|
+
const providedNum = newEvents.at(0)!.seqNum
|
483
485
|
// All subsequent pushes with same generation should be rejected as well
|
484
486
|
// We're also handling the case where the localPushQueue already contains events
|
485
487
|
// from the next generation which we preserve in the queue
|
@@ -503,8 +505,8 @@ const backgroundApplyLocalPushes = ({
|
|
503
505
|
Deferred.fail(
|
504
506
|
deferred,
|
505
507
|
LeaderAheadError.make({
|
506
|
-
|
507
|
-
|
508
|
+
minimumExpectedNum: mergeResult.expectedMinimumId,
|
509
|
+
providedNum,
|
508
510
|
// nextGeneration,
|
509
511
|
}),
|
510
512
|
),
|
@@ -617,7 +619,7 @@ const backgroundBackendPulling = ({
|
|
617
619
|
mergePayloads,
|
618
620
|
advancePushHead,
|
619
621
|
}: {
|
620
|
-
initialBackendHead:
|
622
|
+
initialBackendHead: EventSequenceNumber.GlobalEventSequenceNumber
|
621
623
|
isClientEvent: (eventEncoded: LiveStoreEvent.EncodedWithMeta) => boolean
|
622
624
|
restartBackendPushing: (
|
623
625
|
filteredRebasedPending: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
@@ -631,7 +633,7 @@ const backgroundBackendPulling = ({
|
|
631
633
|
connectedClientSessionPullQueues: PullQueueSet
|
632
634
|
mergeCounterRef: { current: number }
|
633
635
|
mergePayloads: Map<number, typeof SyncState.PayloadUpstream.Type>
|
634
|
-
advancePushHead: (
|
636
|
+
advancePushHead: (eventNum: EventSequenceNumber.EventSequenceNumber) => void
|
635
637
|
}) =>
|
636
638
|
Effect.gen(function* () {
|
637
639
|
const { syncBackend, dbState: db, dbEventlog, schema } = yield* LeaderThreadCtx
|
@@ -675,7 +677,7 @@ const backgroundBackendPulling = ({
|
|
675
677
|
return yield* Effect.fail(mergeResult.cause)
|
676
678
|
}
|
677
679
|
|
678
|
-
const newBackendHead = newEvents.at(-1)!.
|
680
|
+
const newBackendHead = newEvents.at(-1)!.seqNum
|
679
681
|
|
680
682
|
Eventlog.updateBackendHead(dbEventlog, newBackendHead)
|
681
683
|
|
@@ -697,7 +699,7 @@ const backgroundBackendPulling = ({
|
|
697
699
|
yield* rollback({
|
698
700
|
dbState: db,
|
699
701
|
dbEventlog,
|
700
|
-
|
702
|
+
eventNumsToRollback: mergeResult.rollbackEvents.map((_) => _.seqNum),
|
701
703
|
})
|
702
704
|
}
|
703
705
|
|
@@ -731,7 +733,9 @@ const backgroundBackendPulling = ({
|
|
731
733
|
// `mergeResult.confirmedEvents` don't contain the correct sync metadata, so we need to use
|
732
734
|
// `newEvents` instead which we filter via `mergeResult.confirmedEvents`
|
733
735
|
const confirmedNewEvents = newEvents.filter((event) =>
|
734
|
-
mergeResult.confirmedEvents.some((confirmedEvent) =>
|
736
|
+
mergeResult.confirmedEvents.some((confirmedEvent) =>
|
737
|
+
EventSequenceNumber.isEqual(event.seqNum, confirmedEvent.seqNum),
|
738
|
+
),
|
735
739
|
)
|
736
740
|
yield* Eventlog.updateSyncMetadata(confirmedNewEvents)
|
737
741
|
}
|
@@ -828,10 +832,10 @@ const backgroundBackendPushing = ({
|
|
828
832
|
}
|
829
833
|
}).pipe(Effect.interruptible, Effect.withSpan('@livestore/common:LeaderSyncProcessor:backend-pushing'))
|
830
834
|
|
831
|
-
const trimChangesetRows = (db: SqliteDb, newHead:
|
835
|
+
const trimChangesetRows = (db: SqliteDb, newHead: EventSequenceNumber.EventSequenceNumber) => {
|
832
836
|
// Since we're using the session changeset rows to query for the current head,
|
833
837
|
// we're keeping at least one row for the current head, and thus are using `<` instead of `<=`
|
834
|
-
db.execute(sql`DELETE FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE
|
838
|
+
db.execute(sql`DELETE FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE seqNumGlobal < ${newHead.global}`)
|
835
839
|
}
|
836
840
|
|
837
841
|
interface PullQueueSet {
|
@@ -908,7 +912,10 @@ const getMergeCounterFromDb = (dbState: SqliteDb) =>
|
|
908
912
|
return result[0]?.mergeCounter ?? 0
|
909
913
|
})
|
910
914
|
|
911
|
-
const validatePushBatch = (
|
915
|
+
const validatePushBatch = (
|
916
|
+
batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
917
|
+
pushHead: EventSequenceNumber.EventSequenceNumber,
|
918
|
+
) =>
|
912
919
|
Effect.gen(function* () {
|
913
920
|
if (batch.length === 0) {
|
914
921
|
return
|
@@ -916,18 +923,18 @@ const validatePushBatch = (batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
|
|
916
923
|
|
917
924
|
// Make sure batch is monotonically increasing
|
918
925
|
for (let i = 1; i < batch.length; i++) {
|
919
|
-
if (
|
926
|
+
if (EventSequenceNumber.isGreaterThanOrEqual(batch[i - 1]!.seqNum, batch[i]!.seqNum)) {
|
920
927
|
shouldNeverHappen(
|
921
|
-
`Events must be ordered in monotonically ascending order by
|
928
|
+
`Events must be ordered in monotonically ascending order by eventNum. Received: [${batch.map((e) => EventSequenceNumber.toString(e.seqNum)).join(', ')}]`,
|
922
929
|
)
|
923
930
|
}
|
924
931
|
}
|
925
932
|
|
926
|
-
// Make sure smallest
|
927
|
-
if (
|
933
|
+
// Make sure smallest sequence number is > pushHead
|
934
|
+
if (EventSequenceNumber.isGreaterThanOrEqual(pushHead, batch[0]!.seqNum)) {
|
928
935
|
return yield* LeaderAheadError.make({
|
929
|
-
|
930
|
-
|
936
|
+
minimumExpectedNum: pushHead,
|
937
|
+
providedNum: batch[0]!.seqNum,
|
931
938
|
})
|
932
939
|
}
|
933
940
|
})
|
@@ -2,7 +2,7 @@ import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
|
|
2
2
|
import { Effect, Option, Schema } from '@livestore/utils/effect'
|
3
3
|
|
4
4
|
import type { SqliteDb } from '../adapter-types.js'
|
5
|
-
import * as
|
5
|
+
import * as EventSequenceNumber from '../schema/EventSequenceNumber.js'
|
6
6
|
import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
|
7
7
|
import {
|
8
8
|
EVENTLOG_META_TABLE,
|
@@ -34,7 +34,7 @@ export const initEventlogDb = (dbEventlog: SqliteDb) =>
|
|
34
34
|
yield* execSql(
|
35
35
|
dbEventlog,
|
36
36
|
sql`INSERT INTO ${SYNC_STATUS_TABLE} (head)
|
37
|
-
SELECT ${
|
37
|
+
SELECT ${EventSequenceNumber.ROOT.global}
|
38
38
|
WHERE NOT EXISTS (SELECT 1 FROM ${SYNC_STATUS_TABLE})`,
|
39
39
|
{},
|
40
40
|
)
|
@@ -42,16 +42,16 @@ export const initEventlogDb = (dbEventlog: SqliteDb) =>
|
|
42
42
|
|
43
43
|
/** Exclusive of the "since event" */
|
44
44
|
export const getEventsSince = (
|
45
|
-
since:
|
45
|
+
since: EventSequenceNumber.EventSequenceNumber,
|
46
46
|
): Effect.Effect<ReadonlyArray<LiveStoreEvent.EncodedWithMeta>, never, LeaderThreadCtx> =>
|
47
47
|
Effect.gen(function* () {
|
48
48
|
const { dbEventlog, dbState } = yield* LeaderThreadCtx
|
49
49
|
|
50
|
-
const query = eventlogMetaTable.where('
|
50
|
+
const query = eventlogMetaTable.where('seqNumGlobal', '>=', since.global).asSql()
|
51
51
|
const pendingEventsRaw = dbEventlog.select(query.query, prepareBindValues(query.bindValues, query.query))
|
52
52
|
const pendingEvents = Schema.decodeUnknownSync(eventlogMetaTable.rowSchema.pipe(Schema.Array))(pendingEventsRaw)
|
53
53
|
|
54
|
-
const sessionChangesetRows = sessionChangesetMetaTable.where('
|
54
|
+
const sessionChangesetRows = sessionChangesetMetaTable.where('seqNumGlobal', '>=', since.global).asSql()
|
55
55
|
const sessionChangesetRowsRaw = dbState.select(
|
56
56
|
sessionChangesetRows.query,
|
57
57
|
prepareBindValues(sessionChangesetRows.bindValues, sessionChangesetRows.query),
|
@@ -64,13 +64,14 @@ export const getEventsSince = (
|
|
64
64
|
.map((eventlogEvent) => {
|
65
65
|
const sessionChangeset = sessionChangesetRowsDecoded.find(
|
66
66
|
(readModelEvent) =>
|
67
|
-
readModelEvent.
|
67
|
+
readModelEvent.seqNumGlobal === eventlogEvent.seqNumGlobal &&
|
68
|
+
readModelEvent.seqNumClient === eventlogEvent.seqNumClient,
|
68
69
|
)
|
69
70
|
return LiveStoreEvent.EncodedWithMeta.make({
|
70
71
|
name: eventlogEvent.name,
|
71
72
|
args: eventlogEvent.argsJson,
|
72
|
-
|
73
|
-
|
73
|
+
seqNum: { global: eventlogEvent.seqNumGlobal, client: eventlogEvent.seqNumClient },
|
74
|
+
parentSeqNum: { global: eventlogEvent.parentSeqNumGlobal, client: eventlogEvent.parentSeqNumClient },
|
74
75
|
clientId: eventlogEvent.clientId,
|
75
76
|
sessionId: eventlogEvent.sessionId,
|
76
77
|
meta: {
|
@@ -86,24 +87,28 @@ export const getEventsSince = (
|
|
86
87
|
},
|
87
88
|
})
|
88
89
|
})
|
89
|
-
.filter((_) =>
|
90
|
-
.sort((a, b) =>
|
90
|
+
.filter((_) => EventSequenceNumber.compare(_.seqNum, since) > 0)
|
91
|
+
.sort((a, b) => EventSequenceNumber.compare(a.seqNum, b.seqNum))
|
91
92
|
})
|
92
93
|
|
93
|
-
export const getClientHeadFromDb = (dbEventlog: SqliteDb):
|
94
|
-
const res = dbEventlog.select<{
|
95
|
-
|
94
|
+
export const getClientHeadFromDb = (dbEventlog: SqliteDb): EventSequenceNumber.EventSequenceNumber => {
|
95
|
+
const res = dbEventlog.select<{
|
96
|
+
seqNumGlobal: EventSequenceNumber.GlobalEventSequenceNumber
|
97
|
+
seqNumClient: EventSequenceNumber.ClientEventSequenceNumber
|
98
|
+
}>(
|
99
|
+
sql`select seqNumGlobal, seqNumClient from ${EVENTLOG_META_TABLE} order by seqNumGlobal DESC, seqNumClient DESC limit 1`,
|
96
100
|
)[0]
|
97
101
|
|
98
|
-
return res ? { global: res.
|
102
|
+
return res ? { global: res.seqNumGlobal, client: res.seqNumClient } : EventSequenceNumber.ROOT
|
99
103
|
}
|
100
104
|
|
101
|
-
export const getBackendHeadFromDb = (dbEventlog: SqliteDb):
|
102
|
-
dbEventlog.select<{ head:
|
103
|
-
|
105
|
+
export const getBackendHeadFromDb = (dbEventlog: SqliteDb): EventSequenceNumber.GlobalEventSequenceNumber =>
|
106
|
+
dbEventlog.select<{ head: EventSequenceNumber.GlobalEventSequenceNumber }>(
|
107
|
+
sql`select head from ${SYNC_STATUS_TABLE}`,
|
108
|
+
)[0]?.head ?? EventSequenceNumber.ROOT.global
|
104
109
|
|
105
110
|
// TODO use prepared statements
|
106
|
-
export const updateBackendHead = (dbEventlog: SqliteDb, head:
|
111
|
+
export const updateBackendHead = (dbEventlog: SqliteDb, head: EventSequenceNumber.EventSequenceNumber) =>
|
107
112
|
dbEventlog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
|
108
113
|
|
109
114
|
export const insertIntoEventlog = (
|
@@ -115,16 +120,16 @@ export const insertIntoEventlog = (
|
|
115
120
|
) =>
|
116
121
|
Effect.gen(function* () {
|
117
122
|
// Check history consistency during LS_DEV
|
118
|
-
if (LS_DEV && eventEncoded.
|
123
|
+
if (LS_DEV && eventEncoded.parentSeqNum.global !== EventSequenceNumber.ROOT.global) {
|
119
124
|
const parentEventExists =
|
120
125
|
dbEventlog.select<{ count: number }>(
|
121
|
-
`SELECT COUNT(*) as count FROM ${EVENTLOG_META_TABLE} WHERE
|
122
|
-
[eventEncoded.
|
126
|
+
`SELECT COUNT(*) as count FROM ${EVENTLOG_META_TABLE} WHERE seqNumGlobal = ? AND seqNumClient = ?`,
|
127
|
+
[eventEncoded.parentSeqNum.global, eventEncoded.parentSeqNum.client] as any as PreparedBindValues,
|
123
128
|
)[0]!.count === 1
|
124
129
|
|
125
130
|
if (parentEventExists === false) {
|
126
131
|
shouldNeverHappen(
|
127
|
-
`Parent mutation ${eventEncoded.
|
132
|
+
`Parent mutation ${eventEncoded.parentSeqNum.global},${eventEncoded.parentSeqNum.client} does not exist`,
|
128
133
|
)
|
129
134
|
}
|
130
135
|
}
|
@@ -136,10 +141,10 @@ export const insertIntoEventlog = (
|
|
136
141
|
tableName: EVENTLOG_META_TABLE,
|
137
142
|
columns: eventlogMetaTable.sqliteDef.columns,
|
138
143
|
values: {
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
144
|
+
seqNumGlobal: eventEncoded.seqNum.global,
|
145
|
+
seqNumClient: eventEncoded.seqNum.client,
|
146
|
+
parentSeqNumGlobal: eventEncoded.parentSeqNum.global,
|
147
|
+
parentSeqNumClient: eventEncoded.parentSeqNum.client,
|
143
148
|
name: eventEncoded.name,
|
144
149
|
argsJson: eventEncoded.args ?? {},
|
145
150
|
clientId,
|
@@ -164,18 +169,18 @@ export const updateSyncMetadata = (items: ReadonlyArray<LiveStoreEvent.EncodedWi
|
|
164
169
|
...updateRows({
|
165
170
|
tableName: EVENTLOG_META_TABLE,
|
166
171
|
columns: eventlogMetaTable.sqliteDef.columns,
|
167
|
-
where: {
|
172
|
+
where: { seqNumGlobal: event.seqNum.global, seqNumClient: event.seqNum.client },
|
168
173
|
updateValues: { syncMetadataJson: event.meta.syncMetadata },
|
169
174
|
}),
|
170
175
|
)
|
171
176
|
}
|
172
177
|
})
|
173
178
|
|
174
|
-
export const getSyncBackendCursorInfo = (remoteHead:
|
179
|
+
export const getSyncBackendCursorInfo = (remoteHead: EventSequenceNumber.GlobalEventSequenceNumber) =>
|
175
180
|
Effect.gen(function* () {
|
176
181
|
const { dbEventlog } = yield* LeaderThreadCtx
|
177
182
|
|
178
|
-
if (remoteHead ===
|
183
|
+
if (remoteHead === EventSequenceNumber.ROOT.global) return Option.none()
|
179
184
|
|
180
185
|
const EventlogQuerySchema = Schema.Struct({
|
181
186
|
syncMetadataJson: Schema.parseJson(Schema.Option(Schema.JsonValue)),
|
@@ -183,12 +188,12 @@ export const getSyncBackendCursorInfo = (remoteHead: EventId.GlobalEventId) =>
|
|
183
188
|
|
184
189
|
const syncMetadataOption = yield* Effect.sync(() =>
|
185
190
|
dbEventlog.select<{ syncMetadataJson: string }>(
|
186
|
-
sql`SELECT syncMetadataJson FROM ${EVENTLOG_META_TABLE} WHERE
|
191
|
+
sql`SELECT syncMetadataJson FROM ${EVENTLOG_META_TABLE} WHERE seqNumGlobal = ${remoteHead} ORDER BY seqNumClient ASC LIMIT 1`,
|
187
192
|
),
|
188
193
|
).pipe(Effect.andThen(Schema.decode(EventlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
|
189
194
|
|
190
195
|
return Option.some({
|
191
|
-
cursor: { global: remoteHead, client:
|
196
|
+
cursor: { global: remoteHead, client: EventSequenceNumber.clientDefault },
|
192
197
|
metadata: syncMetadataOption,
|
193
198
|
}) satisfies InitialSyncInfo
|
194
199
|
}).pipe(Effect.withSpan('@livestore/common:eventlog:getSyncBackendCursorInfo', { attributes: { remoteHead } }))
|
@@ -50,7 +50,7 @@ export const bootDevtools = (options: DevtoolsOptions) =>
|
|
50
50
|
const syncState = yield* syncProcessor.syncState
|
51
51
|
const mergeCounter = syncProcessor.getMergeCounter()
|
52
52
|
|
53
|
-
yield* syncProcessor.pull({ cursor: { mergeCounter,
|
53
|
+
yield* syncProcessor.pull({ cursor: { mergeCounter, eventNum: syncState.localHead } }).pipe(
|
54
54
|
Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
|
55
55
|
Stream.runDrain,
|
56
56
|
Effect.forkScoped,
|
@@ -4,7 +4,7 @@ import { Effect, ReadonlyArray, Schema } from '@livestore/utils/effect'
|
|
4
4
|
import type { SqliteDb } from '../adapter-types.js'
|
5
5
|
import { getExecArgsFromEvent } from '../materializer-helper.js'
|
6
6
|
import type { LiveStoreSchema } from '../schema/mod.js'
|
7
|
-
import {
|
7
|
+
import { EventSequenceNumber, getEventDef, SystemTables } from '../schema/mod.js'
|
8
8
|
import { insertRow } from '../sql-queries/index.js'
|
9
9
|
import { sql } from '../util.js'
|
10
10
|
import { execSql, execSqlPrepared } from './connection.js'
|
@@ -71,8 +71,8 @@ export const makeMaterializeEvent = ({
|
|
71
71
|
tableName: SystemTables.SESSION_CHANGESET_META_TABLE,
|
72
72
|
columns: SystemTables.sessionChangesetMetaTable.sqliteDef.columns,
|
73
73
|
values: {
|
74
|
-
|
75
|
-
|
74
|
+
seqNumGlobal: eventEncoded.seqNum.global,
|
75
|
+
seqNumClient: eventEncoded.seqNum.client,
|
76
76
|
// NOTE the changeset will be empty (i.e. null) for no-op events
|
77
77
|
changeset: changeset ?? null,
|
78
78
|
debug: LS_DEV ? execArgsArr : null,
|
@@ -112,8 +112,8 @@ export const makeMaterializeEvent = ({
|
|
112
112
|
Effect.withSpan(`@livestore/common:leader-thread:materializeEvent`, {
|
113
113
|
attributes: {
|
114
114
|
eventName: eventEncoded.name,
|
115
|
-
|
116
|
-
'span.label': `${
|
115
|
+
eventNum: eventEncoded.seqNum,
|
116
|
+
'span.label': `${EventSequenceNumber.toString(eventEncoded.seqNum)} ${eventEncoded.name}`,
|
117
117
|
},
|
118
118
|
}),
|
119
119
|
// Effect.logDuration('@livestore/common:leader-thread:materializeEvent'),
|
@@ -123,19 +123,23 @@ export const makeMaterializeEvent = ({
|
|
123
123
|
export const rollback = ({
|
124
124
|
dbState,
|
125
125
|
dbEventlog,
|
126
|
-
|
126
|
+
eventNumsToRollback,
|
127
127
|
}: {
|
128
128
|
dbState: SqliteDb
|
129
129
|
dbEventlog: SqliteDb
|
130
|
-
|
130
|
+
eventNumsToRollback: EventSequenceNumber.EventSequenceNumber[]
|
131
131
|
}) =>
|
132
132
|
Effect.gen(function* () {
|
133
133
|
const rollbackEvents = dbState
|
134
134
|
.select<SystemTables.SessionChangesetMetaRow>(
|
135
|
-
sql`SELECT * FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (
|
135
|
+
sql`SELECT * FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (seqNumGlobal, seqNumClient) IN (${eventNumsToRollback.map((id) => `(${id.global}, ${id.client})`).join(', ')})`,
|
136
136
|
)
|
137
|
-
.map((_) => ({
|
138
|
-
|
137
|
+
.map((_) => ({
|
138
|
+
seqNum: { global: _.seqNumGlobal, client: _.seqNumClient },
|
139
|
+
changeset: _.changeset,
|
140
|
+
debug: _.debug,
|
141
|
+
}))
|
142
|
+
.toSorted((a, b) => EventSequenceNumber.compare(a.seqNum, b.seqNum))
|
139
143
|
|
140
144
|
// Apply changesets in reverse order
|
141
145
|
for (let i = rollbackEvents.length - 1; i >= 0; i--) {
|
@@ -145,25 +149,25 @@ export const rollback = ({
|
|
145
149
|
}
|
146
150
|
}
|
147
151
|
|
148
|
-
const
|
149
|
-
|
152
|
+
const eventNumPairChunks = ReadonlyArray.chunksOf(100)(
|
153
|
+
eventNumsToRollback.map((seqNum) => `(${seqNum.global}, ${seqNum.client})`),
|
150
154
|
)
|
151
155
|
|
152
156
|
// Delete the changeset rows
|
153
|
-
for (const
|
157
|
+
for (const eventNumPairChunk of eventNumPairChunks) {
|
154
158
|
dbState.execute(
|
155
|
-
sql`DELETE FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (
|
159
|
+
sql`DELETE FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (seqNumGlobal, seqNumClient) IN (${eventNumPairChunk.join(', ')})`,
|
156
160
|
)
|
157
161
|
}
|
158
162
|
|
159
163
|
// Delete the eventlog rows
|
160
|
-
for (const
|
164
|
+
for (const eventNumPairChunk of eventNumPairChunks) {
|
161
165
|
dbEventlog.execute(
|
162
|
-
sql`DELETE FROM ${SystemTables.EVENTLOG_META_TABLE} WHERE (
|
166
|
+
sql`DELETE FROM ${SystemTables.EVENTLOG_META_TABLE} WHERE (seqNumGlobal, seqNumClient) IN (${eventNumPairChunk.join(', ')})`,
|
163
167
|
)
|
164
168
|
}
|
165
169
|
}).pipe(
|
166
170
|
Effect.withSpan('@livestore/common:LeaderSyncProcessor:rollback', {
|
167
|
-
attributes: { count:
|
171
|
+
attributes: { count: eventNumsToRollback.length },
|
168
172
|
}),
|
169
173
|
)
|
@@ -24,7 +24,7 @@ import type {
|
|
24
24
|
SyncBackend,
|
25
25
|
UnexpectedError,
|
26
26
|
} from '../index.js'
|
27
|
-
import type {
|
27
|
+
import type { EventSequenceNumber, LiveStoreEvent, LiveStoreSchema } from '../schema/mod.js'
|
28
28
|
import type * as SyncState from '../sync/syncstate.js'
|
29
29
|
import type { ShutdownChannel } from './shutdown-channel.js'
|
30
30
|
|
@@ -43,7 +43,7 @@ export const InitialSyncOptions = Schema.Union(InitialSyncOptionsSkip, InitialSy
|
|
43
43
|
export type InitialSyncOptions = typeof InitialSyncOptions.Type
|
44
44
|
|
45
45
|
export type InitialSyncInfo = Option.Option<{
|
46
|
-
cursor:
|
46
|
+
cursor: EventSequenceNumber.EventSequenceNumber
|
47
47
|
metadata: Option.Option<Schema.JsonValue>
|
48
48
|
}>
|
49
49
|
|
@@ -102,7 +102,7 @@ export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
|
|
102
102
|
syncProcessor: LeaderSyncProcessor
|
103
103
|
materializeEvent: MaterializeEvent
|
104
104
|
initialState: {
|
105
|
-
leaderHead:
|
105
|
+
leaderHead: EventSequenceNumber.EventSequenceNumber
|
106
106
|
migrationsReport: MigrationsReport
|
107
107
|
}
|
108
108
|
/**
|
@@ -165,7 +165,7 @@ export interface LeaderSyncProcessor {
|
|
165
165
|
}) => Effect.Effect<void, UnexpectedError>
|
166
166
|
|
167
167
|
boot: Effect.Effect<
|
168
|
-
{ initialLeaderHead:
|
168
|
+
{ initialLeaderHead: EventSequenceNumber.EventSequenceNumber },
|
169
169
|
UnexpectedError,
|
170
170
|
LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
|
171
171
|
>
|