Skip to content
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

[16.0][IMP] queue_job: remove dead jobs requeuer cron and automatically requeue dead jobs #716

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from

Conversation

AnizR
Copy link

@AnizR AnizR commented Dec 6, 2024

Goal

Automatically re-queue jobs that have been started but whose worker have been killed.
And rely on Odoo's limit_time_cpu and limit_time_real for job execution.

Technical explanation

Everything relies on a new table queue_job_locks which contains ids of jobs that have been started.
When a job is executed, its row queue_job_locks is locked.

If a row is in queue_job_locks with a state='started' but not locked, it is either:

  • a job killed
  • a job not yet started (happens in a very small time frame)

Using this information, we can re-queue these jobs.

Why not lock directly in the `queue_job' table?

This was tried in #423 but it wasn't working when a job was raising an error.
It seems that the row was locked and it tried to write on the row to set as failed before committing.

Improve current behavior

Re-queue jobs that have been killed but increment their 'retries' to avoid having a job that is always get killed in infinite re-queuing.

@OCA-git-bot
Copy link
Contributor

Hi @guewen,
some modules you are maintaining are being modified, check this out!

@AnizR AnizR changed the title [IMP] queue_job: remove cron garbage collector and automatically requeue jobs in timeout [16.0][IMP] queue_job: remove cron garbage collector and automatically requeue jobs in timeout Dec 6, 2024
Copy link
Member

@sbidoul sbidoul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very promising!

A few thoughts:

  • There is a Caveat comment in runner.py that needs updating.
  • This should handle the enqueued state too, which is the state when the runner has decided that a jobs needs to run but then /queue_job/runjob controller has not set it started yet. This state normally exists for a very short time, but I have seen situations where the workers are overloaded and take time to accept /queue_job/runjob requests then die, leaving jobs in enqueued state forever.
  • Since there are two race conditions between enqueued and started, and between started and the time the job transaction actually starts with the lock, I wonder if we should not introduce a small elapsed time condition (10s?) in reset_dead_jobs. May be based on date_enqueued.

queue_job/readme/CONFIGURE.rst Outdated Show resolved Hide resolved
@AnizR AnizR marked this pull request as ready for review December 6, 2024 14:09
@AnizR
Copy link
Author

AnizR commented Dec 6, 2024

This looks very promising!

A few thoughts:

* There is a Caveat comment in `runner.py` that needs updating.

* This should handle the `enqueued` state too, which is the state when the runner has decided that a jobs needs to run but then `/queue_job/runjob` controller has not set it started yet. This state normally exists for a very short time, but I have seen situations where the workers are overloaded and take time to accept `/queue_job/runjob` requests then die, leaving jobs in `enqueued` state forever.

* Since there are two race conditions between `enqueued` and `started`, and between `started` and the time the job transaction actually starts with the lock, I wonder if we should not introduce a small elapsed time condition (10s?) in `reset_dead_jobs`. May be based on `date_enqueued`.

Thank you for your suggestions. I have implemented the necessary corrections.
While I have not encountered a case where a job is left in the 'enqueued' state, I have made the appropriate correction to ensure the code is more robust.

Copy link
Member

@sbidoul sbidoul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more minor comments.

queue_job/__manifest__.py Outdated Show resolved Hide resolved
queue_job/controllers/main.py Outdated Show resolved Hide resolved
queue_job/job.py Show resolved Hide resolved
queue_job/job.py Outdated Show resolved Hide resolved
queue_job/jobrunner/runner.py Outdated Show resolved Hide resolved
queue_job/jobrunner/runner.py Outdated Show resolved Hide resolved
queue_job/jobrunner/runner.py Show resolved Hide resolved
@sbidoul sbidoul changed the title [16.0][IMP] queue_job: remove cron garbage collector and automatically requeue jobs in timeout [16.0][IMP] queue_job: remove dead jobs requeuer cron and automatically requeue jobs in timeout Dec 6, 2024
@sbidoul sbidoul changed the title [16.0][IMP] queue_job: remove dead jobs requeuer cron and automatically requeue jobs in timeout [16.0][IMP] queue_job: remove dead jobs requeuer cron and automatically requeue dead jobs Dec 6, 2024
queue_job/job.py Outdated Show resolved Hide resolved
queue_job/migrations/16.0.2.6.9/pre-migration.py Outdated Show resolved Hide resolved
queue_job/migrations/16.0.2.6.9/pre-migration.py Outdated Show resolved Hide resolved
@AnizR AnizR force-pushed the zra-imp-timeout2 branch 2 times, most recently from f98c856 to 8edf042 Compare December 9, 2024 15:56
Copy link
Member

@guewen guewen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this old issue, I like this elegant solution. It should be quite optimized also. Congrats for this work

@@ -1,17 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record id="ir_cron_queue_job_garbage_collector" model="ir.cron">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this become

<delete id="ir_cron_queue_job_garbage_collector" model="ir.cron"/>

to clean up upgrades / avoid filling cron logs with errors since requeue_stuck_jobs method is gone?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have archived the cron in the pre-migration.py. Therefore, there won't be any error.
I always prefer to archive (set active to false) rather than deleting.

@sbidoul
Copy link
Member

sbidoul commented Dec 11, 2024

@AnizR I think we can also remove the set_job_pending function, as the new mechanism will take care of that part.

@AnizR
Copy link
Author

AnizR commented Dec 13, 2024

@AnizR I think we can also remove the set_job_pending function, as the new mechanism will take care of that part.

Yes, jobs that have not been started will be re-queued by my new mechanism.
Removing this part will provide a more "uniform" process of re-queuing jobs.

…eue jobs in timeout

[IMP] queue_job: increment 'retry' when re-queuing job that have been killed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants