@livestore/adapter-node 0.0.0-snapshot-2b8a9de3ec1a701aca891ebc2c98eb328274ae9e → 0.0.0-snapshot-2c861249e50661661613204300b1fc0d902c2e46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,12 +4,13 @@ import type {
4
4
  ClientSessionLeaderThreadProxy,
5
5
  LockStatus,
6
6
  MakeSqliteDb,
7
+ SqliteDb,
7
8
  SyncOptions,
8
9
  } from '@livestore/common'
9
10
  import { UnexpectedError } from '@livestore/common'
10
- import { getClientHeadFromDb, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
11
+ import { Eventlog, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
11
12
  import type { LiveStoreSchema } from '@livestore/common/schema'
12
- import { MutationEvent } from '@livestore/common/schema'
13
+ import { LiveStoreEvent } from '@livestore/common/schema'
13
14
  import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
14
15
  import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
15
16
  import type { Schema } from '@livestore/utils/effect'
@@ -33,9 +34,16 @@ export interface InMemoryAdapterOptions {
33
34
 
34
35
  /** Only used internally for testing */
35
36
  testing?: {
36
- overrides?: {
37
- leaderThread?: Partial<ClientSessionLeaderThreadProxy>
38
- }
37
+ overrides?: TestingOverrides
38
+ }
39
+ }
40
+
41
+ export type TestingOverrides = {
42
+ clientSession?: {
43
+ leaderThreadProxy?: Partial<ClientSessionLeaderThreadProxy>
44
+ }
45
+ makeLeaderThread?: {
46
+ dbEventlog?: (makeSqliteDb: MakeSqliteDb) => Effect.Effect<SqliteDb, UnexpectedError>
39
47
  }
40
48
  }
41
49
 
@@ -109,9 +117,7 @@ const makeLeaderThread = ({
109
117
  syncOptions: SyncOptions | undefined
110
118
  syncPayload: Schema.JsonValue | undefined
111
119
  testing?: {
112
- overrides?: {
113
- leaderThread?: Partial<ClientSessionLeaderThreadProxy>
114
- }
120
+ overrides?: TestingOverrides
115
121
  }
116
122
  }) =>
117
123
  Effect.gen(function* () {
@@ -119,7 +125,9 @@ const makeLeaderThread = ({
119
125
  makeLeaderThreadLayer({
120
126
  clientId,
121
127
  dbReadModel: yield* makeSqliteDb({ _tag: 'in-memory' }),
122
- dbMutationLog: yield* makeSqliteDb({ _tag: 'in-memory' }),
128
+ dbEventlog: testing?.overrides?.makeLeaderThread?.dbEventlog
129
+ ? yield* testing.overrides.makeLeaderThread.dbEventlog(makeSqliteDb)
130
+ : yield* makeSqliteDb({ _tag: 'in-memory' }),
123
131
  devtoolsOptions: { enabled: false },
124
132
  makeSqliteDb,
125
133
  schema,
@@ -132,41 +140,30 @@ const makeLeaderThread = ({
132
140
  )
133
141
 
134
142
  return yield* Effect.gen(function* () {
135
- const {
136
- dbReadModel: db,
137
- dbMutationLog,
138
- syncProcessor,
139
- connectedClientSessionPullQueues,
140
- extraIncomingMessagesQueue,
141
- initialState,
142
- } = yield* LeaderThreadCtx
143
-
144
- const initialLeaderHead = getClientHeadFromDb(dbMutationLog)
145
- const pullQueue = yield* connectedClientSessionPullQueues.makeQueue(initialLeaderHead)
143
+ const { dbReadModel, dbEventlog, syncProcessor, extraIncomingMessagesQueue, initialState } =
144
+ yield* LeaderThreadCtx
145
+
146
+ const initialLeaderHead = Eventlog.getClientHeadFromDb(dbEventlog)
146
147
 
147
148
  const leaderThread = {
148
- mutations: {
149
- pull: testing?.overrides?.leaderThread?.mutations?.pull ?? (() => Stream.fromQueue(pullQueue)),
149
+ events: {
150
+ pull:
151
+ testing?.overrides?.clientSession?.leaderThreadProxy?.events?.pull ??
152
+ (({ cursor }) => syncProcessor.pull({ cursor })),
150
153
  push: (batch) =>
151
- syncProcessor
152
- .push(
153
- batch.map((item) => new MutationEvent.EncodedWithMeta(item)),
154
- { waitForProcessing: true },
155
- )
156
- .pipe(Effect.provide(layer), Effect.scoped),
154
+ syncProcessor.push(
155
+ batch.map((item) => new LiveStoreEvent.EncodedWithMeta(item)),
156
+ { waitForProcessing: true },
157
+ ),
157
158
  },
158
159
  initialState: { leaderHead: initialLeaderHead, migrationsReport: initialState.migrationsReport },
159
- export: Effect.sync(() => db.export()),
160
- getMutationLogData: Effect.sync(() => dbMutationLog.export()),
161
- // TODO
162
- networkStatus: SubscriptionRef.make({ isConnected: false, timestampMs: Date.now(), latchClosed: false }).pipe(
163
- Effect.runSync,
164
- ),
160
+ export: Effect.sync(() => dbReadModel.export()),
161
+ getEventlogData: Effect.sync(() => dbEventlog.export()),
165
162
  getSyncState: syncProcessor.syncState,
166
163
  sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
167
164
  } satisfies ClientSessionLeaderThreadProxy
168
165
 
169
- const initialSnapshot = db.export()
166
+ const initialSnapshot = dbReadModel.export()
170
167
 
171
168
  return { leaderThread, initialSnapshot }
172
169
  }).pipe(Effect.provide(layer))
@@ -8,7 +8,6 @@ import type {
8
8
  ClientSessionLeaderThreadProxy,
9
9
  IntentionalShutdownCause,
10
10
  LockStatus,
11
- NetworkStatus,
12
11
  } from '@livestore/common'
13
12
  import { Devtools, UnexpectedError } from '@livestore/common'
14
13
  import * as DevtoolsNode from '@livestore/devtools-node-common/web-channel'
@@ -289,12 +288,6 @@ const makeLeaderThread = ({
289
288
 
290
289
  const initialLeaderHead = yield* runInWorker(new WorkerSchema.LeaderWorkerInner.GetLeaderHead())
291
290
 
292
- const networkStatus = yield* SubscriptionRef.make<NetworkStatus>({
293
- isConnected: true,
294
- timestampMs: Date.now(),
295
- latchClosed: false,
296
- })
297
-
298
291
  const bootResult = yield* runInWorker(new WorkerSchema.LeaderWorkerInner.GetRecreateSnapshot()).pipe(
299
292
  Effect.timeout(10_000),
300
293
  UnexpectedError.mapToUnexpectedError,
@@ -302,8 +295,7 @@ const makeLeaderThread = ({
302
295
  )
303
296
 
304
297
  const leaderThread = {
305
- networkStatus,
306
- mutations: {
298
+ events: {
307
299
  pull: ({ cursor }) =>
308
300
  runInWorkerStream(new WorkerSchema.LeaderWorkerInner.PullStream({ cursor })).pipe(Stream.orDie),
309
301
  push: (batch) =>
@@ -322,7 +314,7 @@ const makeLeaderThread = ({
322
314
  UnexpectedError.mapToUnexpectedError,
323
315
  Effect.withSpan('@livestore/adapter-node:client-session:export'),
324
316
  ),
325
- getMutationLogData: Effect.dieMessage('Not implemented'),
317
+ getEventlogData: Effect.dieMessage('Not implemented'),
326
318
  getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInner.GetLeaderSyncState()).pipe(
327
319
  UnexpectedError.mapToUnexpectedError,
328
320
  Effect.withSpan('@livestore/adapter-node:client-session:getLeaderSyncState'),
@@ -8,17 +8,12 @@ if (process.execArgv.includes('--inspect')) {
8
8
  inspector.waitForDebugger()
9
9
  }
10
10
 
11
- import type { NetworkStatus, SyncOptions } from '@livestore/common'
11
+ import type { SyncOptions } from '@livestore/common'
12
12
  import { Devtools, liveStoreStorageFormatVersion, UnexpectedError } from '@livestore/common'
13
13
  import type { DevtoolsOptions, LeaderSqliteDb } from '@livestore/common/leader-thread'
14
- import {
15
- configureConnection,
16
- getClientHeadFromDb,
17
- LeaderThreadCtx,
18
- makeLeaderThreadLayer,
19
- } from '@livestore/common/leader-thread'
14
+ import { configureConnection, Eventlog, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
20
15
  import type { LiveStoreSchema } from '@livestore/common/schema'
21
- import { MutationEvent } from '@livestore/common/schema'
16
+ import { LiveStoreEvent } from '@livestore/common/schema'
22
17
  import { makeNodeDevtoolsChannel } from '@livestore/devtools-node-common/web-channel'
23
18
  import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
24
19
  import { sqliteDbFactory } from '@livestore/sqlite-wasm/node'
@@ -69,7 +64,7 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
69
64
  PushToLeader: ({ batch }) =>
70
65
  Effect.andThen(LeaderThreadCtx, (_) =>
71
66
  _.syncProcessor.push(
72
- batch.map((item) => new MutationEvent.EncodedWithMeta(item)),
67
+ batch.map((item) => new LiveStoreEvent.EncodedWithMeta(item)),
73
68
  // We'll wait in order to keep back pressure on the client session
74
69
  { waitForProcessing: true },
75
70
  ),
@@ -78,37 +73,24 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
78
73
  Effect.andThen(LeaderThreadCtx, (_) => Stream.fromQueue(_.bootStatusQueue)).pipe(Stream.unwrap),
79
74
  PullStream: ({ cursor }) =>
80
75
  Effect.gen(function* () {
81
- const { connectedClientSessionPullQueues } = yield* LeaderThreadCtx
82
- const pullQueue = yield* connectedClientSessionPullQueues.makeQueue(cursor)
83
- return Stream.fromQueue(pullQueue)
76
+ const { syncProcessor } = yield* LeaderThreadCtx
77
+ return syncProcessor.pull({ cursor })
84
78
  }).pipe(Stream.unwrapScoped),
85
79
  Export: () =>
86
80
  Effect.andThen(LeaderThreadCtx, (_) => _.dbReadModel.export()).pipe(
87
81
  UnexpectedError.mapToUnexpectedError,
88
82
  Effect.withSpan('@livestore/adapter-node:worker:Export'),
89
83
  ),
90
- ExportMutationlog: () =>
91
- Effect.andThen(LeaderThreadCtx, (_) => _.dbMutationLog.export()).pipe(
84
+ ExportEventlog: () =>
85
+ Effect.andThen(LeaderThreadCtx, (_) => _.dbEventlog.export()).pipe(
92
86
  UnexpectedError.mapToUnexpectedError,
93
- Effect.withSpan('@livestore/adapter-node:worker:ExportMutationlog'),
87
+ Effect.withSpan('@livestore/adapter-node:worker:ExportEventlog'),
94
88
  ),
95
89
  GetLeaderHead: () =>
96
90
  Effect.gen(function* () {
97
91
  const workerCtx = yield* LeaderThreadCtx
98
- return getClientHeadFromDb(workerCtx.dbMutationLog)
92
+ return Eventlog.getClientHeadFromDb(workerCtx.dbEventlog)
99
93
  }).pipe(UnexpectedError.mapToUnexpectedError, Effect.withSpan('@livestore/adapter-node:worker:GetLeaderHead')),
100
- NetworkStatusStream: () =>
101
- Effect.gen(function* (_) {
102
- const ctx = yield* LeaderThreadCtx
103
-
104
- if (ctx.syncBackend === undefined) {
105
- return Stream.make<[NetworkStatus]>({ isConnected: false, timestampMs: Date.now(), latchClosed: false })
106
- }
107
-
108
- return ctx.syncBackend.isConnected.changes.pipe(
109
- Stream.map((isConnected) => ({ isConnected, timestampMs: Date.now(), latchClosed: false })),
110
- )
111
- }).pipe(Stream.unwrap),
112
94
  GetLeaderSyncState: () =>
113
95
  Effect.gen(function* () {
114
96
  const workerCtx = yield* LeaderThreadCtx
@@ -133,14 +115,14 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
133
115
  ),
134
116
  Shutdown: () =>
135
117
  Effect.gen(function* () {
136
- // const { db, dbMutationLog } = yield* LeaderThreadCtx
118
+ // const { db, dbEventlog } = yield* LeaderThreadCtx
137
119
  yield* Effect.logDebug('[@livestore/adapter-node:worker] Shutdown')
138
120
 
139
121
  // if (devtools.enabled) {
140
122
  // yield* FiberSet.clear(devtools.connections)
141
123
  // }
142
124
  // db.close()
143
- // dbMutationLog.close()
125
+ // dbEventlog.close()
144
126
 
145
127
  // Buy some time for Otel to flush
146
128
  // TODO find a cleaner way to do this
@@ -191,26 +173,25 @@ const makeLeaderThread = ({
191
173
 
192
174
  const schemaHashSuffix = schema.migrationOptions.strategy === 'manual' ? 'fixed' : schema.hash.toString()
193
175
 
194
- const makeDb = (kind: 'app' | 'mutationlog') =>
176
+ const makeDb = (kind: 'app' | 'eventlog') =>
195
177
  makeSqliteDb({
196
178
  _tag: 'fs',
197
179
  directory: path.join(baseDirectory ?? '', storeId),
198
- fileName:
199
- kind === 'app' ? getAppDbFileName(schemaHashSuffix) : `mutationlog@${liveStoreStorageFormatVersion}.db`,
180
+ fileName: kind === 'app' ? getAppDbFileName(schemaHashSuffix) : `eventlog@${liveStoreStorageFormatVersion}.db`,
200
181
  // TODO enable WAL for nodejs
201
182
  configureDb: (db) =>
202
183
  configureConnection(db, { foreignKeys: true }).pipe(Effect.provide(runtime), Effect.runSync),
203
184
  }).pipe(Effect.acquireRelease((db) => Effect.sync(() => db.close())))
204
185
 
205
186
  // Might involve some async work, so we're running them concurrently
206
- const [dbReadModel, dbMutationLog] = yield* Effect.all([makeDb('app'), makeDb('mutationlog')], { concurrency: 2 })
187
+ const [dbReadModel, dbEventlog] = yield* Effect.all([makeDb('app'), makeDb('eventlog')], { concurrency: 2 })
207
188
 
208
189
  const devtoolsOptions = yield* makeDevtoolsOptions({
209
190
  devtoolsEnabled: devtools.enabled,
210
191
  devtoolsPort: devtools.port,
211
192
  devtoolsHost: devtools.host,
212
193
  dbReadModel,
213
- dbMutationLog,
194
+ dbEventlog,
214
195
  storeId,
215
196
  clientId,
216
197
  schemaPath,
@@ -225,7 +206,7 @@ const makeLeaderThread = ({
225
206
  makeSqliteDb,
226
207
  syncOptions,
227
208
  dbReadModel,
228
- dbMutationLog,
209
+ dbEventlog,
229
210
  devtoolsOptions,
230
211
  shutdownChannel,
231
212
  syncPayload,
@@ -242,7 +223,7 @@ const getAppDbFileName = (suffix: string) => `app${suffix}@${liveStoreStorageFor
242
223
  const makeDevtoolsOptions = ({
243
224
  devtoolsEnabled,
244
225
  dbReadModel,
245
- dbMutationLog,
226
+ dbEventlog,
246
227
  storeId,
247
228
  clientId,
248
229
  devtoolsPort,
@@ -251,7 +232,7 @@ const makeDevtoolsOptions = ({
251
232
  }: {
252
233
  devtoolsEnabled: boolean
253
234
  dbReadModel: LeaderSqliteDb
254
- dbMutationLog: LeaderSqliteDb
235
+ dbEventlog: LeaderSqliteDb
255
236
  storeId: string
256
237
  clientId: string
257
238
  devtoolsPort: number
@@ -289,7 +270,7 @@ const makeDevtoolsOptions = ({
289
270
  devtoolsWebChannel,
290
271
  persistenceInfo: {
291
272
  readModel: dbReadModel.metadata.persistenceInfo,
292
- mutationLog: dbMutationLog.metadata.persistenceInfo,
273
+ eventlog: dbEventlog.metadata.persistenceInfo,
293
274
  },
294
275
  }
295
276
  }).pipe(Effect.provide(FetchHttpClient.layer)),
@@ -1,5 +1,13 @@
1
- import { BootStatus, Devtools, LeaderAheadError, MigrationsReport, SyncState, UnexpectedError } from '@livestore/common'
2
- import { EventId, MutationEvent } from '@livestore/common/schema'
1
+ import {
2
+ BootStatus,
3
+ Devtools,
4
+ LeaderAheadError,
5
+ LeaderPullCursor,
6
+ MigrationsReport,
7
+ SyncState,
8
+ UnexpectedError,
9
+ } from '@livestore/common'
10
+ import { EventId, LiveStoreEvent } from '@livestore/common/schema'
3
11
  import { Schema, Transferable } from '@livestore/utils/effect'
4
12
 
5
13
  export const WorkerArgv = Schema.parseJson(
@@ -84,18 +92,18 @@ export namespace LeaderWorkerInner {
84
92
 
85
93
  export class PullStream extends Schema.TaggedRequest<PullStream>()('PullStream', {
86
94
  payload: {
87
- cursor: EventId.EventId,
95
+ cursor: LeaderPullCursor,
88
96
  },
89
97
  success: Schema.Struct({
90
98
  payload: SyncState.PayloadUpstream,
91
- remaining: Schema.Number,
99
+ mergeCounter: Schema.Number,
92
100
  }),
93
101
  failure: UnexpectedError,
94
102
  }) {}
95
103
 
96
104
  export class PushToLeader extends Schema.TaggedRequest<PushToLeader>()('PushToLeader', {
97
105
  payload: {
98
- batch: Schema.Array(MutationEvent.AnyEncoded),
106
+ batch: Schema.Array(LiveStoreEvent.AnyEncoded),
99
107
  },
100
108
  success: Schema.Void,
101
109
  failure: Schema.Union(UnexpectedError, LeaderAheadError),
@@ -116,7 +124,7 @@ export namespace LeaderWorkerInner {
116
124
  failure: UnexpectedError,
117
125
  }) {}
118
126
 
119
- export class ExportMutationlog extends Schema.TaggedRequest<ExportMutationlog>()('ExportMutationlog', {
127
+ export class ExportEventlog extends Schema.TaggedRequest<ExportEventlog>()('ExportEventlog', {
120
128
  payload: {},
121
129
  success: Transferable.Uint8Array,
122
130
  failure: UnexpectedError,
@@ -134,15 +142,6 @@ export namespace LeaderWorkerInner {
134
142
  failure: UnexpectedError,
135
143
  }) {}
136
144
 
137
- export class NetworkStatusStream extends Schema.TaggedRequest<NetworkStatusStream>()('NetworkStatusStream', {
138
- payload: {},
139
- success: Schema.Struct({
140
- isConnected: Schema.Boolean,
141
- timestampMs: Schema.Number,
142
- }),
143
- failure: UnexpectedError,
144
- }) {}
145
-
146
145
  export class Shutdown extends Schema.TaggedRequest<Shutdown>()('Shutdown', {
147
146
  payload: {},
148
147
  success: Schema.Void,
@@ -164,10 +163,9 @@ export namespace LeaderWorkerInner {
164
163
  PushToLeader,
165
164
  Export,
166
165
  GetRecreateSnapshot,
167
- ExportMutationlog,
166
+ ExportEventlog,
168
167
  GetLeaderHead,
169
168
  GetLeaderSyncState,
170
- NetworkStatusStream,
171
169
  Shutdown,
172
170
  ExtraDevtoolsMessage,
173
171
  )