-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Revert "feat(cloudflare): Introduce lock instrumentation for context.waitUntil
to prevent multiple instrumentation (#17539)"
#17666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import type { ExecutionContext } from '@cloudflare/workers-types'; | ||
|
||
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( | ||
promise.finally(() => { | ||
if (--pending === 0) resolveAllDone(); | ||
}), | ||
); | ||
}; | ||
return Object.freeze({ | ||
ready: allDone, | ||
finalize: () => { | ||
if (pending === 0) resolveAllDone(); | ||
return allDone; | ||
}, | ||
}); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Instrumentation Overlap Causes Memory LeaksThe |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential bug: The
makeFlushLock
function overwrites the nativecontext.waitUntil
method. Other parts of the code attempting to bind to this new function will fail, causing an "Illegal invocation" error.Description: The
makeFlushLock
function directly mutates the originalExecutionContext
by overwriting the nativewaitUntil
method with a JavaScript wrapper. Elsewhere in the code,context.waitUntil.bind(context)
is called. Attempting to bind the new JavaScript function, which wraps the original native method, breaks thethis
context required by the Cloudflare Workers runtime. This results in aTypeError: Illegal invocation
whenwaitUntil
is called, causing the worker to crash. The removal of thecopyExecutionContext
utility exacerbates this by ensuring multiple handlers operate on the same mutated context object.Suggested fix: Instead of mutating the original
context
object,makeFlushLock
should return a newwaitUntil
function and other related properties. The caller can then use this new object without affecting the global context. Alternatively, restore a mechanism similar to the removedcopyExecutionContext
to provide isolated, correctly-bound contexts to different parts of the application.severity: 0.85, confidence: 0.95
Did we get this right? 👍 / 👎 to inform future reviews.