@livestore/adapter-node 0.0.0-snapshot-057a9e3a18ca69a310d4eb8cf35a34e94fa1841e → 0.0.0-snapshot-8fd59846e2580d37bdd37ae607e9db2a458a8b63
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/client-session/adapter.d.ts +1 -1
- package/dist/client-session/adapter.d.ts.map +1 -1
- package/dist/client-session/adapter.js +17 -11
- package/dist/client-session/adapter.js.map +1 -1
- package/dist/devtools/mod.d.ts +2 -2
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +1 -1
- package/dist/devtools/mod.js.map +1 -1
- package/dist/leader-thread-shared.d.ts +4 -5
- package/dist/leader-thread-shared.d.ts.map +1 -1
- package/dist/leader-thread-shared.js +2 -4
- package/dist/leader-thread-shared.js.map +1 -1
- package/dist/make-leader-worker.js +1 -1
- package/dist/make-leader-worker.js.map +1 -1
- package/dist/shutdown-channel.d.ts +1 -1
- package/dist/shutdown-channel.d.ts.map +1 -1
- package/dist/webchannel.d.ts.map +1 -1
- package/dist/webchannel.js +1 -0
- package/dist/webchannel.js.map +1 -1
- package/dist/worker-schema.d.ts +6 -6
- package/dist/worker-schema.d.ts.map +1 -1
- package/dist/worker-schema.js +3 -2
- package/dist/worker-schema.js.map +1 -1
- package/package.json +7 -7
- package/src/client-session/adapter.ts +70 -60
- package/src/devtools/mod.ts +2 -2
- package/src/leader-thread-shared.ts +6 -14
- package/src/make-leader-worker.ts +1 -1
- package/src/webchannel.ts +2 -1
- package/src/worker-schema.ts +11 -2
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { hostname } from 'node:os'
|
|
2
2
|
import * as WT from 'node:worker_threads'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
Adapter,
|
|
6
|
+
BootStatus,
|
|
6
7
|
ClientSessionLeaderThreadProxy,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type SyncOptions,
|
|
12
|
-
UnexpectedError,
|
|
8
|
+
IntentionalShutdownCause,
|
|
9
|
+
LockStatus,
|
|
10
|
+
MakeSqliteDb,
|
|
11
|
+
SyncOptions,
|
|
13
12
|
} from '@livestore/common'
|
|
13
|
+
import { makeClientSession, UnexpectedError } from '@livestore/common'
|
|
14
14
|
import { Eventlog, LeaderThreadCtx } from '@livestore/common/leader-thread'
|
|
15
15
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
16
16
|
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
@@ -188,7 +188,6 @@ const makeAdapterImpl = ({
|
|
|
188
188
|
})
|
|
189
189
|
|
|
190
190
|
syncInMemoryDb.import(initialSnapshot)
|
|
191
|
-
syncInMemoryDb.debug.head = leaderThread.initialState.leaderHead
|
|
192
191
|
|
|
193
192
|
const clientSession = yield* makeClientSession({
|
|
194
193
|
...adapterArgs,
|
|
@@ -215,6 +214,7 @@ const makeAdapterImpl = ({
|
|
|
215
214
|
return clientSession
|
|
216
215
|
}).pipe(
|
|
217
216
|
Effect.withSpan('@livestore/adapter-node:adapter'),
|
|
217
|
+
Effect.parallelFinalizers,
|
|
218
218
|
Effect.provide(PlatformNode.NodeFileSystem.layer),
|
|
219
219
|
Effect.provide(FetchHttpClient.layer),
|
|
220
220
|
)) satisfies Adapter
|
|
@@ -262,24 +262,23 @@ const makeLocalLeaderThread = ({
|
|
|
262
262
|
|
|
263
263
|
const initialLeaderHead = Eventlog.getClientHeadFromDb(dbEventlog)
|
|
264
264
|
|
|
265
|
-
const leaderThread =
|
|
266
|
-
{
|
|
267
|
-
|
|
268
|
-
pull
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
initialState: { leaderHead: initialLeaderHead, migrationsReport: initialState.migrationsReport },
|
|
276
|
-
export: Effect.sync(() => dbState.export()),
|
|
277
|
-
getEventlogData: Effect.sync(() => dbEventlog.export()),
|
|
278
|
-
getSyncState: syncProcessor.syncState,
|
|
279
|
-
sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
|
|
265
|
+
const leaderThread = {
|
|
266
|
+
events: {
|
|
267
|
+
pull:
|
|
268
|
+
testing?.overrides?.clientSession?.leaderThreadProxy?.events?.pull ??
|
|
269
|
+
(({ cursor }) => syncProcessor.pull({ cursor })),
|
|
270
|
+
push: (batch) =>
|
|
271
|
+
syncProcessor.push(
|
|
272
|
+
batch.map((item) => new LiveStoreEvent.EncodedWithMeta(item)),
|
|
273
|
+
{ waitForProcessing: true },
|
|
274
|
+
),
|
|
280
275
|
},
|
|
281
|
-
{
|
|
282
|
-
|
|
276
|
+
initialState: { leaderHead: initialLeaderHead, migrationsReport: initialState.migrationsReport },
|
|
277
|
+
export: Effect.sync(() => dbState.export()),
|
|
278
|
+
getEventlogData: Effect.sync(() => dbEventlog.export()),
|
|
279
|
+
getSyncState: syncProcessor.syncState,
|
|
280
|
+
sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
|
|
281
|
+
} satisfies ClientSessionLeaderThreadProxy
|
|
283
282
|
|
|
284
283
|
const initialSnapshot = dbState.export()
|
|
285
284
|
|
|
@@ -337,6 +336,20 @@ const makeWorkerLeaderThread = ({
|
|
|
337
336
|
Effect.withSpan('@livestore/adapter-node:adapter:setupLeaderThread'),
|
|
338
337
|
)
|
|
339
338
|
|
|
339
|
+
yield* Effect.addFinalizer(() =>
|
|
340
|
+
Effect.gen(function* () {
|
|
341
|
+
// We first try to gracefully shutdown the leader worker and then forcefully terminate it
|
|
342
|
+
yield* Effect.raceFirst(
|
|
343
|
+
runInWorker(new WorkerSchema.LeaderWorkerInner.Shutdown()).pipe(Effect.andThen(() => nodeWorker.terminate())),
|
|
344
|
+
|
|
345
|
+
Effect.sync(() => {
|
|
346
|
+
console.warn('[@livestore/adapter-node:adapter] Worker did not gracefully shutdown in time, terminating it')
|
|
347
|
+
nodeWorker.terminate()
|
|
348
|
+
}).pipe(Effect.delay(1000)),
|
|
349
|
+
).pipe(Effect.exit) // The disconnect is to prevent the interrupt to bubble out
|
|
350
|
+
}).pipe(Effect.withSpan('@livestore/adapter-node:adapter:shutdown'), Effect.tapCauseLogPretty, Effect.orDie),
|
|
351
|
+
)
|
|
352
|
+
|
|
340
353
|
const runInWorker = <TReq extends typeof WorkerSchema.LeaderWorkerInner.Request.Type>(
|
|
341
354
|
req: TReq,
|
|
342
355
|
): TReq extends Schema.WithResult<infer A, infer _I, infer _E, infer _EI, infer R>
|
|
@@ -397,42 +410,39 @@ const makeWorkerLeaderThread = ({
|
|
|
397
410
|
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
398
411
|
)
|
|
399
412
|
|
|
400
|
-
const leaderThread =
|
|
401
|
-
{
|
|
402
|
-
|
|
403
|
-
pull
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
),
|
|
411
|
-
},
|
|
412
|
-
initialState: {
|
|
413
|
-
leaderHead: initialLeaderHead,
|
|
414
|
-
migrationsReport: bootResult.migrationsReport,
|
|
415
|
-
},
|
|
416
|
-
export: runInWorker(new WorkerSchema.LeaderWorkerInner.Export()).pipe(
|
|
417
|
-
Effect.timeout(10_000),
|
|
418
|
-
UnexpectedError.mapToUnexpectedError,
|
|
419
|
-
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
420
|
-
),
|
|
421
|
-
getEventlogData: Effect.dieMessage('Not implemented'),
|
|
422
|
-
getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInner.GetLeaderSyncState()).pipe(
|
|
423
|
-
UnexpectedError.mapToUnexpectedError,
|
|
424
|
-
Effect.withSpan('@livestore/adapter-node:client-session:getLeaderSyncState'),
|
|
425
|
-
),
|
|
426
|
-
sendDevtoolsMessage: (message) =>
|
|
427
|
-
runInWorker(new WorkerSchema.LeaderWorkerInner.ExtraDevtoolsMessage({ message })).pipe(
|
|
428
|
-
UnexpectedError.mapToUnexpectedError,
|
|
429
|
-
Effect.withSpan('@livestore/adapter-node:client-session:devtoolsMessageForLeader'),
|
|
413
|
+
const leaderThread = {
|
|
414
|
+
events: {
|
|
415
|
+
pull:
|
|
416
|
+
testing?.overrides?.clientSession?.leaderThreadProxy?.events?.pull ??
|
|
417
|
+
(({ cursor }) =>
|
|
418
|
+
runInWorkerStream(new WorkerSchema.LeaderWorkerInner.PullStream({ cursor })).pipe(Stream.orDie)),
|
|
419
|
+
push: (batch) =>
|
|
420
|
+
runInWorker(new WorkerSchema.LeaderWorkerInner.PushToLeader({ batch })).pipe(
|
|
421
|
+
Effect.withSpan('@livestore/adapter-node:client-session:pushToLeader', {
|
|
422
|
+
attributes: { batchSize: batch.length },
|
|
423
|
+
}),
|
|
430
424
|
),
|
|
431
425
|
},
|
|
432
|
-
{
|
|
433
|
-
|
|
426
|
+
initialState: {
|
|
427
|
+
leaderHead: initialLeaderHead,
|
|
428
|
+
migrationsReport: bootResult.migrationsReport,
|
|
434
429
|
},
|
|
435
|
-
|
|
430
|
+
export: runInWorker(new WorkerSchema.LeaderWorkerInner.Export()).pipe(
|
|
431
|
+
Effect.timeout(10_000),
|
|
432
|
+
UnexpectedError.mapToUnexpectedError,
|
|
433
|
+
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
434
|
+
),
|
|
435
|
+
getEventlogData: Effect.dieMessage('Not implemented'),
|
|
436
|
+
getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInner.GetLeaderSyncState()).pipe(
|
|
437
|
+
UnexpectedError.mapToUnexpectedError,
|
|
438
|
+
Effect.withSpan('@livestore/adapter-node:client-session:getLeaderSyncState'),
|
|
439
|
+
),
|
|
440
|
+
sendDevtoolsMessage: (message) =>
|
|
441
|
+
runInWorker(new WorkerSchema.LeaderWorkerInner.ExtraDevtoolsMessage({ message })).pipe(
|
|
442
|
+
UnexpectedError.mapToUnexpectedError,
|
|
443
|
+
Effect.withSpan('@livestore/adapter-node:client-session:devtoolsMessageForLeader'),
|
|
444
|
+
),
|
|
445
|
+
} satisfies ClientSessionLeaderThreadProxy
|
|
436
446
|
|
|
437
447
|
return { leaderThread, initialSnapshot: bootResult.snapshot }
|
|
438
448
|
})
|
package/src/devtools/mod.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { startDevtoolsServer } from './devtools-server.js'
|
|
2
|
-
export type { ViteDevtoolsOptions } from './vite-dev-server.js'
|
|
3
1
|
export { makeViteMiddleware } from './vite-dev-server.js'
|
|
2
|
+
export type { ViteDevtoolsOptions } from './vite-dev-server.js'
|
|
3
|
+
export { startDevtoolsServer } from './devtools-server.js'
|
|
@@ -21,17 +21,11 @@ import type * as WorkerSchema from './worker-schema.js'
|
|
|
21
21
|
|
|
22
22
|
export type TestingOverrides = {
|
|
23
23
|
clientSession?: {
|
|
24
|
-
leaderThreadProxy?:
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
leaderThreadProxy?: Partial<ClientSessionLeaderThreadProxy>
|
|
25
|
+
}
|
|
26
|
+
makeLeaderThread?: {
|
|
27
|
+
dbEventlog?: (makeSqliteDb: MakeSqliteDb) => Effect.Effect<SqliteDb, UnexpectedError>
|
|
27
28
|
}
|
|
28
|
-
makeLeaderThread?: (makeSqliteDb: MakeSqliteDb) => Effect.Effect<
|
|
29
|
-
{
|
|
30
|
-
dbEventlog: SqliteDb
|
|
31
|
-
dbState: SqliteDb
|
|
32
|
-
},
|
|
33
|
-
UnexpectedError
|
|
34
|
-
>
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
export interface MakeLeaderThreadArgs {
|
|
@@ -68,10 +62,8 @@ export const makeLeaderThread = ({
|
|
|
68
62
|
schema.state.sqlite.migrations.strategy === 'manual' ? 'fixed' : schema.state.sqlite.hash.toString()
|
|
69
63
|
|
|
70
64
|
const makeDb = (kind: 'state' | 'eventlog') => {
|
|
71
|
-
if (testing?.makeLeaderThread) {
|
|
72
|
-
return testing
|
|
73
|
-
.makeLeaderThread(makeSqliteDb)
|
|
74
|
-
.pipe(Effect.map(({ dbEventlog, dbState }) => (kind === 'state' ? dbState : dbEventlog)))
|
|
65
|
+
if (testing?.makeLeaderThread?.dbEventlog && kind === 'eventlog') {
|
|
66
|
+
return testing.makeLeaderThread.dbEventlog(makeSqliteDb)
|
|
75
67
|
}
|
|
76
68
|
|
|
77
69
|
return storage.type === 'in-memory'
|
|
@@ -47,7 +47,7 @@ export type WorkerOptions = {
|
|
|
47
47
|
export const getWorkerArgs = () => Schema.decodeSync(WorkerSchema.WorkerArgv)(process.argv[2]!)
|
|
48
48
|
|
|
49
49
|
export const makeWorker = (options: WorkerOptions) => {
|
|
50
|
-
makeWorkerEffect(options).pipe(
|
|
50
|
+
makeWorkerEffect(options).pipe(Effect.runFork)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export const makeWorkerEffect = (options: WorkerOptions) => {
|
package/src/webchannel.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BroadcastChannel as NodeBroadcastChannel } from 'node:worker_threads'
|
|
2
2
|
|
|
3
3
|
import type { Either, ParseResult } from '@livestore/utils/effect'
|
|
4
4
|
import { Deferred, Effect, Exit, Schema, Scope, Stream, WebChannel } from '@livestore/utils/effect'
|
|
@@ -37,6 +37,7 @@ export const makeBroadcastChannel = <Msg, MsgEncoded>({
|
|
|
37
37
|
const listen = Stream.asyncPush<Either.Either<Msg, ParseResult.ParseError>>((emit) =>
|
|
38
38
|
Effect.acquireRelease(
|
|
39
39
|
Effect.gen(function* () {
|
|
40
|
+
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
|
40
41
|
channel.onmessage = (event: any) => {
|
|
41
42
|
return emit.single(Schema.decodeEither(schema)(event.data))
|
|
42
43
|
}
|
package/src/worker-schema.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BootStatus,
|
|
3
|
+
Devtools,
|
|
4
|
+
LeaderAheadError,
|
|
5
|
+
LeaderPullCursor,
|
|
6
|
+
MigrationsReport,
|
|
7
|
+
SyncState,
|
|
8
|
+
UnexpectedError,
|
|
9
|
+
} from '@livestore/common'
|
|
2
10
|
import { EventSequenceNumber, LiveStoreEvent } from '@livestore/common/schema'
|
|
3
11
|
import { Schema, Transferable } from '@livestore/utils/effect'
|
|
4
12
|
|
|
@@ -83,10 +91,11 @@ export namespace LeaderWorkerInner {
|
|
|
83
91
|
|
|
84
92
|
export class PullStream extends Schema.TaggedRequest<PullStream>()('PullStream', {
|
|
85
93
|
payload: {
|
|
86
|
-
cursor:
|
|
94
|
+
cursor: LeaderPullCursor,
|
|
87
95
|
},
|
|
88
96
|
success: Schema.Struct({
|
|
89
97
|
payload: SyncState.PayloadUpstream,
|
|
98
|
+
mergeCounter: Schema.Number,
|
|
90
99
|
}),
|
|
91
100
|
failure: UnexpectedError,
|
|
92
101
|
}) {}
|