@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.
@@ -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;
@@ -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';
@@ -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
- mutationsInFlight -= 1;
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=079CCC84C9743C1064756E2164756E21
3489
+ //# debugId=E104F5FFDBD631C764756E2164756E21
3442
3490
  //# sourceMappingURL=index.js.map