good_job 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +1 -1
  4. data/engine/app/assets/vendor/rails_ujs.js +747 -0
  5. data/engine/app/controllers/good_job/assets_controller.rb +4 -0
  6. data/engine/app/controllers/good_job/cron_entries_controller.rb +19 -0
  7. data/engine/app/filters/good_job/base_filter.rb +6 -5
  8. data/engine/app/filters/good_job/executions_filter.rb +1 -1
  9. data/engine/app/filters/good_job/jobs_filter.rb +1 -1
  10. data/engine/app/views/good_job/cron_entries/index.html.erb +51 -0
  11. data/engine/app/views/good_job/cron_entries/show.html.erb +4 -0
  12. data/engine/app/views/good_job/{shared/_executions_table.erb → executions/_table.erb} +1 -1
  13. data/engine/app/views/good_job/executions/index.html.erb +1 -1
  14. data/engine/app/views/good_job/{shared/_jobs_table.erb → jobs/_table.erb} +3 -3
  15. data/engine/app/views/good_job/jobs/index.html.erb +1 -1
  16. data/engine/app/views/good_job/jobs/show.html.erb +2 -2
  17. data/engine/app/views/good_job/shared/_filter.erb +9 -10
  18. data/engine/app/views/good_job/shared/icons/_play.html.erb +4 -0
  19. data/engine/app/views/layouts/good_job/base.html.erb +2 -1
  20. data/engine/config/routes.rb +8 -1
  21. data/{engine/app/models → lib}/good_job/active_job_job.rb +0 -0
  22. data/lib/good_job/configuration.rb +1 -1
  23. data/lib/good_job/cron_entry.rb +75 -4
  24. data/lib/good_job/cron_manager.rb +1 -5
  25. data/lib/good_job/current_thread.rb +26 -8
  26. data/lib/good_job/execution.rb +15 -13
  27. data/lib/good_job/version.rb +1 -1
  28. metadata +14 -11
  29. data/engine/app/controllers/good_job/cron_schedules_controller.rb +0 -9
  30. data/engine/app/views/good_job/cron_schedules/index.html.erb +0 -72
@@ -23,6 +23,10 @@ module GoodJob
23
23
  render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartist", "chartist.js")
24
24
  end
25
25
 
26
+ def rails_ujs_js
27
+ render file: GoodJob::Engine.root.join("app", "assets", "vendor", "rails_ujs.js")
28
+ end
29
+
26
30
  def style_css
27
31
  render file: GoodJob::Engine.root.join("app", "assets", "style.css")
28
32
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module GoodJob
3
+ class CronEntriesController < GoodJob::BaseController
4
+ def index
5
+ @cron_entries = CronEntry.all
6
+ end
7
+
8
+ def show
9
+ @cron_entry = CronEntry.find(params[:id])
10
+ @jobs_filter = JobsFilter.new(params, @cron_entry.jobs)
11
+ end
12
+
13
+ def enqueue
14
+ @cron_entry = CronEntry.find(params[:id])
15
+ @cron_entry.enqueue(Time.current)
16
+ redirect_back(fallback_location: cron_entries_path, notice: "Cron entry has been enqueued.")
17
+ end
18
+ end
19
+ end
@@ -3,10 +3,11 @@ module GoodJob
3
3
  class BaseFilter
4
4
  DEFAULT_LIMIT = 25
5
5
 
6
- attr_accessor :params
6
+ attr_accessor :params, :base_query
7
7
 
8
- def initialize(params)
8
+ def initialize(params, base_query = nil)
9
9
  @params = params
10
+ @base_query = base_query || default_base_query
10
11
  end
11
12
 
12
13
  def records
@@ -24,13 +25,13 @@ module GoodJob
24
25
 
25
26
  def job_classes
26
27
  base_query.group("serialized_params->>'job_class'").count
27
- .sort_by { |name, _count| name }
28
+ .sort_by { |name, _count| name.to_s }
28
29
  .to_h
29
30
  end
30
31
 
31
32
  def queues
32
33
  base_query.group(:queue_name).count
