Closed
Description
Version
1.5.0
Short overview
Extracted from #173
Issue occurs on
- Virtual machine
- Docker container
- Dev/Host system
Detailed error description
I was trying to debug this case to find the cause, I did not find it but found another related bug with screen.waitFor
, the waitFor
uses this utility, which does not clear the interval correctly if the max timeout is reached before getting the result of the action()
.
this is the flow:
- you call this function, it creates a timer with the maxDuration set
- the first
action()
call happens - if somehow the
action()
takes a lot to resolve and the time spent is longer than maxDuration then the maxTimeout callback will be called, which will finish the promise (in this case with a reject) - now
action()
finished, let's say that it ended rejected, so the code will go to here which creates a new timer, and if somehow theaction()
continues to be rejected, it will basically create an interval that continues to be executing, which basically will prevent the node process to exit.
maybe something similar is happening in the files related to the OpenCV
Steps to reproduce error
Additional content
Please provide any (mandatory) additional data to reproduce the error (Dockerfiles etc.)
here is basically the code needed to fix this case in util/poll-action.function.ts
, not sure if you want me to send a PR
export function timeout<R>(updateIntervalMs: number, maxDurationMs: number, action: (...params: any) => Promise<R>): Promise<R> {
return new Promise<R>((resolve, reject) => {
let interval: NodeJS.Timeout;
let isDone = false;
const maxTimeout = setTimeout(
() => {
isDone = true;
clearTimeout(maxTimeout);
if (interval) {
clearTimeout(interval);
}
reject(`Action timed out after ${maxDurationMs} ms`);
},
maxDurationMs
);
const startInterval = () => {
interval = setTimeout(function intervalFunc() {
action().then((result) => {
if (isDone) {
return;
}
if (!result) {
interval = setTimeout(intervalFunc, updateIntervalMs);
} else {
isDone = true;
clearTimeout(maxTimeout);
clearTimeout(interval);
resolve(result);
}
}).catch(() => {
if (isDone) {
return;
}
interval = setTimeout(intervalFunc, updateIntervalMs);
});
}, updateIntervalMs);
};
action().then((result) => {
if (isDone) {
return;
}
if (!result) {
startInterval();
} else {
isDone = true;
clearTimeout(maxTimeout);
resolve(result);
}
}).catch(() => {
if (isDone) {
return;
}
startInterval();
});
});
}
Metadata
Assignees
Labels
No labels