@livestore/adapter-web 0.3.0-dev.16 → 0.3.0-dev.17
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/common/connection.d.ts.map +1 -1
- package/dist/devtools-bridge/background-browser-channel.d.ts.map +1 -1
- package/dist/devtools-bridge/bridge-shared.d.ts.map +1 -1
- package/dist/in-memory/index.d.ts.map +1 -1
- package/dist/opfs-utils.d.ts.map +1 -1
- package/dist/web-worker/client-session/client-session-devtools.d.ts.map +1 -1
- package/dist/web-worker/client-session/index.d.ts.map +1 -1
- package/dist/web-worker/client-session/index.js +13 -27
- package/dist/web-worker/client-session/index.js.map +1 -1
- package/dist/web-worker/common/persisted-sqlite.d.ts.map +1 -1
- package/dist/web-worker/common/shutdown-channel.d.ts +1 -5
- package/dist/web-worker/common/shutdown-channel.d.ts.map +1 -1
- package/dist/web-worker/common/worker-disconnect-channel.d.ts +12 -0
- package/dist/web-worker/common/worker-disconnect-channel.d.ts.map +1 -0
- package/dist/web-worker/common/worker-disconnect-channel.js +9 -0
- package/dist/web-worker/common/worker-disconnect-channel.js.map +1 -0
- package/dist/web-worker/common/worker-schema.d.ts +2 -2
- package/dist/web-worker/common/worker-schema.d.ts.map +1 -1
- package/dist/web-worker/common/worker-schema.js +2 -2
- package/dist/web-worker/leader-worker/make-leader-worker.d.ts +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 +4 -2
- 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 +5 -3
- package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -1
- package/package.json +6 -6
- package/src/web-worker/client-session/index.ts +20 -34
- package/src/web-worker/common/worker-disconnect-channel.ts +10 -0
- package/src/web-worker/common/worker-schema.ts +2 -2
- package/src/web-worker/leader-worker/make-leader-worker.ts +4 -2
- package/src/web-worker/shared-worker/make-shared-worker.ts +2 -2
- package/dist/web-worker/client-session/trim-batch.d.ts +0 -4
- package/dist/web-worker/client-session/trim-batch.d.ts.map +0 -1
- package/dist/web-worker/client-session/trim-batch.js +0 -13
- package/dist/web-worker/client-session/trim-batch.js.map +0 -1
- package/dist/web-worker/client-session/trim-batch.test.d.ts +0 -2
- package/dist/web-worker/client-session/trim-batch.test.d.ts.map +0 -1
- package/dist/web-worker/client-session/trim-batch.test.js +0 -38
- package/dist/web-worker/client-session/trim-batch.test.js.map +0 -1
- package/src/web-worker/client-session/trim-batch.test.ts +0 -48
- package/src/web-worker/client-session/trim-batch.ts +0 -15
|
@@ -3,8 +3,6 @@ import { Devtools, IntentionalShutdownCause, UnexpectedError } from '@livestore/
|
|
|
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
|
|
5
5
|
// import LiveStoreSharedWorker from '@livestore/adapter-web/internal-shared-worker?sharedworker'
|
|
6
|
-
import { ShutdownChannel } from '@livestore/common/leader-thread'
|
|
7
|
-
import type { MutationEvent } from '@livestore/common/schema'
|
|
8
6
|
import { EventId, SESSION_CHANGESET_META_TABLE } from '@livestore/common/schema'
|
|
9
7
|
import { makeWebDevtoolsChannel } from '@livestore/devtools-web-common/web-channel'
|
|
10
8
|
import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
|
|
@@ -12,7 +10,6 @@ import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
|
|
|
12
10
|
import { isDevEnv, shouldNeverHappen, tryAsFunctionAndNew } from '@livestore/utils'
|
|
13
11
|
import {
|
|
14
12
|
BrowserWorker,
|
|
15
|
-
BucketQueue,
|
|
16
13
|
Cause,
|
|
17
14
|
Deferred,
|
|
18
15
|
Effect,
|
|
@@ -32,9 +29,9 @@ import { nanoid } from '@livestore/utils/nanoid'
|
|
|
32
29
|
import * as OpfsUtils from '../../opfs-utils.js'
|
|
33
30
|
import { readPersistedAppDbFromClientSession, resetPersistedDataFromClientSession } from '../common/persisted-sqlite.js'
|
|
34
31
|
import { makeShutdownChannel } from '../common/shutdown-channel.js'
|
|
32
|
+
import { DedicatedWorkerDisconnectBroadcast, makeWorkerDisconnectChannel } from '../common/worker-disconnect-channel.js'
|
|
35
33
|
import * as WorkerSchema from '../common/worker-schema.js'
|
|
36
34
|
import { bootDevtools } from './client-session-devtools.js'
|
|
37
|
-
import { trimPushBatch } from './trim-batch.js'
|
|
38
35
|
|
|
39
36
|
// NOTE we're starting to initialize the sqlite wasm binary here to speed things up
|
|
40
37
|
const sqlite3Promise = loadSqlite3Wasm()
|
|
@@ -111,11 +108,11 @@ export const makeAdapter =
|
|
|
111
108
|
const sessionId = getPersistedId(`sessionId:${storeId}`, 'session')
|
|
112
109
|
|
|
113
110
|
const shutdownChannel = yield* makeShutdownChannel(storeId)
|
|
111
|
+
const workerDisconnectChannel = yield* makeWorkerDisconnectChannel(storeId)
|
|
114
112
|
|
|
115
113
|
yield* shutdownChannel.listen.pipe(
|
|
116
114
|
Stream.flatten(),
|
|
117
|
-
Stream.
|
|
118
|
-
Stream.tap((msg) => shutdown(Cause.fail(msg))),
|
|
115
|
+
Stream.tap((error) => Effect.sync(() => shutdown(Cause.fail(error)))),
|
|
119
116
|
Stream.runDrain,
|
|
120
117
|
Effect.interruptible,
|
|
121
118
|
Effect.tapCauseLogPretty,
|
|
@@ -144,7 +141,7 @@ export const makeAdapter =
|
|
|
144
141
|
Effect.provide(BrowserWorker.layer(() => sharedWebWorker)),
|
|
145
142
|
Effect.tapCauseLogPretty,
|
|
146
143
|
UnexpectedError.mapToUnexpectedError,
|
|
147
|
-
Effect.tapErrorCause(shutdown),
|
|
144
|
+
Effect.tapErrorCause((cause) => Effect.sync(() => shutdown(cause))),
|
|
148
145
|
Effect.withSpan('@livestore/adapter-web:client-session:setupSharedWorker'),
|
|
149
146
|
Effect.forkScoped,
|
|
150
147
|
)
|
|
@@ -187,18 +184,19 @@ export const makeAdapter =
|
|
|
187
184
|
}).pipe(
|
|
188
185
|
Effect.provide(BrowserWorker.layer(() => worker)),
|
|
189
186
|
UnexpectedError.mapToUnexpectedError,
|
|
190
|
-
Effect.tapErrorCause(shutdown),
|
|
187
|
+
Effect.tapErrorCause((cause) => Effect.sync(() => shutdown(cause))),
|
|
191
188
|
Effect.withSpan('@livestore/adapter-web:client-session:setupDedicatedWorker'),
|
|
192
189
|
Effect.tapCauseLogPretty,
|
|
193
190
|
Effect.forkScoped,
|
|
194
191
|
)
|
|
195
192
|
|
|
196
|
-
yield*
|
|
193
|
+
yield* workerDisconnectChannel.send(DedicatedWorkerDisconnectBroadcast.make({}))
|
|
197
194
|
|
|
198
195
|
const sharedWorker = yield* Fiber.join(sharedWorkerFiber)
|
|
199
|
-
yield* sharedWorker
|
|
200
|
-
.
|
|
201
|
-
.
|
|
196
|
+
yield* sharedWorker.executeEffect(new WorkerSchema.SharedWorker.UpdateMessagePort({ port: mc.port2 })).pipe(
|
|
197
|
+
UnexpectedError.mapToUnexpectedError,
|
|
198
|
+
Effect.tapErrorCause((cause) => Effect.sync(() => shutdown(cause))),
|
|
199
|
+
)
|
|
202
200
|
|
|
203
201
|
yield* Deferred.succeed(waitForSharedWorkerInitialized, undefined)
|
|
204
202
|
|
|
@@ -304,7 +302,7 @@ export const makeAdapter =
|
|
|
304
302
|
Stream.tap((_) => SubscriptionRef.set(networkStatus, _)),
|
|
305
303
|
Stream.runDrain,
|
|
306
304
|
Effect.forever, // NOTE Whenever the leader changes, we need to re-start the stream
|
|
307
|
-
Effect.tapErrorCause(shutdown),
|
|
305
|
+
Effect.tapErrorCause((cause) => Effect.sync(() => shutdown(cause))),
|
|
308
306
|
Effect.interruptible,
|
|
309
307
|
Effect.tapCauseLogPretty,
|
|
310
308
|
Effect.forkScoped,
|
|
@@ -313,7 +311,9 @@ export const makeAdapter =
|
|
|
313
311
|
const bootStatusFiber = yield* runInWorkerStream(new WorkerSchema.LeaderWorkerInner.BootStatusStream()).pipe(
|
|
314
312
|
Stream.tap((_) => Queue.offer(bootStatusQueue, _)),
|
|
315
313
|
Stream.runDrain,
|
|
316
|
-
Effect.tapErrorCause((cause) =>
|
|
314
|
+
Effect.tapErrorCause((cause) =>
|
|
315
|
+
Cause.isInterruptedOnly(cause) ? Effect.void : Effect.sync(() => shutdown(cause)),
|
|
316
|
+
),
|
|
317
317
|
Effect.interruptible,
|
|
318
318
|
Effect.tapCauseLogPretty,
|
|
319
319
|
Effect.forkScoped,
|
|
@@ -388,21 +388,6 @@ export const makeAdapter =
|
|
|
388
388
|
}).pipe(Effect.tapCauseLogPretty, Effect.orDie),
|
|
389
389
|
)
|
|
390
390
|
|
|
391
|
-
const pushQueue = yield* BucketQueue.make<MutationEvent.AnyEncoded>()
|
|
392
|
-
|
|
393
|
-
yield* Effect.gen(function* () {
|
|
394
|
-
const batch = yield* BucketQueue.takeBetween(pushQueue, 1, 100)
|
|
395
|
-
// We need to trim "old batches" which can happen during client session rebasing
|
|
396
|
-
const trimmedBatch = trimPushBatch(batch)
|
|
397
|
-
yield* runInWorker(new WorkerSchema.LeaderWorkerInner.PushToLeader({ batch: trimmedBatch })).pipe(
|
|
398
|
-
Effect.withSpan('@livestore/adapter-web:client-session:pushToLeader', {
|
|
399
|
-
attributes: { batchSize: batch.length },
|
|
400
|
-
}),
|
|
401
|
-
// We can ignore the error here because the ClientSessionSyncProcessor will retry after rebasing
|
|
402
|
-
Effect.ignoreLogged,
|
|
403
|
-
)
|
|
404
|
-
}).pipe(Effect.forever, Effect.interruptible, Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
405
|
-
|
|
406
391
|
const devtools: ClientSession['devtools'] = devtoolsEnabled
|
|
407
392
|
? { enabled: true, pullLatch: yield* Effect.makeLatch(true), pushLatch: yield* Effect.makeLatch(true) }
|
|
408
393
|
: { enabled: false }
|
|
@@ -425,11 +410,12 @@ export const makeAdapter =
|
|
|
425
410
|
pull: runInWorkerStream(new WorkerSchema.LeaderWorkerInner.PullStream({ cursor: initialLeaderHead })).pipe(
|
|
426
411
|
Stream.orDie,
|
|
427
412
|
),
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
413
|
+
push: (batch) =>
|
|
414
|
+
runInWorker(new WorkerSchema.LeaderWorkerInner.PushToLeader({ batch })).pipe(
|
|
415
|
+
Effect.withSpan('@livestore/adapter-web:client-session:pushToLeader', {
|
|
416
|
+
attributes: { batchSize: batch.length },
|
|
417
|
+
}),
|
|
418
|
+
),
|
|
433
419
|
},
|
|
434
420
|
|
|
435
421
|
initialState: { leaderHead: initialLeaderHead, migrationsReport },
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Schema, WebChannel } from '@livestore/utils/effect'
|
|
2
|
+
|
|
3
|
+
export class DedicatedWorkerDisconnectBroadcast extends Schema.TaggedStruct('DedicatedWorkerDisconnectBroadcast', {}) {}
|
|
4
|
+
|
|
5
|
+
/** Used across workers for leader election purposes */
|
|
6
|
+
export const makeWorkerDisconnectChannel = (storeId: string) =>
|
|
7
|
+
WebChannel.broadcastChannel({
|
|
8
|
+
channelName: `livestore.worker-disconnect.${storeId}`,
|
|
9
|
+
schema: DedicatedWorkerDisconnectBroadcast,
|
|
10
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BootStatus,
|
|
3
3
|
Devtools,
|
|
4
|
-
|
|
4
|
+
LeaderAheadError,
|
|
5
5
|
MigrationsReport,
|
|
6
6
|
NetworkStatus,
|
|
7
7
|
SyncState,
|
|
@@ -78,7 +78,7 @@ export namespace LeaderWorkerInner {
|
|
|
78
78
|
batch: Schema.Array(MutationEvent.AnyEncoded),
|
|
79
79
|
},
|
|
80
80
|
success: Schema.Void,
|
|
81
|
-
failure: Schema.Union(UnexpectedError,
|
|
81
|
+
failure: Schema.Union(UnexpectedError, LeaderAheadError),
|
|
82
82
|
}) {}
|
|
83
83
|
|
|
84
84
|
export class PullStream extends Schema.TaggedRequest<PullStream>()('PullStream', {
|
|
@@ -48,6 +48,8 @@ if (isDevEnv()) {
|
|
|
48
48
|
globalThis.__debugLiveStoreUtils = {
|
|
49
49
|
opfs: OpfsUtils,
|
|
50
50
|
blobUrl: (buffer: Uint8Array) => URL.createObjectURL(new Blob([buffer], { type: 'application/octet-stream' })),
|
|
51
|
+
runSync: (effect: Effect.Effect<any, any, never>) => Effect.runSync(effect),
|
|
52
|
+
runFork: (effect: Effect.Effect<any, any, never>) => Effect.runFork(effect),
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -64,7 +66,7 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
|
|
|
64
66
|
|
|
65
67
|
return makeWorkerRunnerOuter(options).pipe(
|
|
66
68
|
Layer.provide(BrowserWorkerRunner.layer),
|
|
67
|
-
|
|
69
|
+
WorkerRunner.launch,
|
|
68
70
|
Effect.scoped,
|
|
69
71
|
Effect.tapCauseLogPretty,
|
|
70
72
|
Effect.annotateLogs({ thread: self.name }),
|
|
@@ -91,7 +93,7 @@ const makeWorkerRunnerOuter = (
|
|
|
91
93
|
Effect.gen(function* () {
|
|
92
94
|
yield* makeWorkerRunnerInner(workerOptions).pipe(
|
|
93
95
|
Layer.provide(BrowserWorkerRunner.layerMessagePort(incomingRequestsPort)),
|
|
94
|
-
|
|
96
|
+
WorkerRunner.launch,
|
|
95
97
|
Effect.scoped,
|
|
96
98
|
Effect.withSpan('@livestore/adapter-web:worker:wrapper:InitialMessage:innerFiber'),
|
|
97
99
|
Effect.tapCauseLogPretty,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UnexpectedError } from '@livestore/common'
|
|
2
2
|
import { connectViaWorker } from '@livestore/devtools-web-common/web-channel'
|
|
3
3
|
import * as WebMeshWorker from '@livestore/devtools-web-common/worker'
|
|
4
4
|
import { isDevEnv, isNotUndefined, LS_DEV } from '@livestore/utils'
|
|
@@ -233,7 +233,6 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
233
233
|
|
|
234
234
|
yield* shutdownChannel.listen.pipe(
|
|
235
235
|
Stream.flatten(),
|
|
236
|
-
Stream.filter(Schema.is(IntentionalShutdownCause)),
|
|
237
236
|
Stream.tap(() => reset),
|
|
238
237
|
Stream.runDrain,
|
|
239
238
|
)
|
|
@@ -282,6 +281,7 @@ const makeWorkerRunner = Effect.gen(function* () {
|
|
|
282
281
|
export const makeWorker = () => {
|
|
283
282
|
makeWorkerRunner.pipe(
|
|
284
283
|
Layer.provide(BrowserWorkerRunner.layer),
|
|
284
|
+
// WorkerRunner.launch,
|
|
285
285
|
Layer.launch,
|
|
286
286
|
Effect.scoped,
|
|
287
287
|
Effect.tapCauseLogPretty,
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { MutationEvent } from '@livestore/common/schema';
|
|
2
|
-
/** [(0,1), (0,2), (1,0), (0,1), (0,2), (1,0), (1,1)] -> [(0,1), (0,2), (1,0), (1,1)] */
|
|
3
|
-
export declare const trimPushBatch: (batch: ReadonlyArray<MutationEvent.AnyEncoded>) => readonly MutationEvent.AnyEncoded[];
|
|
4
|
-
//# sourceMappingURL=trim-batch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trim-batch.d.ts","sourceRoot":"","sources":["../../../src/web-worker/client-session/trim-batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG7D,wFAAwF;AACxF,eAAO,MAAM,aAAa,UAAW,aAAa,CAAC,aAAa,CAAC,UAAU,CAAC,wCAU3E,CAAA"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { EventId } from '@livestore/common/schema';
|
|
2
|
-
/** [(0,1), (0,2), (1,0), (0,1), (0,2), (1,0), (1,1)] -> [(0,1), (0,2), (1,0), (1,1)] */
|
|
3
|
-
export const trimPushBatch = (batch) => {
|
|
4
|
-
// Iterate over batch from the end and stop once we encounter an event with a larger id than the previous event
|
|
5
|
-
// Then return the slice of the batch up to and including that event
|
|
6
|
-
for (let i = batch.length - 2; i >= 0; i--) {
|
|
7
|
-
if (EventId.isGreaterThanOrEqual(batch[i].id, batch[i + 1].id)) {
|
|
8
|
-
return batch.slice(i + 1);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return batch;
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=trim-batch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trim-batch.js","sourceRoot":"","sources":["../../../src/web-worker/client-session/trim-batch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAElD,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAA8C,EAAE,EAAE;IAC9E,+GAA+G;IAC/G,oEAAoE;IACpE,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trim-batch.test.d.ts","sourceRoot":"","sources":["../../../src/web-worker/client-session/trim-batch.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { EventId } from '@livestore/common/schema';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { trimPushBatch } from './trim-batch.js';
|
|
4
|
-
describe('trimPushBatch', () => {
|
|
5
|
-
it('should return same batch', () => {
|
|
6
|
-
const batch = [
|
|
7
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
8
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
9
|
-
{ id: EventId.make({ global: 1, client: 0 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
10
|
-
{ id: EventId.make({ global: 1, client: 1 }), parentId: EventId.make({ global: 1, client: 0 }) },
|
|
11
|
-
];
|
|
12
|
-
const trimmed = trimPushBatch(batch);
|
|
13
|
-
expect(trimmed).toEqual(batch);
|
|
14
|
-
});
|
|
15
|
-
it('should trim the batch', () => {
|
|
16
|
-
const batch = [
|
|
17
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
18
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
19
|
-
// should trim above
|
|
20
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
21
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
22
|
-
{ id: EventId.make({ global: 1, client: 0 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
23
|
-
{ id: EventId.make({ global: 1, client: 1 }), parentId: EventId.make({ global: 1, client: 0 }) },
|
|
24
|
-
];
|
|
25
|
-
const trimmed = trimPushBatch(batch);
|
|
26
|
-
expect(trimmed).toEqual(batch.slice(2));
|
|
27
|
-
});
|
|
28
|
-
it('should trim the batch', () => {
|
|
29
|
-
const batch = [
|
|
30
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
31
|
-
// should trim above
|
|
32
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
33
|
-
];
|
|
34
|
-
const trimmed = trimPushBatch(batch);
|
|
35
|
-
expect(trimmed).toEqual(batch.slice(1));
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
//# sourceMappingURL=trim-batch.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trim-batch.test.js","sourceRoot":"","sources":["../../../src/web-worker/client-session/trim-batch.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { MutationEvent } from '@livestore/common/schema'
|
|
2
|
-
import { EventId } from '@livestore/common/schema'
|
|
3
|
-
import { describe, expect, it } from 'vitest'
|
|
4
|
-
|
|
5
|
-
import { trimPushBatch } from './trim-batch.js'
|
|
6
|
-
|
|
7
|
-
describe('trimPushBatch', () => {
|
|
8
|
-
it('should return same batch', () => {
|
|
9
|
-
const batch = [
|
|
10
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
11
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
12
|
-
{ id: EventId.make({ global: 1, client: 0 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
13
|
-
{ id: EventId.make({ global: 1, client: 1 }), parentId: EventId.make({ global: 1, client: 0 }) },
|
|
14
|
-
] as MutationEvent.AnyEncoded[]
|
|
15
|
-
|
|
16
|
-
const trimmed = trimPushBatch(batch)
|
|
17
|
-
|
|
18
|
-
expect(trimmed).toEqual(batch)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should trim the batch', () => {
|
|
22
|
-
const batch = [
|
|
23
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
24
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
25
|
-
// should trim above
|
|
26
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
27
|
-
{ id: EventId.make({ global: 0, client: 2 }), parentId: EventId.make({ global: 0, client: 1 }) },
|
|
28
|
-
{ id: EventId.make({ global: 1, client: 0 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
29
|
-
{ id: EventId.make({ global: 1, client: 1 }), parentId: EventId.make({ global: 1, client: 0 }) },
|
|
30
|
-
] as MutationEvent.AnyEncoded[]
|
|
31
|
-
|
|
32
|
-
const trimmed = trimPushBatch(batch)
|
|
33
|
-
|
|
34
|
-
expect(trimmed).toEqual(batch.slice(2))
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('should trim the batch', () => {
|
|
38
|
-
const batch = [
|
|
39
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
40
|
-
// should trim above
|
|
41
|
-
{ id: EventId.make({ global: 0, client: 1 }), parentId: EventId.make({ global: 0, client: 0 }) },
|
|
42
|
-
] as MutationEvent.AnyEncoded[]
|
|
43
|
-
|
|
44
|
-
const trimmed = trimPushBatch(batch)
|
|
45
|
-
|
|
46
|
-
expect(trimmed).toEqual(batch.slice(1))
|
|
47
|
-
})
|
|
48
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { MutationEvent } from '@livestore/common/schema'
|
|
2
|
-
import { EventId } from '@livestore/common/schema'
|
|
3
|
-
|
|
4
|
-
/** [(0,1), (0,2), (1,0), (0,1), (0,2), (1,0), (1,1)] -> [(0,1), (0,2), (1,0), (1,1)] */
|
|
5
|
-
export const trimPushBatch = (batch: ReadonlyArray<MutationEvent.AnyEncoded>) => {
|
|
6
|
-
// Iterate over batch from the end and stop once we encounter an event with a larger id than the previous event
|
|
7
|
-
// Then return the slice of the batch up to and including that event
|
|
8
|
-
for (let i = batch.length - 2; i >= 0; i--) {
|
|
9
|
-
if (EventId.isGreaterThanOrEqual(batch[i]!.id, batch[i + 1]!.id)) {
|
|
10
|
-
return batch.slice(i + 1)
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return batch
|
|
15
|
-
}
|