33
- .sort_by { |name, _count| name }
34
+ .sort_by { |name, _count| name.to_s }
34
35
  .to_h
35
36
  end
36
37
 
@@ -94,7 +95,7 @@ module GoodJob
94
95
 
95
96
  private
96
97
 
97
- def base_query
98
+ def default_base_query
98
99
  raise NotImplementedError
99
100
  end
100
101
 
@@ -12,7 +12,7 @@ module GoodJob
12
12
 
13
13
  private
14
14
 
15
- def base_query
15
+ def default_base_query
16
16
  GoodJob::Execution.all
17
17
  end
18
18
 
@@ -14,7 +14,7 @@ module GoodJob
14
14
 
15
15
  private
16
16
 
17
- def base_query
17
+ def default_base_query
18
18
  GoodJob::ActiveJobJob.all
19
19
  end
20
20
 
@@ -0,0 +1,51 @@
1
+ <% if @cron_entries.present? %>
2
+ <div class="card my-3">
3
+ <div class="table-responsive">
4
+ <table class="table card-table table-bordered table-hover table-sm mb-0">
5
+ <thead>
6
+ <th>Key</th>
7
+ <th>Schedule</th>
8
+ <th>
9
+ Properties
10
+ <%= tag.button "Toggle", type: "button", class: "btn btn-sm btn-outline-primary", role: "button",
11
+ data: { bs_toggle: "collapse", bs_target: ".cron-entry-properties" },
12
+ aria: { expanded: false, controls: @cron_entries.map { |cron_entry| "##{dom_id(cron_entry, 'properties')}" }.join(" ") }
13
+ %>
14
+ </th>
15
+ <th>Description</th>
16
+ <th>Next scheduled</th>
17
+ <th>Last run</th>
18
+ <th>Actions</th>
19
+ </thead>
20
+ <tbody>
21
+ <% @cron_entries.each do |cron_entry| %>
22
+ <tr id="<%= dom_id(cron_entry) %>">
23
+ <td class="font-monospace"><%= cron_entry.key %></td>
24
+ <td class="font-monospace"><%= cron_entry.schedule %></td>
25
+ <td>
26
+ <%= tag.button("Preview", type: "button", class: "btn btn-sm btn-outline-primary", role: "button",
27
+ data: { bs_toggle: "collapse", bs_target: "##{dom_id(cron_entry, 'properties')}" },
28
+ aria: { expanded: false, controls: dom_id(cron_entry, 'properties') }) %>
29
+ <%= tag.pre(JSON.pretty_generate(cron_entry.display_properties), id: dom_id(cron_entry, 'properties'), class: "collapse cron-entry-properties") %>
30
+ </td>
31
+ <td><%= cron_entry.description %></td>
32
+ <td><%= cron_entry.next_at %></td>
33
+ <td>
34
+ <% if cron_entry.last_job.present? %>
35
+ <%= link_to cron_entry.last_at, cron_entry_path(cron_entry), title: "Job #{cron_entry.last_job.id}" %>
36
+ <% end %>
37
+ </td>
38
+ <td>
39
+ <%= button_to enqueue_cron_entry_path(cron_entry.id), method: :post, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Run cron entry now" }, title: "Run cron entry now", data: { confirm: "Confirm run cron entry now" } do %>
40
+ <%= render "good_job/shared/icons/play" %>
41
+ <% end %>
42
+ </td>
43
+ </tr>
44
+ <% end %>
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+ </div>
49
+ <% else %>
50
+ <em>No cron schedules present.</em>
51
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <h1 class="mb-3">Cron Entry Key: <code><%= @cron_entry.id %></code></h1>
2
+
3
+ <%= render 'good_job/shared/filter', filter: @jobs_filter %>
4
+ <%= render 'good_job/jobs/table', jobs: @jobs_filter.records %>
@@ -44,7 +44,7 @@
44
44
  <%= tag.pre JSON.pretty_generate(execution.serialized_params), id: dom_id(execution, "params"), class: "collapse job-params" %>
