@absolutejs/sync 1.18.2 → 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 +83 -3
- package/dist/engine/index.js.map +3 -3
- package/dist/engine/syncEngine.d.ts +115 -0
- package/dist/index.js +82 -3
- package/dist/index.js.map +3 -3
- package/dist/testing.js +82 -3
- package/dist/testing.js.map +3 -3
- package/package.json +1 -1
package/dist/testing.js
CHANGED
|
@@ -625,6 +625,15 @@ class CdcConsumerSlowError extends Error {
|
|
|
625
625
|
this.lastDeliveredVersion = lastDeliveredVersion;
|
|
626
626
|
}
|
|
627
627
|
}
|
|
628
|
+
|
|
629
|
+
class MutationQueueOverflowError extends Error {
|
|
630
|
+
queueLimit;
|
|
631
|
+
constructor(queueLimit) {
|
|
632
|
+
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.`);
|
|
633
|
+
this.name = "MutationQueueOverflowError";
|
|
634
|
+
this.queueLimit = queueLimit;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
628
637
|
var defaultKey = (row) => row.id;
|
|
629
638
|
var shallowEqual3 = (a, b) => {
|
|
630
639
|
if (a === b) {
|
|
@@ -741,6 +750,40 @@ var createSyncEngine = (options = {}) => {
|
|
|
741
750
|
let mutationsFailed = 0;
|
|
742
751
|
let mutationsRetried = 0;
|
|
743
752
|
let mutationsInFlight = 0;
|
|
753
|
+
const mutationWaiters = [];
|
|
754
|
+
let mutationsQueued = 0;
|
|
755
|
+
const acquireMutationSlot = async () => {
|
|
756
|
+
const limit = options.mutationConcurrency;
|
|
757
|
+
if (limit === undefined) {
|
|
758
|
+
mutationsInFlight += 1;
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
if (mutationsInFlight < limit && mutationWaiters.length === 0) {
|
|
762
|
+
mutationsInFlight += 1;
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const queueLimit = options.mutationQueueLimit;
|
|
766
|
+
if (queueLimit !== undefined && mutationsQueued >= queueLimit) {
|
|
767
|
+
throw new MutationQueueOverflowError(queueLimit);
|
|
768
|
+
}
|
|
769
|
+
mutationsQueued += 1;
|
|
770
|
+
try {
|
|
771
|
+
await new Promise((resolve) => {
|
|
772
|
+
mutationWaiters.push(resolve);
|
|
773
|
+
});
|
|
774
|
+
} finally {
|
|
775
|
+
mutationsQueued -= 1;
|
|
776
|
+
}
|
|
777
|
+
mutationsInFlight += 1;
|
|
778
|
+
};
|
|
779
|
+
const releaseMutationSlot = () => {
|
|
780
|
+
mutationsInFlight -= 1;
|
|
781
|
+
if (options.mutationConcurrency === undefined)
|
|
782
|
+
return;
|
|
783
|
+
const next = mutationWaiters.shift();
|
|
784
|
+
if (next !== undefined)
|
|
785
|
+
next();
|
|
786
|
+
};
|
|
744
787
|
const reactiveCacheMax = options.reactiveCache?.max ?? 256;
|
|
745
788
|
const reactiveCacheTtlMs = options.reactiveCache?.ttlMs ?? 60000;
|
|
746
789
|
const cachedReruns = new Map;
|
|
@@ -782,6 +825,31 @@ var createSyncEngine = (options = {}) => {
|
|
|
782
825
|
const runInTransaction = options.transaction;
|
|
783
826
|
const instanceId = options.instanceId ?? globalThis.crypto?.randomUUID?.() ?? `i${Math.random()}`;
|
|
784
827
|
let clusterBus;
|
|
828
|
+
const importChangeLog = (snapshot) => {
|
|
829
|
+
if (version !== 0) {
|
|
830
|
+
throw new Error(`[sync] importChangeLog: engine already has version ${version}; ` + `restore must happen before any local writes commit.`);
|
|
831
|
+
}
|
|
832
|
+
if (snapshot.instanceId !== instanceId) {
|
|
833
|
+
throw new Error(`[sync] importChangeLog: snapshot instanceId "${snapshot.instanceId}" ` + `does not match this engine's instanceId "${instanceId}". ` + `Pass options.instanceId = "${snapshot.instanceId}" to createSyncEngine.`);
|
|
834
|
+
}
|
|
835
|
+
version = snapshot.version;
|
|
836
|
+
for (const entry of snapshot.entries) {
|
|
837
|
+
changeLog.push(entry);
|
|
838
|
+
}
|
|
839
|
+
while (changeLog.length > changeLogSize) {
|
|
840
|
+
changeLog.shift();
|
|
841
|
+
}
|
|
842
|
+
if (changeLogRetainMs !== null && changeLogRetainMs > 0) {
|
|
843
|
+
const cutoff = Date.now() - changeLogRetainMs;
|
|
844
|
+
while (changeLog.length > 0 && changeLog[0].at < cutoff) {
|
|
845
|
+
changeLog.shift();
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return snapshot.entries.length;
|
|
849
|
+
};
|
|
850
|
+
if (options.initialChangeLog !== undefined) {
|
|
851
|
+
importChangeLog(options.initialChangeLog);
|
|
852
|
+
}
|
|
785
853
|
const broadcast = (changes, originVersion) => {
|
|
786
854
|
if (clusterBus !== undefined && changes.length > 0) {
|
|
787
855
|
clusterBus.publish({ changes, origin: instanceId, originVersion });
|
|
@@ -1743,6 +1811,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
1743
1811
|
throw new UnauthorizedError(`run mutation "${name}"`);
|
|
1744
1812
|
}
|
|
1745
1813
|
}
|
|
1814
|
+
await acquireMutationSlot();
|
|
1746
1815
|
const sandboxRunner = sandboxRunners.get(name);
|
|
1747
1816
|
const invokeHandler = sandboxRunner !== undefined ? sandboxRunner : (a, c, actions) => Promise.resolve(mutation.handler(a, c, actions));
|
|
1748
1817
|
const runHandler = async (tx) => {
|
|
@@ -1758,7 +1827,6 @@ var createSyncEngine = (options = {}) => {
|
|
|
1758
1827
|
const startedAt = Date.now();
|
|
1759
1828
|
let lastError;
|
|
1760
1829
|
let attemptsMade = 0;
|
|
1761
|
-
mutationsInFlight += 1;
|
|
1762
1830
|
try {
|
|
1763
1831
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
1764
1832
|
attemptsMade = attempt;
|
|
@@ -1811,7 +1879,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
1811
1879
|
}
|
|
1812
1880
|
throw lastError;
|
|
1813
1881
|
} finally {
|
|
1814
|
-
|
|
1882
|
+
releaseMutationSlot();
|
|
1815
1883
|
}
|
|
1816
1884
|
},
|
|
1817
1885
|
runMutations: async (specs, ctx) => {
|
|
@@ -1824,6 +1892,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
1824
1892
|
}
|
|
1825
1893
|
return { args: spec.args, mutation, name: spec.name };
|
|
1826
1894
|
});
|
|
1895
|
+
await acquireMutationSlot();
|
|
1827
1896
|
const runBatch = async (tx) => {
|
|
1828
1897
|
const results = [];
|
|
1829
1898
|
const accumulated = [];
|
|
@@ -1861,6 +1930,8 @@ var createSyncEngine = (options = {}) => {
|
|
|
1861
1930
|
status: "error"
|
|
1862
1931
|
});
|
|
1863
1932
|
throw error;
|
|
1933
|
+
} finally {
|
|
1934
|
+
releaseMutationSlot();
|
|
1864
1935
|
}
|
|
1865
1936
|
},
|
|
1866
1937
|
registerSchedule: (schedule) => {
|
|
@@ -2051,6 +2122,13 @@ var createSyncEngine = (options = {}) => {
|
|
|
2051
2122
|
}))
|
|
2052
2123
|
};
|
|
2053
2124
|
},
|
|
2125
|
+
exportChangeLog: () => ({
|
|
2126
|
+
entries: changeLog.slice(),
|
|
2127
|
+
exportedAt: Date.now(),
|
|
2128
|
+
instanceId,
|
|
2129
|
+
version
|
|
2130
|
+
}),
|
|
2131
|
+
importChangeLog,
|
|
2054
2132
|
metrics: () => {
|
|
2055
2133
|
const now = Date.now();
|
|
2056
2134
|
const byCollection = {};
|
|
@@ -2073,6 +2151,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2073
2151
|
completed: mutationsCompleted,
|
|
2074
2152
|
failed: mutationsFailed,
|
|
2075
2153
|
inFlight: mutationsInFlight,
|
|
2154
|
+
queued: mutationsQueued,
|
|
2076
2155
|
retried: mutationsRetried
|
|
2077
2156
|
},
|
|
2078
2157
|
reactiveCache: {
|
|
@@ -2193,5 +2272,5 @@ export {
|
|
|
2193
2272
|
createTestEngine
|
|
2194
2273
|
};
|
|
2195
2274
|
|
|
2196
|
-
//# debugId=
|
|
2275
|
+
//# debugId=261DFADB673FBB5664756E2164756E21
|
|
2197
2276
|
//# sourceMappingURL=testing.js.map
|