mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-17 16:15:22 +00:00
45dd16b146
* Disable browser caching * Improve cache read * Fix * Try using it for lookup * Read before increment in redis * Don't use multi * Limit cache to 2min in cloudflare * Cache in cloudflare but not in the browser
51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
import { waitUntil } from './waitUntil';
|
|
|
|
/**
|
|
* Execute a function for each input in parallel and return the first result.
|
|
* It is designed to support executing in a worker environment where async execution outside the request lifecycle is not allowed.
|
|
* And also to support promise cancellation and optional result.
|
|
*/
|
|
export async function race<I, R>(
|
|
inputs: I[],
|
|
execute: (input: I, options: { signal: AbortSignal }) => Promise<R | null>,
|
|
): Promise<R | null> {
|
|
const abort = new AbortController();
|
|
const pendingReads: Array<Promise<void>> = [];
|
|
|
|
// Read from the cache backends and return the first result
|
|
const result = await new Promise<R | null>((resolve, reject) => {
|
|
let resolved = false;
|
|
let pending = inputs.length;
|
|
|
|
inputs.forEach((input) => {
|
|
pendingReads.push(
|
|
execute(input, { signal: abort.signal })
|
|
.then(
|
|
(inputResult) => {
|
|
if (!resolved && inputResult !== null) {
|
|
resolved = true;
|
|
resolve(inputResult);
|
|
abort.abort();
|
|
}
|
|
},
|
|
(error) => {
|
|
// Ignore errors
|
|
},
|
|
)
|
|
.finally(() => {
|
|
pending -= 1;
|
|
if (pending === 0 && !resolved) {
|
|
resolve(null);
|
|
}
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
// Wait for all reads to finish after responding to the request
|
|
// We need this to avoid async execution outside the request lifecycle in Cloudflare
|
|
await waitUntil(Promise.all(pendingReads));
|
|
|
|
return result;
|
|
}
|