45
45
  </td>
46
46
  <td>
47
- <%= button_to execution_path(execution.id), method: :delete, class: "btn btn-sm btn-outline-danger", title: "Delete execution" do %>
47
+ <%= button_to execution_path(execution.id), method: :delete, class: "btn btn-sm btn-outline-danger", title: "Delete execution", data: { confirm: "Confirm delete" } do %>
48
48
  <%= render "good_job/shared/icons/trash" %>
49
49
  <% end %>
50
50
  </td>
@@ -5,7 +5,7 @@
5
5
  <%= render 'good_job/shared/filter', filter: @filter %>
6
6
 
7
7
  <% if @filter.records.present? %>
8
- <%= render 'good_job/shared/executions_table', executions: @filter.records %>
8
+ <%= render 'good_job/executions/table', executions: @filter.records %>
9
9
 
10
10
  <nav aria-label="Job pagination" class="mt-3">
11
11
  <ul class="pagination">
@@ -46,16 +46,16 @@
46
46
  <td>
47
47
  <div class="text-nowrap">
48
48
  <% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
49
- <%= button_to reschedule_job_path(job.id), method: :put, class: "btn btn-sm #{job_reschedulable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_reschedulable, aria: { label: "Reschedule job" }, title: "Reschedule job" do %>
49
+ <%= button_to reschedule_job_path(job.id), method: :put, class: "btn btn-sm #{job_reschedulable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_reschedulable, aria: { label: "Reschedule job" }, title: "Reschedule job", data: { confirm: "Confirm reschedule" } do %>
50
50
  <%= render "good_job/shared/icons/skip_forward" %>
51
51
  <% end %>
52
52
 
53
53
  <% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
54
- <%= button_to discard_job_path(job.id), method: :put, class: "btn btn-sm #{job_discardable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_discardable, aria: { label: "Discard job" }, title: "Discard job" do %>
54
+ <%= button_to discard_job_path(job.id), method: :put, class: "btn btn-sm #{job_discardable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_discardable, aria: { label: "Discard job" }, title: "Discard job", data: { confirm: "Confirm discard" } do %>
55
55
  <%= render "good_job/shared/icons/stop" %>
56
56
  <% end %>
57
57
 
58
- <%= button_to retry_job_path(job.id), method: :put, class: "btn btn-sm #{job.status == :discarded ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: job.status != :discarded, aria: { label: "Retry job" }, title: "Retry job" do %>
58
+ <%= button_to retry_job_path(job.id), method: :put, class: "btn btn-sm #{job.status == :discarded ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: job.status != :discarded, aria: { label: "Retry job" }, title: "Retry job", data: { confirm: "Confirm retry" } do %>
59
59
  <%= render "good_job/shared/icons/arrow_clockwise" %>
60
60
  <% end %>
61
61
  </div>
@@ -5,7 +5,7 @@
5
5
  <%= render 'good_job/shared/filter', filter: @filter %>
6
6
 
7
7
  <% if @filter.records.present? %>
8
- <%= render 'good_job/shared/jobs_table', jobs: @filter.records %>
8
+ <%= render 'good_job/jobs/table', jobs: @filter.records %>
9
9
  <nav aria-label="Job pagination" class="mt-3">
10
10
  <ul class="pagination">
11
11
  <li class="page-item">
@@ -1,3 +1,3 @@
1
- <h1>ActiveJob ID: <code><%= @executions.first.id %></code></h1>
1
+ <h1 class="mb-3">ActiveJob ID: <code><%= @executions.first.id %></code></h1>
2
2
 
3
- <%= render 'good_job/shared/executions_table', executions: @executions %>
3
+ <%= render 'good_job/executions/table', executions: @executions %>
@@ -1,16 +1,15 @@
1
1
  <div class='card mb-2'>
2
2
  <div class='card-body d-flex flex-wrap'>
3
-
4
3
  <div class='me-4'>
5
4
  <small>Filter by job class</small>
6
5
  <br>
