@absolutejs/sync 1.8.1 → 1.9.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/engine/devtools.d.ts +27 -0
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.js +166 -6
- package/dist/engine/index.js.map +7 -6
- package/dist/engine/pack.d.ts +138 -0
- package/dist/engine/schedule.d.ts +14 -0
- package/dist/engine/syncEngine.d.ts +13 -0
- package/dist/index.js +164 -6
- package/dist/index.js.map +6 -5
- package/package.json +1 -1
|
@@ -35,6 +35,18 @@ export type EngineInspection = {
|
|
|
35
35
|
table: string;
|
|
36
36
|
op: RowOp;
|
|
37
37
|
}[];
|
|
38
|
+
/**
|
|
39
|
+
* Registered sync packs (see {@link SyncEngine.registerPack}). Each
|
|
40
|
+
* entry reports the pack's name, version, the tables it owns, and the
|
|
41
|
+
* tables it reads but does not own. Surfaced for devtools and for
|
|
42
|
+
* conflict diagnostics.
|
|
43
|
+
*/
|
|
44
|
+
packs: {
|
|
45
|
+
name: string;
|
|
46
|
+
version: string;
|
|
47
|
+
ownsTables: string[];
|
|
48
|
+
readsTables: string[];
|
|
49
|
+
}[];
|
|
38
50
|
};
|
|
39
51
|
/**
|
|
40
52
|
* A live engine event (see {@link SyncEngine.onActivity}): a committed change or
|
|
@@ -63,4 +75,19 @@ export type EngineActivity = {
|
|
|
63
75
|
delayMs: number;
|
|
64
76
|
errorName: string;
|
|
65
77
|
errorMessage: string;
|
|
78
|
+
} | {
|
|
79
|
+
type: 'schedule';
|
|
80
|
+
at: number;
|
|
81
|
+
name: string;
|
|
82
|
+
status: 'ok' | 'error';
|
|
83
|
+
} | {
|
|
84
|
+
/** Emitted between attempts of a retried schedule. Mirrors
|
|
85
|
+
* {@link mutationRetry}. */
|
|
86
|
+
type: 'scheduleRetry';
|
|
87
|
+
at: number;
|
|
88
|
+
name: string;
|
|
89
|
+
attempt: number;
|
|
90
|
+
delayMs: number;
|
|
91
|
+
errorName: string;
|
|
92
|
+
errorMessage: string;
|
|
66
93
|
};
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export { createVectorIndex } from './vectorIndex';
|
|
|
40
40
|
export type { VectorIndexOptions, VectorMetric } from './vectorIndex';
|
|
41
41
|
export { defineSchedule } from './schedule';
|
|
42
42
|
export type { ScheduleContext, ScheduleDefinition } from './schedule';
|
|
43
|
+
export { defineSyncPack, PackMissingDependencyError, PackTableConflictError } from './pack';
|
|
44
|
+
export type { CrdtFieldsMap, RegisteredPack, SyncPack } from './pack';
|
|
43
45
|
export { defineMutation } from './mutation';
|
|
44
46
|
export type { MutationActions, MutationDefinition, MutationHandler, TableWriter, TransactionRunner } from './mutation';
|
|
45
47
|
export type { BridgeFetchConfig, BridgeFetchEndpoint, BridgeFetchResponse, HandlerMetricsHook, HandlerMetricsRecord, SandboxConfig } from './sandbox';
|
package/dist/engine/index.js
CHANGED
|
@@ -1056,6 +1056,31 @@ var createVectorIndex = (options) => {
|
|
|
1056
1056
|
};
|
|
1057
1057
|
// src/engine/schedule.ts
|
|
1058
1058
|
var defineSchedule = (definition) => definition;
|
|
1059
|
+
// src/engine/pack.ts
|
|
1060
|
+
class PackTableConflictError extends Error {
|
|
1061
|
+
table;
|
|
1062
|
+
existingPack;
|
|
1063
|
+
newPack;
|
|
1064
|
+
constructor(table, existingPack, newPack) {
|
|
1065
|
+
super(`Pack "${newPack}" claims table "${table}", but "${existingPack}" already owns it. Use a tablePrefix on one of them.`);
|
|
1066
|
+
this.name = "PackTableConflictError";
|
|
1067
|
+
this.table = table;
|
|
1068
|
+
this.existingPack = existingPack;
|
|
1069
|
+
this.newPack = newPack;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
class PackMissingDependencyError extends Error {
|
|
1074
|
+
pack;
|
|
1075
|
+
missingTable;
|
|
1076
|
+
constructor(pack, missingTable) {
|
|
1077
|
+
super(`Pack "${pack}" requires a reader for table "${missingTable}" but none is registered. Call engine.registerReader("${missingTable}", ...) before engine.registerPack.`);
|
|
1078
|
+
this.name = "PackMissingDependencyError";
|
|
1079
|
+
this.pack = pack;
|
|
1080
|
+
this.missingTable = missingTable;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
var defineSyncPack = (pack) => pack;
|
|
1059
1084
|
// src/engine/mutation.ts
|
|
1060
1085
|
var defineMutation = (definition) => definition;
|
|
1061
1086
|
// src/engine/retry.ts
|
|
@@ -1405,6 +1430,8 @@ var createSyncEngine = (options = {}) => {
|
|
|
1405
1430
|
const writers = new Map;
|
|
1406
1431
|
const readers = new Map;
|
|
1407
1432
|
const schedules = new Map;
|
|
1433
|
+
const packTableOwners = new Map;
|
|
1434
|
+
const registeredPacks = [];
|
|
1408
1435
|
const permissions = new Map;
|
|
1409
1436
|
for (const [table, rules] of Object.entries(options.permissions ?? {})) {
|
|
1410
1437
|
permissions.set(table, rules);
|
|
@@ -2136,7 +2163,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2136
2163
|
}
|
|
2137
2164
|
};
|
|
2138
2165
|
};
|
|
2139
|
-
|
|
2166
|
+
const engine = {
|
|
2140
2167
|
register: (collection) => {
|
|
2141
2168
|
registry.set(collection.name, collection);
|
|
2142
2169
|
for (const table of collection.tables ?? [collection.name]) {
|
|
@@ -2411,13 +2438,136 @@ var createSyncEngine = (options = {}) => {
|
|
|
2411
2438
|
throw new Error(`Unknown schedule "${name}"`);
|
|
2412
2439
|
}
|
|
2413
2440
|
const runHandler = async (tx) => {
|
|
2414
|
-
const { actions, buffered
|
|
2441
|
+
const { actions, buffered } = makeActions(tx, {}, false);
|
|
2415
2442
|
const db = makeReadHandle({}, new Set, new Set, [], false);
|
|
2416
2443
|
await schedule.run({ actions, db });
|
|
2417
|
-
return
|
|
2444
|
+
return buffered;
|
|
2418
2445
|
};
|
|
2419
|
-
const
|
|
2420
|
-
|
|
2446
|
+
const retry = schedule.retry;
|
|
2447
|
+
const maxAttempts = retry === undefined ? 1 : retry.maxAttempts ?? 5;
|
|
2448
|
+
const isRetryable = retry?.isRetryable ?? isSerializationFailure;
|
|
2449
|
+
const computeDelay = retry?.backoff ?? exponentialBackoff();
|
|
2450
|
+
const maxElapsedMs = retry?.maxElapsedMs ?? 30000;
|
|
2451
|
+
const startedAt = Date.now();
|
|
2452
|
+
let lastError;
|
|
2453
|
+
let attemptsMade = 0;
|
|
2454
|
+
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
2455
|
+
attemptsMade = attempt;
|
|
2456
|
+
try {
|
|
2457
|
+
const buffered = runInTransaction !== undefined ? await runInTransaction((tx) => runHandler(tx)) : await runHandler(undefined);
|
|
2458
|
+
await applyChangeBatch(buffered);
|
|
2459
|
+
emitActivity({
|
|
2460
|
+
type: "schedule",
|
|
2461
|
+
at: Date.now(),
|
|
2462
|
+
name,
|
|
2463
|
+
status: "ok"
|
|
2464
|
+
});
|
|
2465
|
+
return;
|
|
2466
|
+
} catch (error) {
|
|
2467
|
+
lastError = error;
|
|
2468
|
+
const elapsedMs = Date.now() - startedAt;
|
|
2469
|
+
const canRetry = attempt < maxAttempts && isRetryable(error) && elapsedMs < maxElapsedMs;
|
|
2470
|
+
if (!canRetry)
|
|
2471
|
+
break;
|
|
2472
|
+
const rawDelay = computeDelay(attempt);
|
|
2473
|
+
const remaining = maxElapsedMs - elapsedMs;
|
|
2474
|
+
if (remaining <= 0)
|
|
2475
|
+
break;
|
|
2476
|
+
const delayMs = Math.max(0, Math.min(rawDelay, remaining));
|
|
2477
|
+
emitActivity({
|
|
2478
|
+
type: "scheduleRetry",
|
|
2479
|
+
at: Date.now(),
|
|
2480
|
+
name,
|
|
2481
|
+
attempt,
|
|
2482
|
+
delayMs,
|
|
2483
|
+
errorName: error instanceof Error ? error.name : "Error",
|
|
2484
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
2485
|
+
});
|
|
2486
|
+
if (delayMs > 0) {
|
|
2487
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
emitActivity({
|
|
2492
|
+
type: "schedule",
|
|
2493
|
+
at: Date.now(),
|
|
2494
|
+
name,
|
|
2495
|
+
status: "error"
|
|
2496
|
+
});
|
|
2497
|
+
if (attemptsMade > 1) {
|
|
2498
|
+
throw new RetriesExhaustedError(attemptsMade, Date.now() - startedAt, lastError);
|
|
2499
|
+
}
|
|
2500
|
+
throw lastError;
|
|
2501
|
+
},
|
|
2502
|
+
registerPack: (pack) => {
|
|
2503
|
+
for (const table of pack.ownsTables) {
|
|
2504
|
+
const existing = packTableOwners.get(table);
|
|
2505
|
+
if (existing !== undefined) {
|
|
2506
|
+
throw new PackTableConflictError(table, existing, pack.name);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
if (pack.requireDependencies === true) {
|
|
2510
|
+
for (const table of pack.readsTables ?? []) {
|
|
2511
|
+
if (!readers.has(table)) {
|
|
2512
|
+
throw new PackMissingDependencyError(pack.name, table);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
if (pack.schemas !== undefined) {
|
|
2517
|
+
for (const [table, schema] of Object.entries(pack.schemas)) {
|
|
2518
|
+
engine.registerSchema(table, schema);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
if (pack.permissions !== undefined) {
|
|
2522
|
+
for (const [table, rules] of Object.entries(pack.permissions)) {
|
|
2523
|
+
engine.registerPermissions(table, rules);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
if (pack.readers !== undefined) {
|
|
2527
|
+
for (const [table, reader] of Object.entries(pack.readers)) {
|
|
2528
|
+
engine.registerReader(table, reader);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
if (pack.writers !== undefined) {
|
|
2532
|
+
for (const [table, writer] of Object.entries(pack.writers)) {
|
|
2533
|
+
engine.registerWriter(table, writer);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
if (pack.crdt !== undefined) {
|
|
2537
|
+
for (const [table, fields] of Object.entries(pack.crdt)) {
|
|
2538
|
+
engine.registerCrdt(table, fields);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
for (const collection of pack.collections ?? []) {
|
|
2542
|
+
engine.register(collection);
|
|
2543
|
+
}
|
|
2544
|
+
for (const collection of pack.joinCollections ?? []) {
|
|
2545
|
+
engine.registerJoin(collection);
|
|
2546
|
+
}
|
|
2547
|
+
for (const collection of pack.graphCollections ?? []) {
|
|
2548
|
+
engine.registerGraph(collection);
|
|
2549
|
+
}
|
|
2550
|
+
for (const collection of pack.searchCollections ?? []) {
|
|
2551
|
+
engine.registerSearch(collection);
|
|
2552
|
+
}
|
|
2553
|
+
for (const query2 of pack.reactiveQueries ?? []) {
|
|
2554
|
+
engine.registerReactive(query2);
|
|
2555
|
+
}
|
|
2556
|
+
for (const mutation of pack.mutations ?? []) {
|
|
2557
|
+
engine.registerMutation(mutation);
|
|
2558
|
+
}
|
|
2559
|
+
for (const schedule of pack.schedules ?? []) {
|
|
2560
|
+
engine.registerSchedule(schedule);
|
|
2561
|
+
}
|
|
2562
|
+
for (const table of pack.ownsTables) {
|
|
2563
|
+
packTableOwners.set(table, pack.name);
|
|
2564
|
+
}
|
|
2565
|
+
registeredPacks.push({
|
|
2566
|
+
name: pack.name,
|
|
2567
|
+
version: pack.version,
|
|
2568
|
+
ownsTables: [...pack.ownsTables],
|
|
2569
|
+
readsTables: [...pack.readsTables ?? []]
|
|
2570
|
+
});
|
|
2421
2571
|
},
|
|
2422
2572
|
inspect: () => {
|
|
2423
2573
|
const collections = [...registry.entries()].map(([name, def]) => {
|
|
@@ -2457,6 +2607,12 @@ var createSyncEngine = (options = {}) => {
|
|
|
2457
2607
|
version: entry.version,
|
|
2458
2608
|
table: entry.table,
|
|
2459
2609
|
op: entry.change.op
|
|
2610
|
+
})),
|
|
2611
|
+
packs: registeredPacks.map((pack) => ({
|
|
2612
|
+
name: pack.name,
|
|
2613
|
+
version: pack.version,
|
|
2614
|
+
ownsTables: [...pack.ownsTables],
|
|
2615
|
+
readsTables: [...pack.readsTables]
|
|
2460
2616
|
}))
|
|
2461
2617
|
};
|
|
2462
2618
|
},
|
|
@@ -2543,6 +2699,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2543
2699
|
};
|
|
2544
2700
|
}
|
|
2545
2701
|
};
|
|
2702
|
+
return engine;
|
|
2546
2703
|
};
|
|
2547
2704
|
// src/engine/cdc.ts
|
|
2548
2705
|
import { Elysia } from "elysia";
|
|
@@ -2892,6 +3049,7 @@ export {
|
|
|
2892
3049
|
filterOp,
|
|
2893
3050
|
field,
|
|
2894
3051
|
exponentialBackoff,
|
|
3052
|
+
defineSyncPack,
|
|
2895
3053
|
defineSearchCollection,
|
|
2896
3054
|
defineSchema,
|
|
2897
3055
|
defineSchedule,
|
|
@@ -2917,9 +3075,11 @@ export {
|
|
|
2917
3075
|
SchemaError,
|
|
2918
3076
|
SEARCH_SCORE_FIELD,
|
|
2919
3077
|
RetriesExhaustedError,
|
|
3078
|
+
PackTableConflictError,
|
|
3079
|
+
PackMissingDependencyError,
|
|
2920
3080
|
MissedChangesError,
|
|
2921
3081
|
CdcConsumerSlowError
|
|
2922
3082
|
};
|
|
2923
3083
|
|
|
2924
|
-
//# debugId=
|
|
3084
|
+
//# debugId=3D4E309EDB79002E64756E2164756E21
|
|
2925
3085
|
//# sourceMappingURL=index.js.map
|