@evolu/common 8.0.0-next.4 → 8.0.0
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/src/Array.d.ts +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
|
@@ -8,32 +8,43 @@ import {
|
|
|
8
8
|
emptyArray,
|
|
9
9
|
firstInArray,
|
|
10
10
|
isNonEmptyArray,
|
|
11
|
-
shiftFromArray,
|
|
12
11
|
type NonEmptyReadonlyArray,
|
|
13
|
-
} from "../Array.
|
|
14
|
-
import { assert
|
|
15
|
-
import type { Brand } from "../Brand.
|
|
16
|
-
import { createCallbacks } from "../Callbacks.
|
|
17
|
-
import type { ConsoleEntry, ConsoleLevel } from "../Console.
|
|
18
|
-
import type { EncryptionKey } from "../Crypto.
|
|
19
|
-
import {
|
|
20
|
-
import { acquireLeaderLock, type LockManagerDep } from "../LockManager.
|
|
21
|
-
import {
|
|
22
|
-
|
|
12
|
+
} from "../Array.ts";
|
|
13
|
+
import { assert } from "../Assert.ts";
|
|
14
|
+
import type { Brand } from "../Brand.ts";
|
|
15
|
+
import { createCallbacks } from "../Callbacks.ts";
|
|
16
|
+
import type { ConsoleEntry, ConsoleLevel } from "../Console.ts";
|
|
17
|
+
import type { EncryptionKey } from "../Crypto.ts";
|
|
18
|
+
import { disposable } from "../Function.ts";
|
|
19
|
+
import { acquireLeaderLock, type LockManagerDep } from "../LockManager.ts";
|
|
20
|
+
import {
|
|
21
|
+
createLookupMap,
|
|
22
|
+
structuralLookup,
|
|
23
|
+
type LookupMap,
|
|
24
|
+
type StructuralLookupKey,
|
|
25
|
+
} from "../Lookup.ts";
|
|
26
|
+
import { createRefCountByKey, type RefCountByKey } from "../RefCount.ts";
|
|
23
27
|
import {
|
|
24
28
|
createSharedResourceByKey,
|
|
25
29
|
createSharedResourceByKeyWithClaims,
|
|
26
30
|
type BorrowedResource,
|
|
31
|
+
type ClaimLease,
|
|
27
32
|
type SharedResourceByKeyWithClaims,
|
|
28
|
-
} from "../Resource.
|
|
29
|
-
import { ok, type Result } from "../Result.
|
|
30
|
-
import type { NonEmptyReadonlySet } from "../Set.
|
|
31
|
-
import type { SqliteSchema } from "../Sqlite.
|
|
32
|
-
import { createStore, type Store } from "../Store.
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
} from "../Resource.ts";
|
|
34
|
+
import { ok, type Result } from "../Result.ts";
|
|
35
|
+
import type { NonEmptyReadonlySet } from "../Set.ts";
|
|
36
|
+
import type { SqliteSchema } from "../Sqlite.ts";
|
|
37
|
+
import { createStore, type Store } from "../Store.ts";
|
|
38
|
+
import {
|
|
39
|
+
AbortError,
|
|
40
|
+
createMutex,
|
|
41
|
+
unabortable,
|
|
42
|
+
type Mutex,
|
|
43
|
+
type Task,
|
|
44
|
+
} from "../Task.ts";
|
|
45
|
+
import type { ExtractTyped, Id, Name, Typed } from "../Type.ts";
|
|
46
|
+
import type { Callback } from "../Types.ts";
|
|
47
|
+
import type { CreateWebSocketDep, WebSocket } from "../WebSocket.ts";
|
|
37
48
|
import type {
|
|
38
49
|
SharedWorker as CommonSharedWorker,
|
|
39
50
|
CreateBroadcastChannelDep,
|
|
@@ -42,10 +53,10 @@ import type {
|
|
|
42
53
|
NativeMessagePort,
|
|
43
54
|
SharedWorkerSelf,
|
|
44
55
|
WorkerDeps,
|
|
45
|
-
} from "../Worker.
|
|
46
|
-
import type { DbWorkerInit } from "./Db.
|
|
47
|
-
import type { EvoluError } from "./Error.
|
|
48
|
-
import type { Owner, OwnerId, OwnerTransport, SyncOwner } from "./Owner.
|
|
56
|
+
} from "../Worker.ts";
|
|
57
|
+
import type { DbWorkerInit } from "./Db.ts";
|
|
58
|
+
import type { EvoluError } from "./Error.ts";
|
|
59
|
+
import type { Owner, OwnerId, OwnerTransport, SyncOwner } from "./Owner.ts";
|
|
49
60
|
import {
|
|
50
61
|
createProtocolMessageForUnsubscribe,
|
|
51
62
|
createProtocolMessageFromCrdtMessages,
|
|
@@ -53,16 +64,16 @@ import {
|
|
|
53
64
|
type ApplyProtocolMessageAsClientResult,
|
|
54
65
|
type ProtocolError,
|
|
55
66
|
type ProtocolMessage,
|
|
56
|
-
} from "./Protocol.
|
|
67
|
+
} from "./Protocol.ts";
|
|
57
68
|
import {
|
|
58
69
|
makePatches,
|
|
59
70
|
type Patch,
|
|
60
71
|
type Query,
|
|
61
72
|
type Row,
|
|
62
73
|
type RowsByQueryMap,
|
|
63
|
-
} from "./Query.
|
|
64
|
-
import type { MutationChange } from "./Schema.
|
|
65
|
-
import type { CrdtMessage } from "./Storage.
|
|
74
|
+
} from "./Query.ts";
|
|
75
|
+
import type { MutationChange } from "./Schema.ts";
|
|
76
|
+
import type { CrdtMessage } from "./Storage.ts";
|
|
66
77
|
|
|
67
78
|
export type SharedWorker = CommonSharedWorker<
|
|
68
79
|
SharedWorkerInput,
|
|
@@ -151,7 +162,9 @@ export type DbWorkerRequest =
|
|
|
151
162
|
| {
|
|
152
163
|
readonly type: "ForEvolu";
|
|
153
164
|
readonly id: EvoluInstanceId;
|
|
154
|
-
readonly message:
|
|
165
|
+
readonly message: {
|
|
166
|
+
readonly [Message in EvoluInput as Message["type"]]: Message;
|
|
167
|
+
}["Mutate" | "Query" | "Export"];
|
|
155
168
|
}
|
|
156
169
|
| {
|
|
157
170
|
readonly type: "ForSharedWorker";
|
|
@@ -229,7 +242,7 @@ export type SharedWorkerDeps = WorkerDeps &
|
|
|
229
242
|
|
|
230
243
|
interface EvoluTenant extends AsyncDisposable {
|
|
231
244
|
readonly addInstance: (
|
|
232
|
-
message:
|
|
245
|
+
message: ExtractTyped<SharedWorkerInput, "CreateEvolu">,
|
|
233
246
|
onDisposed: () => void,
|
|
234
247
|
) => void;
|
|
235
248
|
|
|
@@ -260,8 +273,7 @@ interface TransportsDep {
|
|
|
260
273
|
readonly transports: SharedResourceByKeyWithClaims<
|
|
261
274
|
OwnerTransport,
|
|
262
275
|
OwnerId,
|
|
263
|
-
WebSocket
|
|
264
|
-
SharedWorkerDeps
|
|
276
|
+
WebSocket
|
|
265
277
|
>;
|
|
266
278
|
}
|
|
267
279
|
|
|
@@ -269,6 +281,7 @@ export type EvoluInstanceId = Id & Brand<"EvoluInstance">;
|
|
|
269
281
|
|
|
270
282
|
export type SyncState = 123;
|
|
271
283
|
|
|
284
|
+
/** Initializes the platform-agnostic Evolu SharedWorker. */
|
|
272
285
|
export const initSharedWorker =
|
|
273
286
|
(
|
|
274
287
|
self: SharedWorkerSelf<SharedWorkerInput, SharedWorkerOutput>,
|
|
@@ -308,13 +321,10 @@ export const initSharedWorker =
|
|
|
308
321
|
|
|
309
322
|
case "CreateEvolu": {
|
|
310
323
|
void sharedWorkerRun(async (run) => {
|
|
311
|
-
const
|
|
312
|
-
tenantsByName.acquire(message),
|
|
313
|
-
);
|
|
314
|
-
tenant.addInstance(
|
|
315
|
-
message,
|
|
316
|
-
() => void sharedWorkerRun(tenantsByName.release(message)),
|
|
324
|
+
const tenantLease = await run.ok(
|
|
325
|
+
unabortable(tenantsByName.acquire(message)),
|
|
317
326
|
);
|
|
327
|
+
tenantLease.resource.addInstance(message, tenantLease.release);
|
|
318
328
|
return ok();
|
|
319
329
|
});
|
|
320
330
|
break;
|
|
@@ -333,12 +343,13 @@ export const initSharedWorker =
|
|
|
333
343
|
}),
|
|
334
344
|
);
|
|
335
345
|
|
|
346
|
+
const currentTenantsByName = new Map<Name, BorrowedResource<EvoluTenant>>();
|
|
336
347
|
const transports = disposer.use(
|
|
337
|
-
await run.
|
|
348
|
+
await run.ok(
|
|
338
349
|
createSharedResourceByKeyWithClaims<
|
|
339
|
-
WebSocket,
|
|
340
350
|
OwnerTransport,
|
|
341
351
|
OwnerId,
|
|
352
|
+
WebSocket,
|
|
342
353
|
SharedWorkerDeps,
|
|
343
354
|
StructuralLookupKey
|
|
344
355
|
>(
|
|
@@ -405,17 +416,23 @@ export const initSharedWorker =
|
|
|
405
416
|
),
|
|
406
417
|
);
|
|
407
418
|
|
|
408
|
-
const sharedWorkerRun = run.create(
|
|
419
|
+
const sharedWorkerRun = run.create({
|
|
420
|
+
...deps,
|
|
409
421
|
postConsoleEntryOrError,
|
|
410
422
|
tabLeaderPortStore,
|
|
411
423
|
transports,
|
|
412
424
|
});
|
|
413
425
|
|
|
414
426
|
const tenantsByName = disposer.use(
|
|
415
|
-
await sharedWorkerRun.
|
|
416
|
-
createSharedResourceByKey(
|
|
417
|
-
|
|
418
|
-
|
|
427
|
+
await sharedWorkerRun.ok(
|
|
428
|
+
createSharedResourceByKey(
|
|
429
|
+
(message: ExtractTyped<SharedWorkerInput, "CreateEvolu">) =>
|
|
430
|
+
createEvoluTenant(message, currentTenantsByName),
|
|
431
|
+
{
|
|
432
|
+
idleDisposeAfter: "3s",
|
|
433
|
+
lookup: (message) => message.name,
|
|
434
|
+
},
|
|
435
|
+
),
|
|
419
436
|
),
|
|
420
437
|
);
|
|
421
438
|
|
|
@@ -424,26 +441,23 @@ export const initSharedWorker =
|
|
|
424
441
|
const forEachTenant = (
|
|
425
442
|
callback: Callback<BorrowedResource<EvoluTenant>>,
|
|
426
443
|
): void => {
|
|
427
|
-
for (const tenant of
|
|
428
|
-
callback(tenant);
|
|
429
|
-
}
|
|
444
|
+
for (const tenant of currentTenantsByName.values()) callback(tenant);
|
|
430
445
|
};
|
|
431
446
|
|
|
432
447
|
return ok(disposer.move());
|
|
433
448
|
};
|
|
434
449
|
|
|
435
450
|
const createEvoluTenant =
|
|
436
|
-
(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
> =>
|
|
451
|
+
(
|
|
452
|
+
{
|
|
453
|
+
name,
|
|
454
|
+
consoleLevel,
|
|
455
|
+
sqliteSchema,
|
|
456
|
+
encryptionKey,
|
|
457
|
+
memoryOnly,
|
|
458
|
+
}: ExtractTyped<SharedWorkerInput, "CreateEvolu">,
|
|
459
|
+
currentTenantsByName: Map<Name, BorrowedResource<EvoluTenant>>,
|
|
460
|
+
): Task<EvoluTenant, never, EvoluTenantDeps> =>
|
|
447
461
|
async (run) => {
|
|
448
462
|
await using disposer = new AsyncDisposableStack();
|
|
449
463
|
const tenantRun = disposer.use(run.create());
|
|
@@ -453,6 +467,7 @@ const createEvoluTenant =
|
|
|
453
467
|
|
|
454
468
|
interface EvoluInstance extends AsyncDisposable {
|
|
455
469
|
readonly id: EvoluInstanceId;
|
|
470
|
+
readonly claimLeasesBySyncOwner: LookupMap<SyncOwner, Array<ClaimLease>>;
|
|
456
471
|
readonly onDisposed: () => void;
|
|
457
472
|
readonly port: MessagePort<EvoluOutput, EvoluInput>;
|
|
458
473
|
readonly useOwnerMutex: Mutex;
|
|
@@ -505,8 +520,6 @@ const createEvoluTenant =
|
|
|
505
520
|
callbacks.execute(message.callbackId, message);
|
|
506
521
|
break;
|
|
507
522
|
}
|
|
508
|
-
default:
|
|
509
|
-
exhaustiveCheck(message);
|
|
510
523
|
}
|
|
511
524
|
};
|
|
512
525
|
|
|
@@ -526,7 +539,7 @@ const createEvoluTenant =
|
|
|
526
539
|
|
|
527
540
|
const queue: Array<DbWorkerRequest> = [];
|
|
528
541
|
const callbacks = disposer.use(
|
|
529
|
-
createCallbacks<
|
|
542
|
+
createCallbacks<ExtractTyped<DbWorkerOutput, "OnQueuedResponse">>(
|
|
530
543
|
run.deps,
|
|
531
544
|
),
|
|
532
545
|
);
|
|
@@ -549,13 +562,10 @@ const createEvoluTenant =
|
|
|
549
562
|
case "ForSharedWorker":
|
|
550
563
|
handleResponseForSharedWorker(response);
|
|
551
564
|
break;
|
|
552
|
-
|
|
553
|
-
default:
|
|
554
|
-
exhaustiveCheck(response);
|
|
555
565
|
}
|
|
556
566
|
|
|
557
567
|
// Complete the current queue item and continue with the next one.
|
|
558
|
-
|
|
568
|
+
queue.shift();
|
|
559
569
|
queueRequestInFlight = false;
|
|
560
570
|
runQueue();
|
|
561
571
|
});
|
|
@@ -569,17 +579,21 @@ const createEvoluTenant =
|
|
|
569
579
|
dbWorkerPort = null;
|
|
570
580
|
queueRequestInFlight = false;
|
|
571
581
|
|
|
572
|
-
|
|
582
|
+
// The DbWorker holds this tenant leader lock while it is alive. Tenant
|
|
583
|
+
// disposal sends Dispose, then acquires the same lock to wait until the
|
|
584
|
+
// DbWorker releases it: either because Dispose was delivered or because
|
|
585
|
+
// the hosting tab closed. The wait is unabortable because tenant disposal
|
|
586
|
+
// must finish even after tenantRun receives an abort request.
|
|
587
|
+
await using _ = await tenantRun.ok(acquireLeaderLock(name));
|
|
573
588
|
});
|
|
574
589
|
|
|
575
590
|
disposer.defer(deps.tabLeaderPortStore.subscribe(initDbWorker));
|
|
576
591
|
|
|
577
592
|
initDbWorker();
|
|
578
593
|
await dbWorkerInited.promise;
|
|
579
|
-
const disposables = disposer.move();
|
|
580
594
|
|
|
581
595
|
const handleResponseForEvolu = (
|
|
582
|
-
response:
|
|
596
|
+
response: ExtractTyped<DbWorkerQueuedResponse, "ForEvolu">,
|
|
583
597
|
first: DbWorkerRequest,
|
|
584
598
|
): void => {
|
|
585
599
|
const instance = instancesById.get(response.id);
|
|
@@ -652,14 +666,11 @@ const createEvoluTenant =
|
|
|
652
666
|
[response.message.file.buffer],
|
|
653
667
|
);
|
|
654
668
|
break;
|
|
655
|
-
|
|
656
|
-
default:
|
|
657
|
-
exhaustiveCheck(response.message);
|
|
658
669
|
}
|
|
659
670
|
};
|
|
660
671
|
|
|
661
672
|
const handleResponseForSharedWorker = (
|
|
662
|
-
response:
|
|
673
|
+
response: ExtractTyped<DbWorkerQueuedResponse, "ForSharedWorker">,
|
|
663
674
|
): void => {
|
|
664
675
|
switch (response.message.type) {
|
|
665
676
|
case "CreateSyncMessages":
|
|
@@ -698,15 +709,9 @@ const createEvoluTenant =
|
|
|
698
709
|
case "Broadcast":
|
|
699
710
|
case "NoResponse":
|
|
700
711
|
break;
|
|
701
|
-
|
|
702
|
-
default:
|
|
703
|
-
exhaustiveCheck(response.message.result.value);
|
|
704
712
|
}
|
|
705
713
|
}
|
|
706
714
|
break;
|
|
707
|
-
|
|
708
|
-
default:
|
|
709
|
-
exhaustiveCheck(response.message);
|
|
710
715
|
}
|
|
711
716
|
};
|
|
712
717
|
|
|
@@ -714,20 +719,20 @@ const createEvoluTenant =
|
|
|
714
719
|
protocolMessagesByOwnerId: ReadonlyMap<OwnerId, ProtocolMessage>,
|
|
715
720
|
): void => {
|
|
716
721
|
for (const [ownerId, protocolMessage] of protocolMessagesByOwnerId) {
|
|
717
|
-
|
|
722
|
+
deps.transports.forEachResourceForClaim(
|
|
718
723
|
ownerId,
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
if (!webSocket?.isOpen()) continue;
|
|
724
|
+
(webSocket, transport) => {
|
|
725
|
+
if (!webSocket.isOpen()) return;
|
|
722
726
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
727
|
+
console.debug("sendProtocolMessage", {
|
|
728
|
+
ownerId,
|
|
729
|
+
url: transport.url,
|
|
730
|
+
byteLength: protocolMessage.byteLength,
|
|
731
|
+
});
|
|
728
732
|
|
|
729
|
-
|
|
730
|
-
|
|
733
|
+
webSocket.send(protocolMessage);
|
|
734
|
+
},
|
|
735
|
+
);
|
|
731
736
|
}
|
|
732
737
|
};
|
|
733
738
|
|
|
@@ -753,159 +758,187 @@ const createEvoluTenant =
|
|
|
753
758
|
async (run) => {
|
|
754
759
|
if (action === "add") {
|
|
755
760
|
instance.usedSyncOwners.increment(syncOwner);
|
|
756
|
-
|
|
757
|
-
|
|
761
|
+
let succeeded = false;
|
|
762
|
+
using compensation = new DisposableStack();
|
|
763
|
+
compensation.defer(() => {
|
|
764
|
+
if (!succeeded) instance.usedSyncOwners.decrement(syncOwner);
|
|
765
|
+
});
|
|
766
|
+
const claimLease = await run.ok(
|
|
767
|
+
deps.transports.claim(syncOwner.owner.id, syncOwner.transports),
|
|
758
768
|
);
|
|
769
|
+
instance.claimLeasesBySyncOwner
|
|
770
|
+
.getOrInsertComputed(syncOwner, () => [])
|
|
771
|
+
.push(claimLease);
|
|
772
|
+
succeeded = true;
|
|
759
773
|
} else {
|
|
760
774
|
instance.usedSyncOwners.decrement(syncOwner);
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
)
|
|
775
|
+
const claimLeases = instance.claimLeasesBySyncOwner.get(syncOwner);
|
|
776
|
+
assert(claimLeases, "Expected a ClaimLease for the used owner.");
|
|
777
|
+
const claimLease = claimLeases.pop();
|
|
778
|
+
assert(claimLease, "Expected a ClaimLease for the used owner.");
|
|
779
|
+
claimLease.release();
|
|
780
|
+
if (claimLeases.length === 0) {
|
|
781
|
+
instance.claimLeasesBySyncOwner.delete(syncOwner);
|
|
782
|
+
}
|
|
767
783
|
}
|
|
784
|
+
return ok();
|
|
768
785
|
};
|
|
769
786
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
const disposer = new AsyncDisposableStack();
|
|
791
|
-
|
|
792
|
-
disposer.defer(instance.onDisposed);
|
|
793
|
-
disposer.use(instance.usedSyncOwners);
|
|
794
|
-
disposer.use(instance.useOwnerMutex);
|
|
795
|
-
|
|
796
|
-
disposer.defer(async () => {
|
|
797
|
-
await tenantRun(
|
|
798
|
-
instance.useOwnerMutex.withLock(async (run) => {
|
|
799
|
-
for (const syncOwner of instance.usedSyncOwners.keys()) {
|
|
800
|
-
while (instance.usedSyncOwners.has(syncOwner)) {
|
|
801
|
-
await run(toggleSyncOwner(instance, syncOwner, "remove"));
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
return ok();
|
|
787
|
+
disposer.defer(() => {
|
|
788
|
+
currentTenantsByName.delete(name);
|
|
789
|
+
});
|
|
790
|
+
const tenant = disposable<EvoluTenant>(
|
|
791
|
+
{
|
|
792
|
+
addInstance: (message, onDisposed) => {
|
|
793
|
+
const disposer = new AsyncDisposableStack();
|
|
794
|
+
const instance: EvoluInstance = {
|
|
795
|
+
id: message.id,
|
|
796
|
+
claimLeasesBySyncOwner: createLookupMap({
|
|
797
|
+
lookup: (syncOwner: SyncOwner) =>
|
|
798
|
+
structuralLookup<{
|
|
799
|
+
readonly ownerId: OwnerId;
|
|
800
|
+
readonly transports: ReadonlyArray<StructuralLookupKey>;
|
|
801
|
+
}>({
|
|
802
|
+
ownerId: syncOwner.owner.id,
|
|
803
|
+
transports: syncOwner.transports
|
|
804
|
+
.map(structuralLookup)
|
|
805
|
+
.toSorted(),
|
|
806
|
+
}),
|
|
805
807
|
}),
|
|
806
|
-
|
|
807
|
-
|
|
808
|
+
port: deps.createMessagePort<EvoluOutput, EvoluInput>(
|
|
809
|
+
message.evoluPort,
|
|
810
|
+
),
|
|
811
|
+
onDisposed,
|
|
812
|
+
rowsByQuery: new Map<Query, ReadonlyArray<Row>>(),
|
|
813
|
+
useOwnerMutex: createMutex(),
|
|
814
|
+
usedSyncOwners: createRefCountByKey<SyncOwner, OwnerId>({
|
|
815
|
+
lookup: (syncOwner) => syncOwner.owner.id,
|
|
816
|
+
}),
|
|
817
|
+
[Symbol.asyncDispose]: () => disposer.disposeAsync(),
|
|
818
|
+
};
|
|
808
819
|
|
|
809
|
-
|
|
810
|
-
instancesById.delete(instance.id);
|
|
811
|
-
console.info("evoluDispose", { name, id: instance.id });
|
|
812
|
-
});
|
|
813
|
-
disposer.use(instance.port);
|
|
820
|
+
instancesById.set(instance.id, instance);
|
|
814
821
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const lock = result.value;
|
|
822
|
+
disposer.defer(instance.onDisposed);
|
|
823
|
+
disposer.use(instance.usedSyncOwners);
|
|
818
824
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
825
|
+
disposer.defer(async () => {
|
|
826
|
+
await tenantRun(
|
|
827
|
+
instance.useOwnerMutex.withLock(async (run) => {
|
|
828
|
+
for (const syncOwner of instance.usedSyncOwners.keys()) {
|
|
829
|
+
while (instance.usedSyncOwners.has(syncOwner)) {
|
|
830
|
+
await run(toggleSyncOwner(instance, syncOwner, "remove"));
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return ok();
|
|
834
|
+
}),
|
|
835
|
+
);
|
|
836
|
+
});
|
|
822
837
|
|
|
823
|
-
disposer.
|
|
824
|
-
|
|
825
|
-
|
|
838
|
+
disposer.defer(() => {
|
|
839
|
+
instancesById.delete(instance.id);
|
|
840
|
+
console.info("evoluDispose", { name, id: instance.id });
|
|
841
|
+
});
|
|
842
|
+
disposer.use(instance.port);
|
|
843
|
+
disposer.defer(() => {
|
|
844
|
+
instance.port.onMessage = null;
|
|
845
|
+
});
|
|
826
846
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
847
|
+
// The main-thread Evolu instance holds this per-instance leader lock
|
|
848
|
+
// while it is alive. Acquiring the same lock here means the main
|
|
849
|
+
// thread instance was disposed or its tab closed, so the tenant-side
|
|
850
|
+
// instance must dispose itself.
|
|
851
|
+
void tenantRun
|
|
852
|
+
.abortable(acquireLeaderLock(message.id))
|
|
853
|
+
.then((lock) => {
|
|
854
|
+
if (!lock.ok) return;
|
|
855
|
+
|
|
856
|
+
disposer.use(lock.value);
|
|
857
|
+
return instance[Symbol.asyncDispose]();
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
instance.port.onMessage = (message) => {
|
|
861
|
+
switch (message.type) {
|
|
862
|
+
case "Query":
|
|
863
|
+
case "Export": {
|
|
864
|
+
queue.push({ type: "ForEvolu", id: instance.id, message });
|
|
865
|
+
runQueue();
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
case "Mutate": {
|
|
869
|
+
// TODO: Delegate do vsech evolu instances, co to pouzivaji
|
|
870
|
+
queue.push({ type: "ForEvolu", id: instance.id, message });
|
|
871
|
+
runQueue();
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
case "UseOwner": {
|
|
875
|
+
void tenantRun(
|
|
876
|
+
instance.useOwnerMutex.withLock(async (run) => {
|
|
877
|
+
for (const { owner, action } of message.actions) {
|
|
878
|
+
console.debug("useOwner", {
|
|
879
|
+
id: instance.id,
|
|
880
|
+
action,
|
|
881
|
+
ownerId: owner.owner.id,
|
|
882
|
+
transportUrls: owner.transports.map(({ url }) => url),
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
await run(toggleSyncOwner(instance, owner, action));
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
return ok();
|
|
889
|
+
}),
|
|
890
|
+
);
|
|
891
|
+
break;
|
|
892
|
+
}
|
|
840
893
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
instance.useOwnerMutex.withLock(async (run) => {
|
|
844
|
-
for (const { owner, action } of message.actions) {
|
|
845
|
-
console.debug("useOwner", {
|
|
846
|
-
id: instance.id,
|
|
847
|
-
action,
|
|
848
|
-
ownerId: owner.owner.id,
|
|
849
|
-
transportUrls: owner.transports.map(({ url }) => url),
|
|
850
|
-
});
|
|
851
|
-
|
|
852
|
-
await run(toggleSyncOwner(instance, owner, action));
|
|
853
|
-
}
|
|
894
|
+
};
|
|
895
|
+
},
|
|
854
896
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
);
|
|
858
|
-
break;
|
|
859
|
-
}
|
|
860
|
-
default:
|
|
861
|
-
exhaustiveCheck(message);
|
|
862
|
-
}
|
|
863
|
-
};
|
|
864
|
-
},
|
|
897
|
+
requestCreateSyncMessages: (ownerIds): void => {
|
|
898
|
+
const ownersToSync = [...getUsedOwnersById(ownerIds).values()];
|
|
865
899
|
|
|
866
|
-
|
|
867
|
-
const ownersToSync = [...getUsedOwnersById(ownerIds).values()];
|
|
900
|
+
if (!isNonEmptyArray(ownersToSync)) return;
|
|
868
901
|
|
|
869
|
-
|
|
902
|
+
console.debug("requestCreateSyncMessages", {
|
|
903
|
+
ownerIds: ownersToSync.map(({ id }) => id),
|
|
904
|
+
});
|
|
870
905
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
906
|
+
queue.push({
|
|
907
|
+
type: "ForSharedWorker",
|
|
908
|
+
message: {
|
|
909
|
+
type: "CreateSyncMessages",
|
|
910
|
+
owners: ownersToSync,
|
|
911
|
+
},
|
|
912
|
+
});
|
|
874
913
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
message: {
|
|
878
|
-
type: "CreateSyncMessages",
|
|
879
|
-
owners: ownersToSync,
|
|
880
|
-
},
|
|
881
|
-
});
|
|
914
|
+
runQueue();
|
|
915
|
+
},
|
|
882
916
|
|
|
883
|
-
|
|
884
|
-
|
|
917
|
+
requestApplySyncMessage: (ownerId, inputMessage): void => {
|
|
918
|
+
const owner = getUsedOwnersById(new Set([ownerId])).get(ownerId);
|
|
919
|
+
if (!owner) return;
|
|
885
920
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
921
|
+
console.debug("requestApplySyncMessage", {
|
|
922
|
+
ownerId,
|
|
923
|
+
byteLength: inputMessage.byteLength,
|
|
924
|
+
});
|
|
889
925
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
type: "ApplySyncMessage",
|
|
899
|
-
owner,
|
|
900
|
-
inputMessage,
|
|
901
|
-
},
|
|
902
|
-
});
|
|
926
|
+
queue.push({
|
|
927
|
+
type: "ForSharedWorker",
|
|
928
|
+
message: {
|
|
929
|
+
type: "ApplySyncMessage",
|
|
930
|
+
owner,
|
|
931
|
+
inputMessage,
|
|
932
|
+
},
|
|
933
|
+
});
|
|
903
934
|
|
|
904
|
-
|
|
935
|
+
runQueue();
|
|
936
|
+
},
|
|
905
937
|
},
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
938
|
+
disposer,
|
|
939
|
+
);
|
|
940
|
+
currentTenantsByName.set(name, tenant);
|
|
941
|
+
return ok(tenant);
|
|
909
942
|
};
|
|
910
943
|
|
|
911
944
|
// | (Typed<"reset"> & {
|
|
@@ -931,10 +964,17 @@ const createEvoluTenant =
|
|
|
931
964
|
// readonly reload: boolean;
|
|
932
965
|
// })
|
|
933
966
|
|
|
934
|
-
// TODO:
|
|
935
|
-
// -
|
|
936
|
-
// -
|
|
967
|
+
// TODO: SharedWorker follow-ups.
|
|
968
|
+
// - Complete the queue head when a DbWorker mutation returns an error.
|
|
969
|
+
// - Make retried DbWorker requests deterministic by materializing clocks and
|
|
970
|
+
// timestamps in the SharedWorker before enqueueing them.
|
|
971
|
+
// - Replace the callback registry and queueRequestInFlight flag with one
|
|
972
|
+
// explicit in-flight request state.
|
|
973
|
+
// - Detect DbWorker and port liveness so a worker-only crash resumes the queue.
|
|
974
|
+
// - Consolidate usedSyncOwners and claimLeasesBySyncOwner into one owner-use
|
|
975
|
+
// state abstraction without changing repeated-use semantics.
|
|
976
|
+
// - Split worker protocol types and the EvoluTenant implementation into focused
|
|
977
|
+
// modules.
|
|
978
|
+
// - Remove the obsolete commented protocol block above.
|
|
979
|
+
// - Replace the SyncState placeholder with actual sync monitoring state.
|
|
937
980
|
// - Propagate invalid protocol messages to sync state.
|
|
938
|
-
// - Make DbWorker logically stateless by making all requests idempotent.
|
|
939
|
-
// - Investigate WebKit bug 301520 relevance to DbWorker disposal. (again)
|
|
940
|
-
// https://bugs.webkit.org/show_bug.cgi?id=301520
|