@absolutejs/sync 1.19.0 → 1.20.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 +5 -0
- package/dist/engine/index.d.ts +2 -2
- package/dist/engine/index.js +51 -3
- package/dist/engine/index.js.map +3 -3
- package/dist/engine/syncEngine.d.ts +40 -0
- package/dist/index.js +50 -3
- package/dist/index.js.map +3 -3
- package/dist/testing.js +50 -3
- package/dist/testing.js.map +3 -3
- package/package.json +1 -1
|
@@ -96,6 +96,11 @@ export type EngineMetrics = {
|
|
|
96
96
|
retried: number;
|
|
97
97
|
/** Currently running, not yet committed or failed. */
|
|
98
98
|
inFlight: number;
|
|
99
|
+
/**
|
|
100
|
+
* Waiting in the `mutationConcurrency` queue. Always `0` when
|
|
101
|
+
* `mutationConcurrency` is unset (no semaphore). Added in 1.20.0.
|
|
102
|
+
*/
|
|
103
|
+
queued: number;
|
|
99
104
|
};
|
|
100
105
|
schedules: {
|
|
101
106
|
registered: number;
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -47,8 +47,8 @@ export type { MutationActions, MutationDefinition, MutationHandler, TableWriter,
|
|
|
47
47
|
export type { BridgeFetchConfig, BridgeFetchEndpoint, BridgeFetchResponse, HandlerMetricsHook, HandlerMetricsRecord, SandboxConfig } from './sandbox';
|
|
48
48
|
export { exponentialBackoff, isSerializationFailure, RetriesExhaustedError } from './retry';
|
|
49
49
|
export type { ExponentialBackoffOptions, RetryPolicy } from './retry';
|
|
50
|
-
export { CdcConsumerSlowError, createSyncEngine, MissedChangesError, SchemaError, UnauthorizedError } from './syncEngine';
|
|
51
|
-
export type { CrdtFields, LoggedChange, StreamChangesOptions, SubscribeArgs, Subscription, SyncEngine } from './syncEngine';
|
|
50
|
+
export { CdcConsumerSlowError, createSyncEngine, MissedChangesError, MutationQueueOverflowError, SchemaError, UnauthorizedError } from './syncEngine';
|
|
51
|
+
export type { ChangeLogSnapshot, CrdtFields, LoggedChange, StreamChangesOptions, SubscribeArgs, Subscription, SyncEngine, SyncEngineOptions } from './syncEngine';
|
|
52
52
|
export { syncCdc } from './cdc';
|
|
53
53
|
export type { SyncCdcOptions } from './cdc';
|
|
54
54
|
export type { CrdtMergeable } from '../crdt';
|
package/dist/engine/index.js
CHANGED
|
@@ -1410,6 +1410,15 @@ class CdcConsumerSlowError extends Error {
|
|
|
1410
1410
|
this.lastDeliveredVersion = lastDeliveredVersion;
|
|
1411
1411
|
}
|
|
1412
1412
|
}
|
|
1413
|
+
|
|
1414
|
+
class MutationQueueOverflowError extends Error {
|
|
1415
|
+
queueLimit;
|
|
1416
|
+
constructor(queueLimit) {
|
|
1417
|
+
super(`Mutation queue overflowed (limit ${queueLimit}); the engine is at ` + `its mutationConcurrency cap and the waiting queue is full. ` + `Retry later or shed load at the gateway.`);
|
|
1418
|
+
this.name = "MutationQueueOverflowError";
|
|
1419
|
+
this.queueLimit = queueLimit;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1413
1422
|
var defaultKey = (row) => row.id;
|
|
1414
1423
|
var shallowEqual4 = (a, b) => {
|
|
1415
1424
|
if (a === b) {
|
|
@@ -1526,6 +1535,40 @@ var createSyncEngine = (options = {}) => {
|
|
|
1526
1535
|
let mutationsFailed = 0;
|
|
1527
1536
|
let mutationsRetried = 0;
|
|
1528
1537
|
let mutationsInFlight = 0;
|
|
1538
|
+
const mutationWaiters = [];
|
|
1539
|
+
let mutationsQueued = 0;
|
|
1540
|
+
const acquireMutationSlot = async () => {
|
|
1541
|
+
const limit = options.mutationConcurrency;
|
|
1542
|
+
if (limit === undefined) {
|
|
1543
|
+
mutationsInFlight += 1;
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
if (mutationsInFlight < limit && mutationWaiters.length === 0) {
|
|
1547
|
+
mutationsInFlight += 1;
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
const queueLimit = options.mutationQueueLimit;
|
|
1551
|
+
if (queueLimit !== undefined && mutationsQueued >= queueLimit) {
|
|
1552
|
+
throw new MutationQueueOverflowError(queueLimit);
|
|
1553
|
+
}
|
|
1554
|
+
mutationsQueued += 1;
|
|
1555
|
+
try {
|
|
1556
|
+
await new Promise((resolve) => {
|
|
1557
|
+
mutationWaiters.push(resolve);
|
|
1558
|
+
});
|
|
1559
|
+
} finally {
|
|
1560
|
+
mutationsQueued -= 1;
|
|
1561
|
+
}
|
|
1562
|
+
mutationsInFlight += 1;
|
|
1563
|
+
};
|
|
1564
|
+
const releaseMutationSlot = () => {
|
|
1565
|
+
mutationsInFlight -= 1;
|
|
1566
|
+
if (options.mutationConcurrency === undefined)
|
|
1567
|
+
return;
|
|
1568
|
+
const next = mutationWaiters.shift();
|
|
1569
|
+
if (next !== undefined)
|
|
1570
|
+
next();
|
|
1571
|
+
};
|
|
1529
1572
|
const reactiveCacheMax = options.reactiveCache?.max ?? 256;
|
|
1530
1573
|
const reactiveCacheTtlMs = options.reactiveCache?.ttlMs ?? 60000;
|
|
1531
1574
|
const cachedReruns = new Map;
|
|
@@ -2553,6 +2596,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2553
2596
|
throw new UnauthorizedError(`run mutation "${name}"`);
|
|
2554
2597
|
}
|
|
2555
2598
|
}
|
|
2599
|
+
await acquireMutationSlot();
|
|
2556
2600
|
const sandboxRunner = sandboxRunners.get(name);
|
|
2557
2601
|
const invokeHandler = sandboxRunner !== undefined ? sandboxRunner : (a, c, actions) => Promise.resolve(mutation.handler(a, c, actions));
|
|
2558
2602
|
const runHandler = async (tx) => {
|
|
@@ -2568,7 +2612,6 @@ var createSyncEngine = (options = {}) => {
|
|
|
2568
2612
|
const startedAt = Date.now();
|
|
2569
2613
|
let lastError;
|
|
2570
2614
|
let attemptsMade = 0;
|
|
2571
|
-
mutationsInFlight += 1;
|
|
2572
2615
|
try {
|
|
2573
2616
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
2574
2617
|
attemptsMade = attempt;
|
|
@@ -2621,7 +2664,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2621
2664
|
}
|
|
2622
2665
|
throw lastError;
|
|
2623
2666
|
} finally {
|
|
2624
|
-
|
|
2667
|
+
releaseMutationSlot();
|
|
2625
2668
|
}
|
|
2626
2669
|
},
|
|
2627
2670
|
runMutations: async (specs, ctx) => {
|
|
@@ -2634,6 +2677,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2634
2677
|
}
|
|
2635
2678
|
return { args: spec.args, mutation, name: spec.name };
|
|
2636
2679
|
});
|
|
2680
|
+
await acquireMutationSlot();
|
|
2637
2681
|
const runBatch = async (tx) => {
|
|
2638
2682
|
const results = [];
|
|
2639
2683
|
const accumulated = [];
|
|
@@ -2671,6 +2715,8 @@ var createSyncEngine = (options = {}) => {
|
|
|
2671
2715
|
status: "error"
|
|
2672
2716
|
});
|
|
2673
2717
|
throw error;
|
|
2718
|
+
} finally {
|
|
2719
|
+
releaseMutationSlot();
|
|
2674
2720
|
}
|
|
2675
2721
|
},
|
|
2676
2722
|
registerSchedule: (schedule) => {
|
|
@@ -2890,6 +2936,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2890
2936
|
completed: mutationsCompleted,
|
|
2891
2937
|
failed: mutationsFailed,
|
|
2892
2938
|
inFlight: mutationsInFlight,
|
|
2939
|
+
queued: mutationsQueued,
|
|
2893
2940
|
retried: mutationsRetried
|
|
2894
2941
|
},
|
|
2895
2942
|
reactiveCache: {
|
|
@@ -3434,9 +3481,10 @@ export {
|
|
|
3434
3481
|
RetriesExhaustedError,
|
|
3435
3482
|
PackTableConflictError,
|
|
3436
3483
|
PackMissingDependencyError,
|
|
3484
|
+
MutationQueueOverflowError,
|
|
3437
3485
|
MissedChangesError,
|
|
3438
3486
|
CdcConsumerSlowError
|
|
3439
3487
|
};
|
|
3440
3488
|
|
|
3441
|
-
//# debugId=
|
|
3489
|
+
//# debugId=E104F5FFDBD631C764756E2164756E21
|
|
3442
3490
|
//# sourceMappingURL=index.js.map
|