@livestore/adapter-web 0.0.0-snapshot-f6ec49b1a18859aad769f0a0d8edf8bae231ed07 → 0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0
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/in-memory/in-memory-adapter.d.ts.map +1 -1
- package/dist/in-memory/in-memory-adapter.js +1 -2
- package/dist/in-memory/in-memory-adapter.js.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.d.ts +9 -0
- package/dist/web-worker/client-session/persisted-adapter.d.ts.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.js +7 -32
- package/dist/web-worker/client-session/persisted-adapter.js.map +1 -1
- package/dist/web-worker/common/persisted-sqlite.d.ts +2 -1
- package/dist/web-worker/common/persisted-sqlite.d.ts.map +1 -1
- package/dist/web-worker/common/persisted-sqlite.js +6 -4
- package/dist/web-worker/common/persisted-sqlite.js.map +1 -1
- package/dist/web-worker/common/worker-schema.d.ts +6 -18
- package/dist/web-worker/common/worker-schema.d.ts.map +1 -1
- package/dist/web-worker/common/worker-schema.js +6 -13
- package/dist/web-worker/common/worker-schema.js.map +1 -1
- package/dist/web-worker/leader-worker/make-leader-worker.d.ts.map +1 -1
- package/dist/web-worker/leader-worker/make-leader-worker.js +8 -16
- package/dist/web-worker/leader-worker/make-leader-worker.js.map +1 -1
- package/dist/web-worker/shared-worker/make-shared-worker.d.ts.map +1 -1
- package/dist/web-worker/shared-worker/make-shared-worker.js +32 -54
- package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -1
- package/package.json +6 -6
- package/src/in-memory/in-memory-adapter.ts +1 -4
- package/src/web-worker/client-session/persisted-adapter.ts +21 -48
- package/src/web-worker/common/persisted-sqlite.ts +12 -4
- package/src/web-worker/common/worker-schema.ts +6 -22
- package/src/web-worker/leader-worker/make-leader-worker.ts +10 -24
- package/src/web-worker/shared-worker/make-shared-worker.ts +40 -80
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UnexpectedError } from '@livestore/common';
|
|
2
2
|
import { connectViaWorker } from '@livestore/devtools-web-common/web-channel';
|
|
3
|
-
import * as
|
|
3
|
+
import * as WebmeshWorker from '@livestore/devtools-web-common/worker';
|
|
4
4
|
import { isDevEnv, isNotUndefined, LS_DEV } from '@livestore/utils';
|
|
5
|
-
import { BrowserWorker, BrowserWorkerRunner, Deferred,
|
|
5
|
+
import { BrowserWorker, BrowserWorkerRunner, Deferred, Effect, Exit, FetchHttpClient, identity, Layer, Logger, LogLevel, ParseResult, Ref, Schema, Scope, Stream, SubscriptionRef, TaskTracing, Worker, WorkerError, WorkerRunner, } from '@livestore/utils/effect';
|
|
6
6
|
import { makeShutdownChannel } from '../common/shutdown-channel.js';
|
|
7
7
|
import * as WorkerSchema from '../common/worker-schema.js';
|
|
8
8
|
if (isDevEnv()) {
|
|
@@ -21,7 +21,7 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
21
21
|
Effect.andThen((worker) => worker.executeEffect(req)),
|
|
22
22
|
// Effect.tap((_) => Effect.log(`forwardRequest: ${req._tag}`, _)),
|
|
23
23
|
// Effect.tapError((cause) => Effect.logError(`forwardRequest err: ${req._tag}`, cause)),
|
|
24
|
-
Effect.logWarnIfTakesLongerThan({
|
|
24
|
+
Effect.interruptible, Effect.logWarnIfTakesLongerThan({
|
|
25
25
|
label: `@livestore/adapter-web:shared-worker:forwardRequest:${req._tag}`,
|
|
26
26
|
duration: 500,
|
|
27
27
|
}), Effect.mapError((cause) => Schema.is(UnexpectedError)(cause)
|
|
@@ -29,49 +29,31 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
29
29
|
: ParseResult.isParseError(cause) || Schema.is(WorkerError.WorkerError)(cause)
|
|
30
30
|
? new UnexpectedError({ cause })
|
|
31
31
|
: cause), Effect.catchAllDefect((cause) => new UnexpectedError({ cause })), Effect.tapCauseLogPretty);
|
|
32
|
-
// const forwardRequestStream = <TReq extends WorkerSchema.DedicatedWorkerInner.Request>(
|
|
33
|
-
// req: TReq,
|
|
34
|
-
// ): TReq extends Serializable.WithResult<infer A, infer _I, infer _E, infer _EI, infer _R>
|
|
35
|
-
// ? Stream.Stream<A, UnexpectedError, never>
|
|
36
|
-
// : never =>
|
|
37
|
-
// waitForWorker.pipe(
|
|
38
|
-
// Effect.logBefore(`forwardRequestStream: ${req._tag}`),
|
|
39
|
-
// Effect.andThen((worker) => worker.execute(req) as Stream.Stream<unknown, unknown, never>),
|
|
40
|
-
// Effect.interruptible,
|
|
41
|
-
// UnexpectedError.mapToUnexpectedError,
|
|
42
|
-
// Effect.tapCauseLogPretty,
|
|
43
|
-
// Stream.unwrap,
|
|
44
|
-
// Stream.ensuring(Effect.logDebug(`shutting down stream for ${req._tag}`)),
|
|
45
|
-
// UnexpectedError.mapToUnexpectedErrorStream,
|
|
46
|
-
// ) as any
|
|
47
|
-
// TODO bring back the `forwardRequestStream` impl above. Needs debugging with Tim Smart
|
|
48
|
-
// It seems the in-progress streams are not being closed properly if the worker is closed (e.g. by closing the leader tab)
|
|
49
32
|
const forwardRequestStream = (req) => Effect.gen(function* () {
|
|
33
|
+
yield* Effect.logDebug(`forwardRequestStream: ${req._tag}`);
|
|
50
34
|
const { worker, scope } = yield* SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
const stream = worker.execute(req);
|
|
36
|
+
// It seems the request stream is not automatically interrupted when the scope shuts down
|
|
37
|
+
// so we need to manually interrupt it when the scope shuts down
|
|
38
|
+
const shutdownDeferred = yield* Deferred.make();
|
|
39
|
+
yield* Scope.addFinalizer(scope, Deferred.succeed(shutdownDeferred, undefined));
|
|
40
|
+
// Here we're creating an empty stream that will finish when the scope shuts down
|
|
41
|
+
const scopeShutdownStream = Effect.gen(function* () {
|
|
42
|
+
yield* shutdownDeferred;
|
|
43
|
+
return Stream.empty;
|
|
44
|
+
}).pipe(Stream.unwrap);
|
|
45
|
+
return Stream.merge(stream, scopeShutdownStream, { haltStrategy: 'either' });
|
|
46
|
+
}).pipe(Effect.interruptible, UnexpectedError.mapToUnexpectedError, Effect.tapCauseLogPretty, Stream.unwrap, Stream.ensuring(Effect.logDebug(`shutting down stream for ${req._tag}`)), UnexpectedError.mapToUnexpectedErrorStream);
|
|
61
47
|
const resetCurrentWorkerCtx = Effect.gen(function* () {
|
|
62
48
|
const prevWorker = yield* SubscriptionRef.get(leaderWorkerContextSubRef);
|
|
63
49
|
if (prevWorker !== undefined) {
|
|
64
50
|
// NOTE we're already unsetting the current worker here, so new incoming requests are queued for the new worker
|
|
65
51
|
yield* SubscriptionRef.set(leaderWorkerContextSubRef, undefined);
|
|
66
52
|
yield* Effect.yieldNow();
|
|
67
|
-
yield* Scope.close(prevWorker.scope, Exit.void).pipe(
|
|
68
|
-
// TODO there still seem to be scenarios where it takes longer than 1 second which is leading to problems
|
|
69
|
-
Effect.timeout(Duration.seconds(1)), Effect.logWarnIfTakesLongerThan({
|
|
53
|
+
yield* Scope.close(prevWorker.scope, Exit.void).pipe(Effect.logWarnIfTakesLongerThan({
|
|
70
54
|
label: '@livestore/adapter-web:shared-worker:close-previous-worker',
|
|
71
55
|
duration: 500,
|
|
72
|
-
})
|
|
73
|
-
// Effect.catchTag('TimeoutException', () => Scope.close(prevWorker.scope, Exit.fail('boom'))),
|
|
74
|
-
Effect.ignoreLogged);
|
|
56
|
+
}));
|
|
75
57
|
}
|
|
76
58
|
}).pipe(Effect.withSpan('@livestore/adapter-web:shared-worker:resetCurrentWorkerCtx'));
|
|
77
59
|
// const devtoolsWebBridge = yield* makeDevtoolsWebBridge
|
|
@@ -115,23 +97,21 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
115
97
|
const initialMessagePayload = yield* initialMessagePayloadDeferredRef.get.pipe(Effect.andThen(Deferred.await));
|
|
116
98
|
yield* resetCurrentWorkerCtx;
|
|
117
99
|
const scope = yield* Scope.make();
|
|
118
|
-
const workerDeferred = yield* Deferred.make();
|
|
119
|
-
// TODO we could also keep the pool instance around to re-use it by removing the previous worker and adding a new one
|
|
120
|
-
yield* Worker.makePoolSerialized({
|
|
121
|
-
size: 1,
|
|
122
|
-
concurrency: 100,
|
|
123
|
-
initialMessage: () => initialMessagePayload.initialMessage,
|
|
124
|
-
}).pipe(Effect.tap((worker) => Deferred.succeed(workerDeferred, worker)), Effect.provide(BrowserWorker.layer(() => port)), Effect.catchAllCause((cause) => new UnexpectedError({ cause })), Effect.tapError((cause) => Deferred.fail(workerDeferred, cause)), Effect.withSpan('@livestore/adapter-web:shared-worker:makeWorkerProxyFromPort'), Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
|
|
125
100
|
yield* Effect.gen(function* () {
|
|
126
101
|
const shutdownChannel = yield* makeShutdownChannel(initialMessagePayload.initialMessage.storeId);
|
|
127
|
-
yield* shutdownChannel.listen.pipe(Stream.flatten(), Stream.tap(() => reset), Stream.runDrain);
|
|
102
|
+
yield* shutdownChannel.listen.pipe(Stream.flatten(), Stream.tap(() => reset), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
103
|
+
const workerLayer = yield* Layer.build(BrowserWorker.layer(() => port));
|
|
104
|
+
const worker = yield* Worker.makePoolSerialized({
|
|
105
|
+
size: 1,
|
|
106
|
+
concurrency: 100,
|
|
107
|
+
initialMessage: () => initialMessagePayload.initialMessage,
|
|
108
|
+
}).pipe(Effect.provide(workerLayer), Effect.withSpan('@livestore/adapter-web:shared-worker:makeWorkerProxyFromPort'));
|
|
109
|
+
// Prepare the web mesh connection for leader worker to be able to connect to the devtools
|
|
110
|
+
const { node } = yield* WebmeshWorker.CacheService;
|
|
111
|
+
const { storeId, clientId } = initialMessagePayload.initialMessage;
|
|
112
|
+
yield* connectViaWorker({ node, worker, target: `leader-${storeId}-${clientId}` }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
113
|
+
yield* SubscriptionRef.set(leaderWorkerContextSubRef, { worker, scope });
|
|
128
114
|
}).pipe(Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
|
|
129
|
-
const worker = yield* workerDeferred;
|
|
130
|
-
// Prepare the web mesh connection for leader worker to be able to connect to the devtools
|
|
131
|
-
const { node } = yield* WebMeshWorker.CacheService;
|
|
132
|
-
const { storeId, clientId } = initialMessagePayload.initialMessage;
|
|
133
|
-
yield* connectViaWorker({ node, worker, target: `leader-${storeId}-${clientId}` }).pipe(Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
|
|
134
|
-
yield* SubscriptionRef.set(leaderWorkerContextSubRef, { worker, scope });
|
|
135
115
|
}).pipe(Effect.withSpan('@livestore/adapter-web:shared-worker:updateMessagePort'), UnexpectedError.mapToUnexpectedError, Effect.tapCauseLogPretty),
|
|
136
116
|
// Proxied requests
|
|
137
117
|
BootStatusStream: forwardRequestStream,
|
|
@@ -143,18 +123,16 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
143
123
|
Setup: forwardRequest,
|
|
144
124
|
GetLeaderSyncState: forwardRequest,
|
|
145
125
|
GetLeaderHead: forwardRequest,
|
|
146
|
-
NetworkStatusStream: forwardRequestStream,
|
|
147
126
|
Shutdown: forwardRequest,
|
|
148
127
|
ExtraDevtoolsMessage: forwardRequest,
|
|
149
128
|
// Accept devtools connections (from leader and client sessions)
|
|
150
|
-
'DevtoolsWebCommon.CreateConnection':
|
|
151
|
-
// ...devtoolsWebBridge.handlers,
|
|
129
|
+
'DevtoolsWebCommon.CreateConnection': WebmeshWorker.CreateConnection,
|
|
152
130
|
});
|
|
153
131
|
}).pipe(Layer.unwrapScoped);
|
|
154
132
|
export const makeWorker = () => {
|
|
155
133
|
makeWorkerRunner.pipe(Layer.provide(BrowserWorkerRunner.layer),
|
|
156
134
|
// WorkerRunner.launch,
|
|
157
|
-
Layer.launch, Effect.scoped, Effect.tapCauseLogPretty, Effect.annotateLogs({ thread: self.name }), Effect.provide(Logger.prettyWithThread(self.name)), Effect.provide(FetchHttpClient.layer), Effect.provide(
|
|
135
|
+
Layer.launch, Effect.scoped, Effect.tapCauseLogPretty, Effect.annotateLogs({ thread: self.name }), Effect.provide(Logger.prettyWithThread(self.name)), Effect.provide(FetchHttpClient.layer), Effect.provide(WebmeshWorker.CacheService.layer({ nodeName: 'shared-worker' })), LS_DEV ? TaskTracing.withAsyncTaggingTracing((name) => console.createTask(name)) : identity,
|
|
158
136
|
// TODO remove type-cast (currently needed to silence a tsc bug)
|
|
159
137
|
(_) => _, Logger.withMinimumLogLevel(LogLevel.Debug), Effect.runFork);
|
|
160
138
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-shared-worker.js","sourceRoot":"","sources":["../../../src/web-worker/shared-worker/make-shared-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAA;AAC7E,OAAO,KAAK,aAAa,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,
|
|
1
|
+
{"version":3,"file":"make-shared-worker.js","sourceRoot":"","sources":["../../../src/web-worker/shared-worker/make-shared-worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/adapter-web",
|
|
3
|
-
"version": "0.0.0-snapshot-
|
|
3
|
+
"version": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@opentelemetry/api": "1.9.0",
|
|
54
|
-
"@livestore/common": "0.0.0-snapshot-
|
|
55
|
-
"@livestore/devtools-web-common": "0.0.0-snapshot-
|
|
56
|
-
"@livestore/sqlite-wasm": "0.0.0-snapshot-
|
|
57
|
-
"@livestore/
|
|
58
|
-
"@livestore/
|
|
54
|
+
"@livestore/common": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0",
|
|
55
|
+
"@livestore/devtools-web-common": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0",
|
|
56
|
+
"@livestore/sqlite-wasm": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0",
|
|
57
|
+
"@livestore/utils": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0",
|
|
58
|
+
"@livestore/webmesh": "0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/chrome": "^0.0.304",
|
|
@@ -46,16 +46,13 @@ export const makeInMemoryAdapter =
|
|
|
46
46
|
sessionId: nanoid(6),
|
|
47
47
|
leaderThread: {
|
|
48
48
|
mutations: {
|
|
49
|
-
pull: Stream.never,
|
|
49
|
+
pull: () => Stream.never,
|
|
50
50
|
push: () => Effect.void,
|
|
51
51
|
},
|
|
52
52
|
initialState: { leaderHead: EventId.ROOT, migrationsReport },
|
|
53
53
|
export: Effect.sync(() => sqliteDb.export()),
|
|
54
54
|
getMutationLogData: Effect.succeed(new Uint8Array()),
|
|
55
55
|
getSyncState: Effect.dieMessage('Not implemented'),
|
|
56
|
-
networkStatus: SubscriptionRef.make({ isConnected: false, timestampMs: Date.now(), latchClosed: false }).pipe(
|
|
57
|
-
Effect.runSync,
|
|
58
|
-
),
|
|
59
56
|
sendDevtoolsMessage: () => Effect.dieMessage('Not implemented'),
|
|
60
57
|
},
|
|
61
58
|
lockStatus,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Adapter, ClientSession, LockStatus
|
|
1
|
+
import type { Adapter, ClientSession, LockStatus } from '@livestore/common'
|
|
2
2
|
import { Devtools, IntentionalShutdownCause, StoreInterrupted, UnexpectedError } from '@livestore/common'
|
|
3
3
|
// TODO bring back - this currently doesn't work due to https://github.com/vitejs/vite/issues/8427
|
|
4
4
|
// NOTE We're using a non-relative import here for Vite to properly resolve the import during app builds
|
|
@@ -91,6 +91,15 @@ export type WebAdapterOptions = {
|
|
|
91
91
|
* store it in `sessionStorage` and restore it for subsequent client sessions in the same tab/window.
|
|
92
92
|
*/
|
|
93
93
|
sessionId?: string
|
|
94
|
+
experimental?: {
|
|
95
|
+
/**
|
|
96
|
+
* When set to `true`, the adapter will always start with a snapshot from the leader
|
|
97
|
+
* instead of trying to load a snapshot from storage.
|
|
98
|
+
*
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
101
|
+
disableFastPath?: boolean
|
|
102
|
+
}
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
export const makePersistedAdapter =
|
|
@@ -116,7 +125,11 @@ export const makePersistedAdapter =
|
|
|
116
125
|
|
|
117
126
|
const storageOptions = yield* Schema.decode(WorkerSchema.StorageType)(options.storage)
|
|
118
127
|
|
|
128
|
+
const shutdownChannel = yield* makeShutdownChannel(storeId)
|
|
129
|
+
|
|
119
130
|
if (options.resetPersistence === true) {
|
|
131
|
+
yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'adapter-reset' }))
|
|
132
|
+
|
|
120
133
|
yield* resetPersistedDataFromClientSession({ storageOptions, storeId })
|
|
121
134
|
}
|
|
122
135
|
|
|
@@ -126,14 +139,16 @@ export const makePersistedAdapter =
|
|
|
126
139
|
// we usually speeds up the boot process by a lot.
|
|
127
140
|
// We need to be extra careful though to not run into any race conditions or inconsistencies.
|
|
128
141
|
// TODO also verify persisted data
|
|
129
|
-
const dataFromFile =
|
|
142
|
+
const dataFromFile =
|
|
143
|
+
options.experimental?.disableFastPath === true
|
|
144
|
+
? undefined
|
|
145
|
+
: yield* readPersistedAppDbFromClientSession({ storageOptions, storeId, schema })
|
|
130
146
|
|
|
131
147
|
// The same across all client sessions (i.e. tabs, windows)
|
|
132
148
|
const clientId = options.clientId ?? getPersistedId(`clientId:${storeId}`, 'local')
|
|
133
149
|
// Unique per client session (i.e. tab, window)
|
|
134
150
|
const sessionId = options.sessionId ?? getPersistedId(`sessionId:${storeId}`, 'session')
|
|
135
151
|
|
|
136
|
-
const shutdownChannel = yield* makeShutdownChannel(storeId)
|
|
137
152
|
const workerDisconnectChannel = yield* makeWorkerDisconnectChannel(storeId)
|
|
138
153
|
|
|
139
154
|
yield* shutdownChannel.listen.pipe(
|
|
@@ -190,7 +205,7 @@ export const makePersistedAdapter =
|
|
|
190
205
|
|
|
191
206
|
const runLocked = Effect.gen(function* () {
|
|
192
207
|
yield* Effect.logDebug(
|
|
193
|
-
`[@livestore/adapter-web:client-session] ✅ Got lock '${LIVESTORE_TAB_LOCK}' (clientId: ${clientId}, sessionId: ${sessionId})
|
|
208
|
+
`[@livestore/adapter-web:client-session] ✅ Got lock '${LIVESTORE_TAB_LOCK}' (clientId: ${clientId}, sessionId: ${sessionId}).`,
|
|
194
209
|
)
|
|
195
210
|
|
|
196
211
|
yield* Effect.addFinalizer(() =>
|
|
@@ -227,29 +242,6 @@ export const makePersistedAdapter =
|
|
|
227
242
|
|
|
228
243
|
yield* Deferred.succeed(waitForSharedWorkerInitialized, undefined)
|
|
229
244
|
|
|
230
|
-
yield* Effect.addFinalizer(() =>
|
|
231
|
-
Effect.gen(function* () {
|
|
232
|
-
// console.log('[@livestore/adapter-web:client-session] Shutting down leader worker')
|
|
233
|
-
// We first try to gracefully shutdown the leader worker and then forcefully terminate it
|
|
234
|
-
// yield* Effect.raceFirst(
|
|
235
|
-
// sharedWorker
|
|
236
|
-
// .executeEffect(new WorkerSchema.LeaderWorkerInner.Shutdown({}))
|
|
237
|
-
// .pipe(Effect.andThen(() => worker.terminate())),
|
|
238
|
-
// Effect.sync(() => {
|
|
239
|
-
// console.warn(
|
|
240
|
-
// '[@livestore/adapter-web:client-session] Worker did not gracefully shutdown in time, terminating it',
|
|
241
|
-
// )
|
|
242
|
-
// worker.terminate()
|
|
243
|
-
// }).pipe(
|
|
244
|
-
// // Seems like we still need to wait a bit for the worker to terminate
|
|
245
|
-
// // TODO improve this implementation (possibly via another weblock?)
|
|
246
|
-
// Effect.delay(1000),
|
|
247
|
-
// ),
|
|
248
|
-
// )
|
|
249
|
-
// yield* Effect.logDebug('[@livestore/adapter-web:client-session] client-session shutdown. worker terminated')
|
|
250
|
-
}).pipe(Effect.withSpan('@livestore/adapter-web:client-session:lock:shutdown'), Effect.ignoreLogged),
|
|
251
|
-
)
|
|
252
|
-
|
|
253
245
|
yield* Effect.never
|
|
254
246
|
}).pipe(Effect.withSpan('@livestore/adapter-web:client-session:lock'))
|
|
255
247
|
|
|
@@ -319,22 +311,6 @@ export const makePersistedAdapter =
|
|
|
319
311
|
)
|
|
320
312
|
}).pipe(Stream.unwrap) as any
|
|
321
313
|
|
|
322
|
-
const networkStatus = yield* SubscriptionRef.make<NetworkStatus>({
|
|
323
|
-
isConnected: false,
|
|
324
|
-
timestampMs: Date.now(),
|
|
325
|
-
latchClosed: false,
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
yield* runInWorkerStream(new WorkerSchema.LeaderWorkerInner.NetworkStatusStream()).pipe(
|
|
329
|
-
Stream.tap((_) => SubscriptionRef.set(networkStatus, _)),
|
|
330
|
-
Stream.runDrain,
|
|
331
|
-
Effect.forever, // NOTE Whenever the leader changes, we need to re-start the stream
|
|
332
|
-
Effect.tapErrorCause((cause) => Effect.sync(() => shutdown(cause))),
|
|
333
|
-
Effect.interruptible,
|
|
334
|
-
Effect.tapCauseLogPretty,
|
|
335
|
-
Effect.forkScoped,
|
|
336
|
-
)
|
|
337
|
-
|
|
338
314
|
const bootStatusFiber = yield* runInWorkerStream(new WorkerSchema.LeaderWorkerInner.BootStatusStream()).pipe(
|
|
339
315
|
Stream.tap((_) => Queue.offer(bootStatusQueue, _)),
|
|
340
316
|
Stream.runDrain,
|
|
@@ -435,9 +411,8 @@ export const makePersistedAdapter =
|
|
|
435
411
|
),
|
|
436
412
|
|
|
437
413
|
mutations: {
|
|
438
|
-
pull:
|
|
439
|
-
Stream.orDie,
|
|
440
|
-
),
|
|
414
|
+
pull: ({ cursor }) =>
|
|
415
|
+
runInWorkerStream(new WorkerSchema.LeaderWorkerInner.PullStream({ cursor })).pipe(Stream.orDie),
|
|
441
416
|
push: (batch) =>
|
|
442
417
|
runInWorker(new WorkerSchema.LeaderWorkerInner.PushToLeader({ batch })).pipe(
|
|
443
418
|
Effect.withSpan('@livestore/adapter-web:client-session:pushToLeader', {
|
|
@@ -459,8 +434,6 @@ export const makePersistedAdapter =
|
|
|
459
434
|
Effect.withSpan('@livestore/adapter-web:client-session:getLeaderSyncState'),
|
|
460
435
|
),
|
|
461
436
|
|
|
462
|
-
networkStatus,
|
|
463
|
-
|
|
464
437
|
sendDevtoolsMessage: (message) =>
|
|
465
438
|
runInWorker(new WorkerSchema.LeaderWorkerInner.ExtraDevtoolsMessage({ message })).pipe(
|
|
466
439
|
UnexpectedError.mapToUnexpectedError,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { liveStoreStorageFormatVersion } from '@livestore/common'
|
|
1
|
+
import { liveStoreStorageFormatVersion, UnexpectedError } from '@livestore/common'
|
|
2
2
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
3
|
import { decodeSAHPoolFilename, HEADER_OFFSET_DATA } from '@livestore/sqlite-wasm/browser'
|
|
4
|
-
import { Effect, Schema } from '@livestore/utils/effect'
|
|
4
|
+
import { Effect, Schedule, Schema } from '@livestore/utils/effect'
|
|
5
5
|
|
|
6
6
|
import * as OpfsUtils from '../../opfs-utils.js'
|
|
7
7
|
import type * as WorkerSchema from './worker-schema.js'
|
|
@@ -87,7 +87,12 @@ export const resetPersistedDataFromClientSession = ({
|
|
|
87
87
|
Effect.gen(function* () {
|
|
88
88
|
const directory = sanitizeOpfsDir(storageOptions.directory, storeId)
|
|
89
89
|
yield* opfsDeleteAbs(directory)
|
|
90
|
-
}).pipe(
|
|
90
|
+
}).pipe(
|
|
91
|
+
Effect.retry({
|
|
92
|
+
schedule: Schedule.exponentialBackoff10Sec,
|
|
93
|
+
}),
|
|
94
|
+
Effect.withSpan('@livestore/adapter-web:resetPersistedDataFromClientSession'),
|
|
95
|
+
)
|
|
91
96
|
|
|
92
97
|
const opfsDeleteAbs = (absPath: string) =>
|
|
93
98
|
Effect.promise(async () => {
|
|
@@ -114,7 +119,10 @@ const opfsDeleteAbs = (absPath: string) =>
|
|
|
114
119
|
throw error
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
|
-
}).pipe(
|
|
122
|
+
}).pipe(
|
|
123
|
+
UnexpectedError.mapToUnexpectedError,
|
|
124
|
+
Effect.withSpan('@livestore/adapter-web:worker:opfsDeleteFile', { attributes: { absFilePath: absPath } }),
|
|
125
|
+
)
|
|
118
126
|
|
|
119
127
|
export const sanitizeOpfsDir = (directory: string | undefined, storeId: string) => {
|
|
120
128
|
// Root dir should be `''` not `/`
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BootStatus,
|
|
3
|
-
Devtools,
|
|
4
|
-
LeaderAheadError,
|
|
5
|
-
MigrationsReport,
|
|
6
|
-
NetworkStatus,
|
|
7
|
-
SyncState,
|
|
8
|
-
UnexpectedError,
|
|
9
|
-
} from '@livestore/common'
|
|
1
|
+
import { BootStatus, Devtools, LeaderAheadError, MigrationsReport, SyncState, UnexpectedError } from '@livestore/common'
|
|
10
2
|
import { EventId, MutationEvent } from '@livestore/common/schema'
|
|
11
|
-
import * as
|
|
3
|
+
import * as WebmeshWorker from '@livestore/devtools-web-common/worker'
|
|
12
4
|
import { Schema, Transferable } from '@livestore/utils/effect'
|
|
13
5
|
|
|
14
6
|
export const StorageTypeOpfs = Schema.Struct({
|
|
@@ -84,11 +76,11 @@ export namespace LeaderWorkerInner {
|
|
|
84
76
|
|
|
85
77
|
export class PullStream extends Schema.TaggedRequest<PullStream>()('PullStream', {
|
|
86
78
|
payload: {
|
|
87
|
-
cursor:
|
|
79
|
+
cursor: Schema.Number,
|
|
88
80
|
},
|
|
89
81
|
success: Schema.Struct({
|
|
90
82
|
payload: SyncState.PayloadUpstream,
|
|
91
|
-
|
|
83
|
+
mergeCounter: Schema.Number,
|
|
92
84
|
}),
|
|
93
85
|
failure: UnexpectedError,
|
|
94
86
|
}) {}
|
|
@@ -126,12 +118,6 @@ export namespace LeaderWorkerInner {
|
|
|
126
118
|
failure: UnexpectedError,
|
|
127
119
|
}) {}
|
|
128
120
|
|
|
129
|
-
export class NetworkStatusStream extends Schema.TaggedRequest<NetworkStatusStream>()('NetworkStatusStream', {
|
|
130
|
-
payload: {},
|
|
131
|
-
success: NetworkStatus,
|
|
132
|
-
failure: UnexpectedError,
|
|
133
|
-
}) {}
|
|
134
|
-
|
|
135
121
|
export class Shutdown extends Schema.TaggedRequest<Shutdown>()('Shutdown', {
|
|
136
122
|
payload: {},
|
|
137
123
|
success: Schema.Void,
|
|
@@ -156,10 +142,9 @@ export namespace LeaderWorkerInner {
|
|
|
156
142
|
GetRecreateSnapshot,
|
|
157
143
|
GetLeaderHead,
|
|
158
144
|
GetLeaderSyncState,
|
|
159
|
-
NetworkStatusStream,
|
|
160
145
|
Shutdown,
|
|
161
146
|
ExtraDevtoolsMessage,
|
|
162
|
-
|
|
147
|
+
WebmeshWorker.Schema.CreateConnection,
|
|
163
148
|
)
|
|
164
149
|
export type Request = typeof Request.Type
|
|
165
150
|
}
|
|
@@ -198,10 +183,9 @@ export namespace SharedWorker {
|
|
|
198
183
|
LeaderWorkerInner.ExportMutationlog,
|
|
199
184
|
LeaderWorkerInner.GetLeaderHead,
|
|
200
185
|
LeaderWorkerInner.GetLeaderSyncState,
|
|
201
|
-
LeaderWorkerInner.NetworkStatusStream,
|
|
202
186
|
LeaderWorkerInner.Shutdown,
|
|
203
187
|
LeaderWorkerInner.ExtraDevtoolsMessage,
|
|
204
188
|
|
|
205
|
-
|
|
189
|
+
WebmeshWorker.Schema.CreateConnection,
|
|
206
190
|
) {}
|
|
207
191
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SqliteDb, SyncOptions } from '@livestore/common'
|
|
2
2
|
import { Devtools, UnexpectedError } from '@livestore/common'
|
|
3
3
|
import type { DevtoolsOptions } from '@livestore/common/leader-thread'
|
|
4
4
|
import {
|
|
5
5
|
configureConnection,
|
|
6
|
-
getClientHeadFromDb,
|
|
7
6
|
LeaderThreadCtx,
|
|
8
7
|
makeLeaderThreadLayer,
|
|
8
|
+
Mutationlog,
|
|
9
9
|
} from '@livestore/common/leader-thread'
|
|
10
10
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
11
11
|
import { MutationEvent } from '@livestore/common/schema'
|
|
12
12
|
import { makeChannelForConnectedMeshNode } from '@livestore/devtools-web-common/web-channel'
|
|
13
|
-
import * as
|
|
13
|
+
import * as WebmeshWorker from '@livestore/devtools-web-common/worker'
|
|
14
14
|
import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
|
|
15
15
|
import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
|
|
16
16
|
import { isDevEnv, LS_DEV } from '@livestore/utils'
|
|
@@ -97,7 +97,7 @@ const makeWorkerRunnerOuter = (
|
|
|
97
97
|
Effect.scoped,
|
|
98
98
|
Effect.withSpan('@livestore/adapter-web:worker:wrapper:InitialMessage:innerFiber'),
|
|
99
99
|
Effect.tapCauseLogPretty,
|
|
100
|
-
Effect.provide(
|
|
100
|
+
Effect.provide(WebmeshWorker.CacheService.layer({ nodeName: `leader-${storeId}-${clientId}` })),
|
|
101
101
|
Effect.forkScoped,
|
|
102
102
|
)
|
|
103
103
|
|
|
@@ -175,9 +175,8 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
|
|
|
175
175
|
),
|
|
176
176
|
PullStream: ({ cursor }) =>
|
|
177
177
|
Effect.gen(function* () {
|
|
178
|
-
const {
|
|
179
|
-
|
|
180
|
-
return Stream.fromQueue(pullQueue)
|
|
178
|
+
const { syncProcessor } = yield* LeaderThreadCtx
|
|
179
|
+
return syncProcessor.pull({ cursor })
|
|
181
180
|
}).pipe(
|
|
182
181
|
Stream.unwrapScoped,
|
|
183
182
|
// For debugging purposes
|
|
@@ -206,7 +205,7 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
|
|
|
206
205
|
GetLeaderHead: () =>
|
|
207
206
|
Effect.gen(function* () {
|
|
208
207
|
const workerCtx = yield* LeaderThreadCtx
|
|
209
|
-
return getClientHeadFromDb(workerCtx.dbMutationLog)
|
|
208
|
+
return Mutationlog.getClientHeadFromDb(workerCtx.dbMutationLog)
|
|
210
209
|
}).pipe(UnexpectedError.mapToUnexpectedError, Effect.withSpan('@livestore/adapter-web:worker:GetLeaderHead')),
|
|
211
210
|
GetLeaderSyncState: () =>
|
|
212
211
|
Effect.gen(function* () {
|
|
@@ -216,19 +215,6 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
|
|
|
216
215
|
UnexpectedError.mapToUnexpectedError,
|
|
217
216
|
Effect.withSpan('@livestore/adapter-web:worker:GetLeaderSyncState'),
|
|
218
217
|
),
|
|
219
|
-
NetworkStatusStream: () =>
|
|
220
|
-
Effect.gen(function* (_) {
|
|
221
|
-
const ctx = yield* LeaderThreadCtx
|
|
222
|
-
|
|
223
|
-
if (ctx.syncBackend === undefined) {
|
|
224
|
-
return Stream.make<[NetworkStatus]>({ isConnected: false, timestampMs: Date.now(), latchClosed: false })
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return Stream.zipLatest(
|
|
228
|
-
ctx.syncBackend.isConnected.changes,
|
|
229
|
-
ctx.devtools.enabled ? ctx.devtools.syncBackendLatchState.changes : Stream.make({ latchClosed: false }),
|
|
230
|
-
).pipe(Stream.map(([isConnected, { latchClosed }]) => ({ isConnected, timestampMs: Date.now(), latchClosed })))
|
|
231
|
-
}).pipe(Stream.unwrap),
|
|
232
218
|
Shutdown: () =>
|
|
233
219
|
Effect.gen(function* () {
|
|
234
220
|
yield* Effect.logDebug('[@livestore/adapter-web:worker] Shutdown')
|
|
@@ -242,7 +228,7 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
|
|
|
242
228
|
UnexpectedError.mapToUnexpectedError,
|
|
243
229
|
Effect.withSpan('@livestore/adapter-web:worker:ExtraDevtoolsMessage'),
|
|
244
230
|
),
|
|
245
|
-
'DevtoolsWebCommon.CreateConnection':
|
|
231
|
+
'DevtoolsWebCommon.CreateConnection': WebmeshWorker.CreateConnection,
|
|
246
232
|
})
|
|
247
233
|
|
|
248
234
|
const makeDevtoolsOptions = ({
|
|
@@ -253,12 +239,12 @@ const makeDevtoolsOptions = ({
|
|
|
253
239
|
devtoolsEnabled: boolean
|
|
254
240
|
dbReadModel: SqliteDb
|
|
255
241
|
dbMutationLog: SqliteDb
|
|
256
|
-
}): Effect.Effect<DevtoolsOptions, UnexpectedError, Scope.Scope |
|
|
242
|
+
}): Effect.Effect<DevtoolsOptions, UnexpectedError, Scope.Scope | WebmeshWorker.CacheService> =>
|
|
257
243
|
Effect.gen(function* () {
|
|
258
244
|
if (devtoolsEnabled === false) {
|
|
259
245
|
return { enabled: false }
|
|
260
246
|
}
|
|
261
|
-
const { node } = yield*
|
|
247
|
+
const { node } = yield* WebmeshWorker.CacheService
|
|
262
248
|
|
|
263
249
|
return {
|
|
264
250
|
enabled: true,
|