@yorozu/utils 0.5.0 → 0.5.2
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/async/index.d.ts +1 -0
- package/async/priority-work-queue.d.ts +25 -0
- package/index.js +139 -21
- package/package.json +1 -1
package/async/index.d.ts
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type WorkPri = "visible" | "preload" | "background";
|
|
2
|
+
export type PriorityWorkJob = {
|
|
3
|
+
id: string;
|
|
4
|
+
pri: WorkPri;
|
|
5
|
+
run: (ctx: {
|
|
6
|
+
signal: AbortSignal;
|
|
7
|
+
}) => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export type PriorityWorkQueueStats = {
|
|
10
|
+
active: number;
|
|
11
|
+
queued: number;
|
|
12
|
+
maxActive: number;
|
|
13
|
+
};
|
|
14
|
+
export type PriorityWorkQueueOptions = {
|
|
15
|
+
concurrency?: number;
|
|
16
|
+
onError?: (error: Error, id: string) => void;
|
|
17
|
+
};
|
|
18
|
+
export type PriorityWorkQueue = {
|
|
19
|
+
enqueue(job: PriorityWorkJob): boolean;
|
|
20
|
+
cancel(id: string): boolean;
|
|
21
|
+
cancelAll(): void;
|
|
22
|
+
isBusy(id: string): boolean;
|
|
23
|
+
get stats(): PriorityWorkQueueStats;
|
|
24
|
+
};
|
|
25
|
+
export declare function createPriorityWorkQueue(opts?: PriorityWorkQueueOptions): PriorityWorkQueue;
|
package/index.js
CHANGED
|
@@ -1803,26 +1803,6 @@ async function parallelMap(iterable, executor, options = {}) {
|
|
|
1803
1803
|
return result;
|
|
1804
1804
|
}
|
|
1805
1805
|
//#endregion
|
|
1806
|
-
//#region src/async/sleep.ts
|
|
1807
|
-
function sleep(ms, signal) {
|
|
1808
|
-
if (ms < 0) throw new RangeError("sleep: ms must be a non-negative number");
|
|
1809
|
-
return new Promise((resolve, reject) => {
|
|
1810
|
-
if (signal?.aborted) {
|
|
1811
|
-
reject(signal.reason ?? new DOMException("The operation was aborted.", "AbortError"));
|
|
1812
|
-
return;
|
|
1813
|
-
}
|
|
1814
|
-
let onAbort = () => {
|
|
1815
|
-
clearTimeout(timeoutId);
|
|
1816
|
-
reject(signal?.reason ?? new DOMException("The operation was aborted.", "AbortError"));
|
|
1817
|
-
};
|
|
1818
|
-
let timeoutId = setTimeout(() => {
|
|
1819
|
-
signal?.removeEventListener("abort", onAbort);
|
|
1820
|
-
resolve();
|
|
1821
|
-
}, ms);
|
|
1822
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1823
|
-
});
|
|
1824
|
-
}
|
|
1825
|
-
//#endregion
|
|
1826
1806
|
//#region src/types/error.ts
|
|
1827
1807
|
function unknownToError(err) {
|
|
1828
1808
|
if (err instanceof Error) return err;
|
|
@@ -1845,6 +1825,144 @@ function throwUnreachable() {
|
|
|
1845
1825
|
throw new Error("Unreachable");
|
|
1846
1826
|
}
|
|
1847
1827
|
//#endregion
|
|
1828
|
+
//#region src/async/priority-work-queue.ts
|
|
1829
|
+
var PRI_ORDER = [
|
|
1830
|
+
"visible",
|
|
1831
|
+
"preload",
|
|
1832
|
+
"background"
|
|
1833
|
+
];
|
|
1834
|
+
function isAbortError(err) {
|
|
1835
|
+
return err instanceof Error && err.name === "AbortError";
|
|
1836
|
+
}
|
|
1837
|
+
function emptyLanes() {
|
|
1838
|
+
return {
|
|
1839
|
+
visible: [],
|
|
1840
|
+
preload: [],
|
|
1841
|
+
background: []
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
function resolveConcurrency(value) {
|
|
1845
|
+
if (value === void 0) return 3;
|
|
1846
|
+
let n = Math.floor(value);
|
|
1847
|
+
if (!Number.isFinite(n) || n < 1) return 1;
|
|
1848
|
+
return n;
|
|
1849
|
+
}
|
|
1850
|
+
function createPriorityWorkQueue(opts) {
|
|
1851
|
+
let concurrency = resolveConcurrency(opts?.concurrency);
|
|
1852
|
+
let lanes = emptyLanes();
|
|
1853
|
+
let queuedPri = /* @__PURE__ */ new Map();
|
|
1854
|
+
let active = /* @__PURE__ */ new Map();
|
|
1855
|
+
let maxActive = 0;
|
|
1856
|
+
function queuedCount() {
|
|
1857
|
+
return queuedPri.size;
|
|
1858
|
+
}
|
|
1859
|
+
function removeQueued(id) {
|
|
1860
|
+
let pri = queuedPri.get(id);
|
|
1861
|
+
if (pri === void 0) return void 0;
|
|
1862
|
+
let lane = lanes[pri];
|
|
1863
|
+
let idx = lane.findIndex((job) => job.id === id);
|
|
1864
|
+
queuedPri.delete(id);
|
|
1865
|
+
if (idx < 0) return void 0;
|
|
1866
|
+
return lane.splice(idx, 1)[0];
|
|
1867
|
+
}
|
|
1868
|
+
function pickNext() {
|
|
1869
|
+
for (let pri of PRI_ORDER) {
|
|
1870
|
+
let lane = lanes[pri];
|
|
1871
|
+
while (lane.length > 0) {
|
|
1872
|
+
let job = lane.shift();
|
|
1873
|
+
queuedPri.delete(job.id);
|
|
1874
|
+
if (active.has(job.id)) continue;
|
|
1875
|
+
return job;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
function pump() {
|
|
1880
|
+
while (active.size < concurrency) {
|
|
1881
|
+
let job = pickNext();
|
|
1882
|
+
if (!job) return;
|
|
1883
|
+
startJob(job);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
function startJob(job) {
|
|
1887
|
+
let controller = new AbortController();
|
|
1888
|
+
active.set(job.id, {
|
|
1889
|
+
id: job.id,
|
|
1890
|
+
controller
|
|
1891
|
+
});
|
|
1892
|
+
if (active.size > maxActive) maxActive = active.size;
|
|
1893
|
+
(async () => {
|
|
1894
|
+
let reported;
|
|
1895
|
+
try {
|
|
1896
|
+
await job.run({ signal: controller.signal });
|
|
1897
|
+
} catch (err) {
|
|
1898
|
+
if (!isAbortError(err)) reported = unknownToError(err);
|
|
1899
|
+
} finally {
|
|
1900
|
+
active.delete(job.id);
|
|
1901
|
+
}
|
|
1902
|
+
if (reported) try {
|
|
1903
|
+
opts?.onError?.(reported, job.id);
|
|
1904
|
+
} catch {}
|
|
1905
|
+
pump();
|
|
1906
|
+
})();
|
|
1907
|
+
}
|
|
1908
|
+
return {
|
|
1909
|
+
enqueue(job) {
|
|
1910
|
+
if (active.has(job.id)) return false;
|
|
1911
|
+
removeQueued(job.id);
|
|
1912
|
+
lanes[job.pri].push({
|
|
1913
|
+
id: job.id,
|
|
1914
|
+
pri: job.pri,
|
|
1915
|
+
run: job.run
|
|
1916
|
+
});
|
|
1917
|
+
queuedPri.set(job.id, job.pri);
|
|
1918
|
+
pump();
|
|
1919
|
+
return true;
|
|
1920
|
+
},
|
|
1921
|
+
cancel(id) {
|
|
1922
|
+
if (removeQueued(id)) return true;
|
|
1923
|
+
let running = active.get(id);
|
|
1924
|
+
if (!running) return false;
|
|
1925
|
+
running.controller.abort();
|
|
1926
|
+
return true;
|
|
1927
|
+
},
|
|
1928
|
+
cancelAll() {
|
|
1929
|
+
lanes = emptyLanes();
|
|
1930
|
+
queuedPri.clear();
|
|
1931
|
+
for (let running of active.values()) running.controller.abort();
|
|
1932
|
+
},
|
|
1933
|
+
isBusy(id) {
|
|
1934
|
+
return active.has(id) || queuedPri.has(id);
|
|
1935
|
+
},
|
|
1936
|
+
get stats() {
|
|
1937
|
+
return {
|
|
1938
|
+
active: active.size,
|
|
1939
|
+
queued: queuedCount(),
|
|
1940
|
+
maxActive
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
//#endregion
|
|
1946
|
+
//#region src/async/sleep.ts
|
|
1947
|
+
function sleep(ms, signal) {
|
|
1948
|
+
if (ms < 0) throw new RangeError("sleep: ms must be a non-negative number");
|
|
1949
|
+
return new Promise((resolve, reject) => {
|
|
1950
|
+
if (signal?.aborted) {
|
|
1951
|
+
reject(signal.reason ?? new DOMException("The operation was aborted.", "AbortError"));
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
let onAbort = () => {
|
|
1955
|
+
clearTimeout(timeoutId);
|
|
1956
|
+
reject(signal?.reason ?? new DOMException("The operation was aborted.", "AbortError"));
|
|
1957
|
+
};
|
|
1958
|
+
let timeoutId = setTimeout(() => {
|
|
1959
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1960
|
+
resolve();
|
|
1961
|
+
}, ms);
|
|
1962
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
//#endregion
|
|
1848
1966
|
//#region src/compress/checksum.ts
|
|
1849
1967
|
var crcTable = new Int32Array(256);
|
|
1850
1968
|
for (let i = 0; i < 256; i++) {
|
|
@@ -3180,4 +3298,4 @@ var decompress_exports = /* @__PURE__ */ __exportAll({
|
|
|
3180
3298
|
zlib: () => decompress$1
|
|
3181
3299
|
});
|
|
3182
3300
|
//#endregion
|
|
3183
|
-
export { Adler32, AggregateError, AsyncInterval, AsyncLock, AsyncQueue, AsyncResource, ChecksumMismatchError, ConditionVariable, Crc32, CustomMap, CustomSet, Deferred, DeferredTracked, Deque, Emitter, FlateError, InvalidBlockTypeError, InvalidDistanceError, InvalidHeaderError, InvalidLengthLiteralError, LruMap, LruSet, NotImplementedError, StreamFinishedError, UnexpectedEofError, abs, adler32, asNonNull, assert, assertEndsWith, assertEndsWith as assertsEndsWith, assertHashKey, assertMatches, assertNotNull, assertStartsWith, asyncPool, base64_exports as base64, bitLength, clearUndefinedInPlace, composeMiddlewares, compress_exports as compress, crc32, decompress_exports as decompress, deepMerge, enumerate, euclideanGcd, fromBytes, hex_exports as hex, isBigInt, isBoolean, isFalsy, isFunction, isNotNull, isNotUndefined, isNumber, isObject, isString, isSymbol, isTruthy, max, max2, min, min2, modInv, modPowBinary, noop, objectEntries, objectKeys, parallelMap, sleep, splitOnce, throwNotImplemented, throwUnreachable, timers_exports as timers, toBytes, twoMultiplicity, typed_exports as typed, u8_exports as u8, unknownToError, unsafeCastType, utf8_exports as utf8 };
|
|
3301
|
+
export { Adler32, AggregateError, AsyncInterval, AsyncLock, AsyncQueue, AsyncResource, ChecksumMismatchError, ConditionVariable, Crc32, CustomMap, CustomSet, Deferred, DeferredTracked, Deque, Emitter, FlateError, InvalidBlockTypeError, InvalidDistanceError, InvalidHeaderError, InvalidLengthLiteralError, LruMap, LruSet, NotImplementedError, StreamFinishedError, UnexpectedEofError, abs, adler32, asNonNull, assert, assertEndsWith, assertEndsWith as assertsEndsWith, assertHashKey, assertMatches, assertNotNull, assertStartsWith, asyncPool, base64_exports as base64, bitLength, clearUndefinedInPlace, composeMiddlewares, compress_exports as compress, crc32, createPriorityWorkQueue, decompress_exports as decompress, deepMerge, enumerate, euclideanGcd, fromBytes, hex_exports as hex, isBigInt, isBoolean, isFalsy, isFunction, isNotNull, isNotUndefined, isNumber, isObject, isString, isSymbol, isTruthy, max, max2, min, min2, modInv, modPowBinary, noop, objectEntries, objectKeys, parallelMap, sleep, splitOnce, throwNotImplemented, throwUnreachable, timers_exports as timers, toBytes, twoMultiplicity, typed_exports as typed, u8_exports as u8, unknownToError, unsafeCastType, utf8_exports as utf8 };
|