Skip to content

Commit

Permalink
wip: force discard jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
jgrau committed Sep 13, 2023
1 parent 3c45787 commit 704d90c
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 24 deletions.
7 changes: 7 additions & 0 deletions app/controllers/good_job/jobs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class JobsController < GoodJob::ApplicationController

ACTIONS = {
discard: "discarded",
force_discard: "force discarded",
reschedule: "rescheduled",
retry: "retried",
destroy: "destroyed",
Expand Down Expand Up @@ -66,6 +67,12 @@ def discard
redirect_back(fallback_location: jobs_path, notice: t(".notice"))
end

def force_discard
@job = Job.find(params[:id])
@job.force_discard_job(DISCARD_MESSAGE)
redirect_back(fallback_location: jobs_path, notice: t(".notice"))
end

def reschedule
@job = Job.find(params[:id])
@job.reschedule_job
Expand Down
56 changes: 33 additions & 23 deletions app/models/good_job/job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -215,32 +215,14 @@ def retry_job
# @return [void]
def discard_job(message)
with_advisory_lock do
execution = head_execution(reload: true)
active_job = execution.active_job(ignore_deserialization_errors: true)

raise ActionForStateMismatchError if execution.finished_at.present?

job_error = GoodJob::Job::DiscardJobError.new(message)

update_execution = proc do
execution.update(
{
finished_at: Time.current,
error: GoodJob::Execution.format_error(job_error),
}.tap do |attrs|
attrs[:error_event] = ERROR_EVENT_DISCARDED if self.class.error_event_migrated?
end
)
end

if active_job.respond_to?(:instrument)
active_job.send :instrument, :discard, error: job_error, &update_execution
else
update_execution.call
end
_discard_job(message)
end
end

def force_discard_job(message)
_discard_job(message)
end

# Reschedule a scheduled job so that it executes immediately (or later) by the next available execution thread.
# @param scheduled_at [DateTime, Time] When to reschedule the job
# @return [void]
Expand Down Expand Up @@ -277,5 +259,33 @@ def _execution_id
def _head?
_execution_id == head_execution(reload: true).id
end

private

def _discard_job(message)
execution = head_execution(reload: true)
active_job = execution.active_job(ignore_deserialization_errors: true)

raise ActionForStateMismatchError if execution.finished_at.present?

job_error = GoodJob::Job::DiscardJobError.new(message)

update_execution = proc do
execution.update(
{
finished_at: Time.current,
error: GoodJob::Execution.format_error(job_error),
}.tap do |attrs|
attrs[:error_event] = ERROR_EVENT_DISCARDED if self.class.error_event_migrated?
end
)
end

if active_job.respond_to?(:instrument)
active_job.send :instrument, :discard, error: job_error, &update_execution
else
update_execution.call
end
end
end
end
7 changes: 7 additions & 0 deletions app/views/good_job/jobs/_table.erb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@
<%=t "good_job.actions.discard" %>
<% end %>
</li>
<li>
<% job_discardable = job.status.in? [:running] %>
<%= link_to force_discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t("good_job.jobs.actions.discard"), data: { confirm: t("good_job.jobs.actions.confirm_discard"), disable: true } do %>
<%= render "good_job/shared/icons/eject" %>
<%=t "good_job.actions.force_discard" %>
<% end %>
</li>
<li>
<%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { confirm: t("good_job.jobs.actions.confirm_retry"), disable: true } do %>
<%= render "good_job/shared/icons/arrow_clockwise" %>
Expand Down
4 changes: 4 additions & 0 deletions app/views/good_job/shared/icons/_eject.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- https://icons.getbootstrap.com/icons/eject/ -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eject" viewBox="0 0 16 16">
<path d="M7.27 1.047a1 1 0 0 1 1.46 0l6.345 6.77c.6.638.146 1.683-.73 1.683H1.656C.78 9.5.326 8.455.926 7.816L7.27 1.047zM14.346 8.5 8 1.731 1.654 8.5h12.692zM.5 11.5a1 1 0 0 1 1-1h13a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1v-1zm14 0h-13v1h13v-1z"/>
</svg>
5 changes: 4 additions & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ en:
actions:
destroy: Destroy
discard: Discard
force_discard: Force Discard
inspect: Inspect
reschedule: Reschedule
retry: Retry
Expand Down Expand Up @@ -120,6 +121,8 @@ en:
notice: Job has been destroyed
discard:
notice: Job has been discarded
force_discard:
notice: Job has been discarded
executions:
in_queue: in queue
runtime: runtime
Expand Down Expand Up @@ -188,7 +191,7 @@ en:
quadrillion: Q
thousand: K
trillion: T
unit: ''
unit: ""
processes:
index:
no_good_job_processes_found: No GoodJob processes found.
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

member do
put :discard
put :force_discard
put :reschedule
put :retry
end
Expand Down
1 change: 1 addition & 0 deletions spec/test_app/app/jobs/example_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def perform(batch, params)
end

def perform(type = SUCCESS_TYPE)
sleep(25)
if type == SUCCESS_TYPE
true
elsif type == ERROR_ONCE_TYPE
Expand Down

0 comments on commit 704d90c

Please sign in to comment.