Skip to content

How to safely re-enqueue an aborted job? #485

Open

Description

@sashkent3

I need to perform something similar to:

await Job("id", pool).abort()
await pool.enqueue_job("func", _job_id="id")

However, sometimes this can lead to the abort of the freshly enqueued job. From my observations, this always happens if the aborted job is not found. Waiting until a key in the abort queue expires (1 minute, not configurable) seems to help. My questions are then:

  1. Is waiting for arq.constants.abort_job_max_age guaranteed to be enough for the freshly enqueued job to not be aborted?
  2. Is it possible to not abort a job if it's not found? Simply checking the job.status() is a race condition.

Activity

  1. sashkent3 commented on Nov 19, 2024

    @sashkent3
    Author

    I believe I've found the culprit of my problem. Calling await Job("id", pool).abort() isn't ever safe. If the job isn't found, the specified job_id will remain in the abort_jobs_ss until a job with the specified id is run. At that point, the job will be "aborted before start".
    The comment here is incorrect. Items in the abort_jobs_ss older than abort_job_max_age are not deleted. The line here seems rather confusing. The worker removes items from the abort_jobs_ss which are abort_job_max_age (60 ms) in the future. Such items can only appear if the Job.abort was called immediately after the above line but before the pipeline is executed.
    If the only intended purpose here was to deliver on the abort_job_max_age comment's promise, the line should probably look like this:

    pipe.zremrangebyscore(abort_jobs_ss, min=0, max=timestamp_ms() - abort_job_max_age)
    

    I'm willing to submit a PR if the issue is confirmed and the proposed resolution is accepted by the maintainers.
    Also, it seems like the value of the abort_job_max_age constant was specified in milliseconds by mistake, and the 60-second max-age was intended.

  2. drizzt commented on Nov 23, 2024

    @drizzt

    hi, did you see if your line fixes the problem?

  3. sashkent3 commented on Nov 23, 2024

    @sashkent3
    Author

    hi, did you see if your line fixes the problem?

    I did very limited testing so take it for what it's worth. But yes, the fix seems to be working for me.

  4. SteniMariyaThomas commented on Dec 26, 2024

    @SteniMariyaThomas

    @sashkent3 The enqueued job always be in queue until it taken for execution. Then how will it be not found while aborting.

    Can you explain the scenario in which the job is not found

  5. sashkent3 commented on Dec 26, 2024

    @sashkent3
    Author

    @SteniMariyaThomas well, nothing prevents the user from running await Job("id", pool).abort() while there's no job with the id "id". For example, this could be a first command on a fresh (empty) queue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions