-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathflush.ts
More file actions
50 lines (47 loc) · 1.77 KB
/
flush.ts
File metadata and controls
50 lines (47 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import type { ExecutionContext } from '@cloudflare/workers-types';
import { startSpan, withScope } from '@sentry/core';
type FlushLock = {
readonly ready: Promise<void>;
readonly finalize: () => Promise<void>;
};
/**
* Enhances the given execution context by wrapping its `waitUntil` method with a proxy
* to monitor pending tasks, and provides a flusher function to ensure all tasks
* have been completed before executing any subsequent logic.
*
* @param {ExecutionContext} context - The execution context to be enhanced. If no context is provided, the function returns undefined.
* @return {FlushLock} Returns a flusher function if a valid context is provided, otherwise undefined.
*/
export function makeFlushLock(context: ExecutionContext): FlushLock {
let resolveAllDone: () => void = () => undefined;
const allDone = new Promise<void>(res => {
resolveAllDone = res;
});
let pending = 0;
const originalWaitUntil = context.waitUntil.bind(context) as typeof context.waitUntil;
context.waitUntil = promise => {
pending++;
return originalWaitUntil(
// Wrap the promise in a new scope and transaction so spans created inside
// waitUntil callbacks are properly isolated from the HTTP request transaction
withScope(() =>
startSpan({ forceTransaction: true, op: 'cloudflare.wait_until', name: 'waitUntil' }, async () => {
// By awaiting the promise inside the new scope, all of its continuations
// will execute in this isolated scope
await promise;
}),
).finally(() => {
if (--pending === 0) {
resolveAllDone();
}
}),
);
};
return Object.freeze({
ready: allDone,
finalize: () => {
if (pending === 0) resolveAllDone();
return allDone;
},
});
}