Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

No supported way to cancel a job that is already executing!

オープン
#806 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
機能追加
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
ruby
領域
backend, databases

調査の方向性

Look at the SolidQueue::ClaimedExecution class and its discard method that raises UndiscardableError. Understand how jobs are claimed and finalized. The goal is to design a way to signal cancellation to a running job, perhaps by adding a flag or a cooperative check, and to allow discard to work on executing jobs. Review the existing job lifecycle and the finalize method's logic.

索引モデルが issue の本文から書いたものです。

説明

Summary

SolidQueue supports cancelling a queued (ready/scheduled) job cleanly via job.discard (as clarified in #395). But there is no supported way to cancel a job that is already executing (claimed) — ClaimedExecution#discard explicitly raises:

def discard
  raise UndiscardableError, "Can't discard a job in progress"
end

In Quepid we have very long "LLM as a judge" type jobs taht could run for many many minutes or hours... And you might say "oh, crap, it's not what I want" and then it's awkward. We wrote a bunch of janky code to support this.

Image

Current behavior

Applications that want a user-facing "Cancel" button for a long-running job (ours: an AI judging run scoped to one book+judge, potentially processing hundreds of records) have no sanctioned way to request cancellation of an already-claimed job. Our workaround bypasses the guard directly:

def self.cancel book, judge
  active_for(book, judge).each do |job|
    if job.claimed_execution.present?
      # Job is actively running — force destroy it. The job's own #perform
      # loop checks for its own SolidQueue row on every iteration and stops
      # as soon as it notices this row is gone.
      job.claimed_execution.destroy
      job.destroy
    else
      job.discard
    end
  end
end

This only works because ClaimedExecution#finalize's unless_already_finalized check (self.class.unscoped.lock.find_by(id: id)) happens to tolerate the claimed_execution row already being gone by the time the job actually finishes — but that's an internal implementation detail we're relying on, not a documented contract, and it could change between versions without notice.

It also means the running job's #perform never gets any signal that cancellation was requested other than a self-written polling loop:

cancellable = SolidQueue::Job.exists?(active_job_id: job_id)
loop do
  break if cancellable && !SolidQueue::Job.exists?(active_job_id: job_id)
  # ... do one unit of work ...
end

There's no cooperative "cancellation requested" flag to check cheaply, and no built-in helper for this pattern either — every app doing cooperative cancellation re-derives the same polling idiom.

Why this belongs in SolidQueue, not application code

ClaimedExecution, #finalize, and the UndiscardableError guard are all internal to SolidQueue; there's no supported extension point for "cancel this specific already-running job" without reaching past that guard into internals that could change between versions.

Related

#395 covers cancelling a scheduled (not-yet-executing) job via discard — this issue is specifically about the claimed/executing case, which that thread doesn't touch.

主要言語
Ruby
スター
2.5k
フォーク
250
平均マージ
8時間 31分
マージ済み PR(30日)
5

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

rails/solid_queue のほかの issue

rails/solid_queue の issue をすべて見る

似ている issue

Ruby の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。