-
Description:When a long job has a specific timeout, then no exception is thrown. There is only an exception if the job doesn't have a timeout but for example Horizon has a timeout. Therefore if you say a job can only have maximum 1 exception but can try 10 times but the timeout for one job run is 100s, then it will try 10 times for 100s every time. I expect an exception to be thrown because all the retries will fail because of the timeout for this long job. Real life example: When using cache locks in job to release a job, the lock can't be released because there's no exception and the "failed" method is not called so you can't cleanup the lock. The second try for the job, the lock is still set but you can retrieve it anymore because that retried job isn't the owner. Therefore job will still retry x amount of times, then fails, and then forceReleased the lock. Not the expected behaviour. Steps To Reproduce:
I guess this is a bug, because the failed job will never be successful for the timeout that has been set to the job. Now the function I would expect the same behaviour as when Horizon-process has been killed by the specified timeout of the worker. Then the default Laravel behaviour is working fine. If wanted, I can submit a PR with a proposal. |
Beta Was this translation helpful? Give feedback.
Replies: 13 comments 9 replies
-
So... what were you expecting to happen? I'm not clear on that. Were you expecting it to only attempt once because of "maximum exceptions"? |
Beta Was this translation helpful? Give feedback.
-
Not clear what you expect here. You want to consider a job timeout as an exception and fail right away since you have maxExceptions=1? |
Beta Was this translation helpful? Give feedback.
-
Sorry for the misunderstanding. The expectation was the same behaviour like hitting the timeout only in horizon/queue command. There it will fail after one long attempt that is hitting the timeout of the process. So yes, failing because of the maxExceptions=1. The
But the behaviour is different in the end. When horizon kills the process, you get the wanted exception right after hitting the timeout (so no additional retries because of the maxExceptions variable set to 1) and the failed method on the job is called (when it exists). The latter isn't happen when set a timeout on the job that is smaller then horizon timeout (like advised in the documentation). |
Beta Was this translation helpful? Give feedback.
-
Sorry I still don't understand. What do you mean by the Horizon timeout? What is the bug here? Is it that the job retries while you have maxExceptions=1? |
Beta Was this translation helpful? Give feedback.
-
In Horizon you can set a timeout for the supervisor. If no job timeout is specified, the timeout set by the worker (Horizon) is used in the function In my opinion instead of calling the In the documentation https://laravel.com/docs/7.x/queues#cleaning-up-after-failed-jobs :
Problem is the "cleanup" can only be done after the amount of retries in case of a timeout due to job timeout. If it's "work as intended". How can you release a cache-lock if the job is running too long, so it goes in timeout. Without waiting to al its retries happened (because maxExceptions is not taken into account for a timeout) |
Beta Was this translation helpful? Give feedback.
-
The |
Beta Was this translation helpful? Give feedback.
-
Why is there then a change in behaviour if no timeout is set? When the supervisor kills the process by hitting the timeout, a retry isn't happen. Can you give an example for the cache lock. Our cache lock hasn't an expire time. We use it to process the jobs in sync for specific client and release it to the queue if lock is already used by other job. But when the job with the lock hits its own timeout, then retries can't require the lock. This is also not wanted because the job hits the timout once, and will timeout all the other times too. How can this be managed? If timeout happend, it shouldn't retry again and use resources. |
Beta Was this translation helpful? Give feedback.
-
I think you're confusing things. I suggest you try post a sample code on the forums and see if people can help explain what's going on in your job. As for Horizon, the timeout works the same as in a regular worker. When a timeout happens the worker will exit but the job is still in queue and is going to be retried if you have tries available. |
Beta Was this translation helpful? Give feedback.
-
It would be a pretty huge change of behavior for us to start calling failed() for every timeout? We have never before called But, I'm not sure if I'm even understanding what you want. Is that what you are wanting? For the |
Beta Was this translation helpful? Give feedback.
-
Converting to discussion pending inactivity. |
Beta Was this translation helpful? Give feedback.
-
Correct, that was a misunderstanding in the tests we tried.
No, that's not the expecting result. When the job fails, it only has to fail once. What we're expecting on the other hand is that the job can fail when there's a timeout. Most of the time, you will catch timeout exceptions for requests to 3rd parties (through Guzzle for example). The timeout of the job is always greater than those timeouts so a retry isn't wanted here. Couple of possible solutions:
Best solution: new function
|
Beta Was this translation helpful? Give feedback.
-
You're using a lock that never expires! Not sure why you're doing so but this is very dangerous. There's no guarantee that any code will run that will release the lock. Your locks should auto expire after a decent amount of time based on how you design your jobs to run. |
Beta Was this translation helpful? Give feedback.
-
Handled in #33521 |
Beta Was this translation helpful? Give feedback.
Handled in #33521