7
- <% @filter.job_classes.each do |name, count| %>
6
+ <% filter.job_classes.each do |name, count| %>
8
7
  <% if params[:job_class] == name %>
9
- <%= link_to(@filter.to_params(job_class: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
8
+ <%= link_to(filter.to_params(job_class: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
10
9
  <%= name %> (<%= count %>)
11
10
  <% end %>
12
11
  <% else %>
13
- <%= link_to(@filter.to_params(job_class: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
12
+ <%= link_to(filter.to_params(job_class: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
14
13
  <%= name %> (<%= count %>)
15
14
  <% end %>
16
15
  <% end %>
@@ -20,13 +19,13 @@
20
19
  <div class='me-4'>
21
20
  <small>Filter by state</small>
22
21
  <br>
23
- <% @filter.states.each do |name, count| %>
22
+ <% filter.states.each do |name, count| %>
24
23
  <% if params[:state] == name %>
25
- <%= link_to(@filter.to_params(state: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
24
+ <%= link_to(filter.to_params(state: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
26
25
  <%= name %> (<%= count %>)
27
26
  <% end %>
28
27
  <% else %>
29
- <%= link_to(@filter.to_params(state: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
28
+ <%= link_to(filter.to_params(state: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
30
29
  <%= name %> (<%= count %>)
31
30
  <% end %>
32
31
  <% end %>
@@ -36,13 +35,13 @@
36
35
  <div>
37
36
  <small>Filter by queue</small>
38
37
  <br>
39
- <% @filter.queues.each do |name, count| %>
38
+ <% filter.queues.each do |name, count| %>
40
39
  <% if params[:queue_name] == name %>
41
- <%= link_to(@filter.to_params(queue_name: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
40
+ <%= link_to(filter.to_params(queue_name: nil), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
42
41
  <%= name %> (<%= count %>)
43
42
  <% end %>
44
43
  <% else %>
45
- <%= link_to(@filter.to_params(queue_name: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
44
+ <%= link_to(filter.to_params(queue_name: name), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
46
45
  <%= name %> (<%= count %>)
47
46
  <% end %>
48
47
  <% end %>
@@ -0,0 +1,4 @@
1
+ <!-- https://icons.getbootstrap.com/icons/play/ -->
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play" viewBox="0 0 16 16">
3
+ <path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z" />
4
+ </svg>
@@ -11,6 +11,7 @@
11
11
 
12
12
  <%= javascript_include_tag bootstrap_path(format: :js, v: GoodJob::VERSION) %>
13
13
  <%= javascript_include_tag chartist_path(format: :js, v: GoodJob::VERSION) %>
14
+ <%= javascript_include_tag rails_ujs_path(format: :js, v: GoodJob::VERSION) %>
14
15
  </head>
15
16
  <body>
16
17
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
@@ -29,7 +30,7 @@
29
30
  <%= link_to "All Jobs", jobs_path, class: ["nav-link", ("active" if current_page?(jobs_path))] %>
30
31
  </li>
31
32
  <li class="nav-item">
32
- <%= link_to "Cron Schedules", cron_schedules_path, class: ["nav-link", ("active" if current_page?(cron_schedules_path))] %>
33
+ <%= link_to "Cron Schedules", cron_entries_path, class: ["nav-link", ("active" if current_page?(cron_entries_path))] %>
33
34
  </li>
34
35
  <li class="nav-item">
35
36
  <div class="nav-link">
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  GoodJob::Engine.routes.draw do
3
3
  root to: 'executions#index'
4
- resources :cron_schedules, only: %i[index]
4
+
5
+ resources :cron_entries, only: %i[index show] do
6
+ member do
7
+ post :enqueue
8
+ end
9
+ end
10
+
5
11
  resources :jobs, only: %i[index show] do
6
12
  member do
7
13
  put :discard
@@ -20,6 +26,7 @@ GoodJob::Engine.routes.draw do
20
26
 
21
27
  constraints(format: :js) do
22
28
  get :bootstrap, action: :bootstrap_js
29
+ get :rails_ujs, action: :rails_ujs_js
23
30
  get :chartist, action: :chartist_js
24
31
  end
25
32
  end
@@ -157,7 +157,7 @@ module GoodJob
157
157
  alias enable_cron? enable_cron
158
158
 
159
159
  def cron
160
- env_cron = JSON.parse(ENV['GOOD_JOB_CRON']) if ENV['GOOD_JOB_CRON'].present?
160
+ env_cron = JSON.parse(ENV['GOOD_JOB_CRON'], symbolize_names: true) if ENV['GOOD_JOB_CRON'].present?
161
161
 
162
162
  options[:cron] ||
163
163
  rails_config[:cron] ||
@@ -12,14 +12,29 @@ module GoodJob # :nodoc:
12
12
 
13
13
  attr_reader :params
14
14
 
15
+ def self.all(configuration: nil)
16
+ configuration ||= GoodJob::Configuration.new({})
17
+ configuration.cron_entries
18
+ end
19
+
20
+ def self.find(key, configuration: nil)
21
+ all(configuration: configuration).find { |entry| entry.key == key.to_sym }.tap do |cron_entry|
22
+ raise ActiveRecord::RecordNotFound unless cron_entry
23
+ end
24
+ end
25
+
15
26
  def initialize(params = {})
16
- @params = params.with_indifferent_access
27
+ @params = params
28
+
29
+ raise ArgumentError, "Invalid cron format: '#{cron}'" unless fugit.instance_of?(Fugit::Cron)
17
30
  end
18
31
 
19
32
  def key
20
33
  params.fetch(:key)
21
34
  end
35
+
22
36
  alias id key
37
+ alias to_param key
23
38
 
24
39
  def job_class
25
40
  params.fetch(:class)
@@ -42,16 +57,61 @@ module GoodJob # :nodoc:
42
57
  end
43
58
 
44
59
  def next_at
45
- fugit = Fugit::Cron.parse(cron)
46
60
  fugit.next_time.to_t
47
61
  end
48
62
 
49
- def enqueue
50
- job_class.constantize.set(set_value).perform_later(*args_value)
63
+ def schedule
64
+ fugit.original
65
+ end
66
+
67
+ def fugit
68
+ @_fugit ||= Fugit.parse(cron)
69
+ end
70
+
71
+ def jobs
72
+ GoodJob::ActiveJobJob.where(cron_key: key)
73
+ end
74
+
75
+ def last_at
76
+ return if last_job.blank?
77
+
78
+ if GoodJob::ActiveJobJob.column_names.include?('cron_at')
79
+ (last_job.cron_at || last_job.created_at).localtime
80
+ else
81
+ last_job.created_at
82
+ end
83
+ end
84
+
85
+ def enqueue(cron_at = nil)
86
+ GoodJob::CurrentThread.within do |current_thread|
87
+ current_thread.cron_key = key
88
+ current_thread.cron_at = cron_at
89
+
90
+ job_class.constantize.set(set_value).perform_later(*args_value)
91
+ end
51
92
  rescue ActiveRecord::RecordNotUnique
52
93
  false
53
94
  end
54
95
 
96
+ def last_job
97
+ if GoodJob::ActiveJobJob.column_names.include?('cron_at')
98
+ jobs.order("cron_at DESC NULLS LAST").first
99
+ else
100
+ jobs.order(created_at: :asc).last
101
+ end
102
+ end
103
+
104
+ def display_properties
105
+ {
106
+ key: key,
107
+ class: job_class,
108
+ cron: schedule,
109
+ set: display_property(set),
110
+ args: display_property(args),
111
+ description: display_property(description),
112
+ }
113
+ end
114
+
55
115
  private
56
116
 
57
117
  def set_value
@@ -63,5 +123,16 @@ module GoodJob # :nodoc:
63
123
  value = args || []
64
124
  value.respond_to?(:call) ? value.call : value
65
125
  end
126
+
127
+ def display_property(value)
128
+ case value
129
+ when NilClass
130
+ "None"
131
+ when Proc
132
+ "Lambda/Callable"
133
+ else
134
+ value
135
+ end
136
+ end
66
137
  end
67
138
  end
@@ -89,11 +89,7 @@ module GoodJob # :nodoc:
89
89
  thr_scheduler.create_task(thr_cron_entry)
90
90
 
91
91
  Rails.application.executor.wrap do
92
- CurrentThread.reset
93
- CurrentThread.cron_key = thr_cron_entry.key
94
- CurrentThread.cron_at = thr_cron_at
95
-
96
- cron_entry.enqueue
92
+ cron_entry.enqueue(thr_cron_at)
97
93
  end
98
94
  end
99
95
 
@@ -5,6 +5,15 @@ module GoodJob
5
5
  # Thread-local attributes for passing values from Instrumentation.
6
6
  # (Cannot use ActiveSupport::CurrentAttributes because ActiveJob resets it)
7
7
  module CurrentThread
8
+ # Resettable accessors for thread-local values.
9
+ ACCESSORS = %i[
10
+ cron_at
11
+ cron_key
12
+ error_on_discard
13
+ error_on_retry
14
+ execution
15
+ ].freeze
16
+
8
17
  # @!attribute [rw] cron_at
9
18
  # @!scope class
10
19
  # Cron At
@@ -36,13 +45,20 @@ module GoodJob
36
45
  thread_mattr_accessor :execution
37
46
 
38
47
  # Resets attributes
48
+ # @param [Hash] values to assign
39
49
  # @return [void]
40
- def self.reset
41
- self.cron_at = nil
42
- self.cron_key = nil
43
- self.execution = nil
44
- self.error_on_discard = nil
45
- self.error_on_retry = nil
50
+ def self.reset(values = {})
51
+ ACCESSORS.each do |accessor|
52
+ send("#{accessor}=", values[accessor])
53
+ end
54
+ end
55
+
56
+ # Exports values to hash
57
+ # @return [Hash]
58
+ def self.to_h
59
+ ACCESSORS.each_with_object({}) do |accessor, hash|
60
+ hash[accessor] = send(accessor)
61
+ end
46
62
  end
47
63
 
48
64
  # @return [String] UUID of the currently executing GoodJob::Execution
@@ -60,12 +76,14 @@ module GoodJob
60
76
  (Thread.current.name || Thread.current.object_id).to_s
61
77
  end
62
78
 
79
+ # Wrap the yielded block with CurrentThread values and reset after the block
80
+ # @yield [self]
63
81
  # @return [void]
64
82
  def self.within
65
- reset
83
+ original_values = to_h
66
84
  yield(self)
67
85
  ensure
68
- reset
86
+ reset(original_values)
69
87
  end
70
88
  end
71
89
  end
@@ -309,22 +309,24 @@ module GoodJob
309
309
 
310
310
  # @return [ExecutionResult]
311
311
  def execute
312
- GoodJob::CurrentThread.reset
313
- GoodJob::CurrentThread.execution = self
312
+ GoodJob::CurrentThread.within do |current_thread|
313
+ current_thread.reset
314
+ current_thread.execution = self
314
315
 
315
- # DEPRECATION: Remove deprecated `good_job:` parameter in GoodJob v3
316
- ActiveSupport::Notifications.instrument("perform_job.good_job", { good_job: self, execution: self, process_id: GoodJob::CurrentThread.process_id, thread_name: GoodJob::CurrentThread.thread_name }) do
317
- value = ActiveJob::Base.execute(active_job_data)
316
+ # DEPRECATION: Remove deprecated `good_job:` parameter in GoodJob v3
317
+ ActiveSupport::Notifications.instrument("perform_job.good_job", { good_job: self, execution: self, process_id: current_thread.process_id, thread_name: current_thread.thread_name }) do
318
+ value = ActiveJob::Base.execute(active_job_data)
318
319
 
319
- if value.is_a?(Exception)
320
- handled_error = value
321
- value = nil
322
- end
323
- handled_error ||= GoodJob::CurrentThread.error_on_retry || GoodJob::CurrentThread.error_on_discard
320
+ if value.is_a?(Exception)
321
+ handled_error = value
322
+ value = nil
323
+ end
324
+ handled_error ||= current_thread.error_on_retry || current_thread.error_on_discard
324
325
 
325
- ExecutionResult.new(value: value, handled_error: handled_error)
326
- rescue StandardError => e
327
- ExecutionResult.new(value: nil, unhandled_error: e)
326
+ ExecutionResult.new(value: value, handled_error: handled_error)
327
+ rescue StandardError => e
328
+ ExecutionResult.new(value: nil, unhandled_error: e)
329
+ end
328
330
  end
329
331
  end
330
332
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '2.5.0'
4
+ VERSION = '2.6.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-25 00:00:00.000000000 Z
11
+ date: 2021-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -126,16 +126,16 @@ dependencies:
126
126
  name: capybara
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: 3.35.0
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: 3.35.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: database_cleaner
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -351,27 +351,29 @@ files:
351
351
  - engine/app/assets/vendor/bootstrap/bootstrap.min.css
352
352
  - engine/app/assets/vendor/chartist/chartist.css
353
353
  - engine/app/assets/vendor/chartist/chartist.js
354
+ - engine/app/assets/vendor/rails_ujs.js
354
355
  - engine/app/controllers/good_job/assets_controller.rb
355
356
  - engine/app/controllers/good_job/base_controller.rb
356
- - engine/app/controllers/good_job/cron_schedules_controller.rb
357
+ - engine/app/controllers/good_job/cron_entries_controller.rb
357
358
  - engine/app/controllers/good_job/executions_controller.rb
358
359
  - engine/app/controllers/good_job/jobs_controller.rb
359
360
  - engine/app/filters/good_job/base_filter.rb
360
361
  - engine/app/filters/good_job/executions_filter.rb
361
362
  - engine/app/filters/good_job/jobs_filter.rb
362
363
  - engine/app/helpers/good_job/application_helper.rb
363
- - engine/app/models/good_job/active_job_job.rb
364
- - engine/app/views/good_job/cron_schedules/index.html.erb
364
+ - engine/app/views/good_job/cron_entries/index.html.erb
365
+ - engine/app/views/good_job/cron_entries/show.html.erb
366
+ - engine/app/views/good_job/executions/_table.erb
365
367
  - engine/app/views/good_job/executions/index.html.erb
368
+ - engine/app/views/good_job/jobs/_table.erb
366
369
  - engine/app/views/good_job/jobs/index.html.erb
367
370
  - engine/app/views/good_job/jobs/show.html.erb
368
371
  - engine/app/views/good_job/shared/_chart.erb
369
- - engine/app/views/good_job/shared/_executions_table.erb
370
372
  - engine/app/views/good_job/shared/_filter.erb
371
- - engine/app/views/good_job/shared/_jobs_table.erb
372
373
  - engine/app/views/good_job/shared/icons/_arrow_clockwise.html.erb
373
374
  - engine/app/views/good_job/shared/icons/_check.html.erb
374
375
  - engine/app/views/good_job/shared/icons/_exclamation.html.erb
376
+ - engine/app/views/good_job/shared/icons/_play.html.erb
375
377
  - engine/app/views/good_job/shared/icons/_skip_forward.html.erb
376
378
  - engine/app/views/good_job/shared/icons/_stop.html.erb
377
379
  - engine/app/views/good_job/shared/icons/_trash.html.erb
@@ -389,6 +391,7 @@ files:
389
391
  - lib/good_job.rb
390
392
  - lib/good_job/active_job_extensions.rb
391
393
  - lib/good_job/active_job_extensions/concurrency.rb
394
+ - lib/good_job/active_job_job.rb
392
395
  - lib/good_job/adapter.rb
393
396
  - lib/good_job/cli.rb
394
397
  - lib/good_job/configuration.rb
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
- module GoodJob
3
- class CronSchedulesController < GoodJob::BaseController
4
- def index
5
- configuration = GoodJob::Configuration.new({})
6
- @cron_entries = configuration.cron_entries
7
- end
8
- end
9
- end