-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
feat(core): Cancel runner task on timeout in external mode #12101
feat(core): Cancel runner task on timeout in external mode #12101
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
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.
Couple changes I'd like to see. Also, we should add N8N_RUNNERS_TASK_TIMEOUT
to docker/images/n8n/n8n-task-runners.json
const vmResult = (await runInNewContext( | ||
`globalThis.global = globalThis; module.exports = async function VmCodeWrapper() {${settings.code}\n}()`, | ||
context, | ||
)) as TaskResultData['result']; |
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.
Although it doesn't cover all cases, we could pass the timeout param to the runInNewContext
. That way it would get canceled eventually as well. Same for runForEachItem
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.
Today I learned 🙏🏻
context, | ||
)) as INodeExecutionData | undefined; | ||
let result = await new Promise<INodeExecutionData | undefined>((resolve, reject) => { | ||
signal.addEventListener( |
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.
Since this runs in a loop, we are adding a new event listener on each iteration, and it could be a thousand of these. I think it would be good in this case to remove the event listener once we are done. Also then we don't get these warnings:
2024/12/10 10:09:30 ERROR [Runner] (node:28928) MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal]. MaxListeners is 10. Use events.setMaxListeners() to increase limit
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.
Interesting, I thought this was covered by { once: true }
Edit: once
removes the listener only if called.
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.
Looking good now, one small comment 👍
@@ -89,4 +89,65 @@ describe('TestRunner', () => { | |||
).toThrowError(/Invalid URL/); | |||
}); | |||
}); | |||
|
|||
describe('taskCancelled', () => { |
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.
👌
@@ -298,6 +300,20 @@ export abstract class TaskRunner extends EventEmitter { | |||
} | |||
task.cancelled = true; | |||
|
|||
for (const [requestId, request] of this.dataRequests.entries()) { | |||
if (request.taskId === taskId) { | |||
request.reject(new ApplicationError('Task cancelled')); |
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.
We receive a cancellation reason in the message. We could include that here. Also could use some more fine grained error than generic ApplicationError
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.
|
||
for (const [requestId, request] of this.nodeTypesRequests.entries()) { | ||
if (request.taskId === taskId) { | ||
request.reject(new ApplicationError('Task cancelled')); |
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.
Same here
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.
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.
Thank you for addressing the feedback 💘
n8n Run #8265
Run Properties:
|
Project |
n8n
|
Branch Review |
cat-405-task-that-times-out-is-left-running-on-task-runner
|
Run status |
Passed #8265
|
Run duration | 04m 28s |
Commit |
ffaba80f79: 🌳 🖥️ browsers:node18.12.0-chrome107 🤖 ivov 🗃️ e2e/*
|
Committer | Iván Ovejero |
View all properties for this run ↗︎ |
Test results | |
---|---|
Failures |
0
|
Flaky |
0
|
Pending |
0
|
Skipped |
0
|
Passing |
480
|
View all changes introduced in this branch ↗︎ |
✅ All Cypress E2E specs passed |
Got released with |
https://linear.app/n8n/issue/CAT-405