mission_control-jobs 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -9
  3. data/app/controllers/concerns/mission_control/jobs/adapter_features.rb +10 -6
  4. data/app/controllers/concerns/mission_control/jobs/failed_jobs_bulk_operations.rb +1 -1
  5. data/app/controllers/concerns/mission_control/jobs/not_found_redirections.rb +9 -1
  6. data/app/controllers/concerns/mission_control/jobs/queue_scoped.rb +1 -1
  7. data/app/controllers/mission_control/jobs/bulk_discards_controller.rb +1 -1
  8. data/app/controllers/mission_control/jobs/discards_controller.rb +1 -1
  9. data/app/controllers/mission_control/jobs/dispatches_controller.rb +13 -0
  10. data/app/controllers/mission_control/jobs/jobs_controller.rb +3 -3
  11. data/app/controllers/mission_control/jobs/queues_controller.rb +4 -4
  12. data/app/controllers/mission_control/jobs/recurring_tasks_controller.rb +23 -0
  13. data/app/controllers/mission_control/jobs/retries_controller.rb +1 -1
  14. data/app/controllers/mission_control/jobs/workers_controller.rb +6 -1
  15. data/app/helpers/mission_control/jobs/jobs_helper.rb +6 -2
  16. data/app/helpers/mission_control/jobs/navigation_helper.rb +2 -1
  17. data/app/models/mission_control/jobs/page.rb +8 -8
  18. data/app/models/mission_control/jobs/recurring_task.rb +17 -0
  19. data/app/views/layouts/mission_control/jobs/_application_selection.html.erb +1 -1
  20. data/app/views/mission_control/jobs/jobs/_error_information.html.erb +0 -1
  21. data/app/views/mission_control/jobs/jobs/_general_information.html.erb +1 -1
  22. data/app/views/mission_control/jobs/jobs/_jobs_page.html.erb +8 -10
  23. data/app/views/mission_control/jobs/jobs/_title.html.erb +3 -0
  24. data/app/views/mission_control/jobs/jobs/blocked/_actions.html.erb +3 -0
  25. data/app/views/mission_control/jobs/jobs/blocked/_job.html.erb +3 -0
  26. data/app/views/mission_control/jobs/jobs/index.html.erb +2 -2
  27. data/app/views/mission_control/jobs/jobs/scheduled/_actions.html.erb +4 -0
  28. data/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb +4 -1
  29. data/app/views/mission_control/jobs/queues/_queue_title.html.erb +1 -1
  30. data/app/views/mission_control/jobs/queues/show.html.erb +2 -2
  31. data/app/views/mission_control/jobs/recurring_tasks/_general_information.html.erb +16 -0
  32. data/app/views/mission_control/jobs/recurring_tasks/_recurring_task.html.erb +14 -0
  33. data/app/views/mission_control/jobs/recurring_tasks/_title.html.erb +7 -0
  34. data/app/views/mission_control/jobs/recurring_tasks/index.html.erb +16 -0
  35. data/app/views/mission_control/jobs/recurring_tasks/show.html.erb +14 -0
  36. data/app/views/mission_control/jobs/{workers → shared}/_job.html.erb +8 -1
  37. data/app/views/mission_control/jobs/shared/_jobs.html.erb +14 -0
  38. data/app/views/mission_control/jobs/shared/_pagination_toolbar.html.erb +3 -3
  39. data/app/views/mission_control/jobs/workers/_workers_page.html.erb +15 -0
  40. data/app/views/mission_control/jobs/workers/index.html.erb +2 -13
  41. data/app/views/mission_control/jobs/workers/show.html.erb +9 -2
  42. data/config/routes.rb +2 -2
  43. data/lib/active_job/executing.rb +3 -6
  44. data/lib/active_job/failed.rb +0 -4
  45. data/lib/active_job/job_proxy.rb +6 -0
  46. data/lib/active_job/jobs_relation.rb +17 -6
  47. data/lib/active_job/queue_adapters/resque_ext.rb +1 -1
  48. data/lib/active_job/queue_adapters/solid_queue_ext/recurring_tasks.rb +43 -0
  49. data/lib/active_job/queue_adapters/solid_queue_ext/workers.rb +41 -0
  50. data/lib/active_job/queue_adapters/solid_queue_ext.rb +51 -55
  51. data/lib/mission_control/jobs/adapter.rb +67 -19
  52. data/lib/mission_control/jobs/console/helpers.rb +1 -1
  53. data/lib/mission_control/jobs/engine.rb +13 -3
  54. data/lib/mission_control/jobs/server/recurring_tasks.rb +15 -0
  55. data/lib/mission_control/jobs/server/serializable.rb +1 -1
  56. data/lib/mission_control/jobs/server/workers.rb +3 -5
  57. data/lib/mission_control/jobs/server.rb +1 -1
  58. data/lib/mission_control/jobs/version.rb +1 -1
  59. data/lib/mission_control/jobs/workers_relation.rb +78 -0
  60. data/lib/mission_control/jobs.rb +3 -0
  61. metadata +19 -6
  62. data/app/jobs/mission_control/jobs/application_job.rb +0 -6
  63. data/app/mailers/mission_control/jobs/application_mailer.rb +0 -8
  64. data/app/views/mission_control/jobs/workers/_jobs.html.erb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c261d6b55b908312495212d5f925b3b4150f59a895b185a5667ce0b9754f9f6
4
- data.tar.gz: db330e0f62f17e8b3e46f63233b8f7fffe5a126f746b7d83bc3afa94c9e07664
3
+ metadata.gz: 8ea81c77ce22c040d30fc8246943945d526a85d1999b0cad6120d59b2a8adeda
4
+ data.tar.gz: c26e71001519a3cb2326b20eff4d634e180d81b9c334cc7a41ca2148ecfa610c
5
5
  SHA512:
6
- metadata.gz: 670df5d56e857f5f9b230c884447738763379c803be0014933016554277463bcaf9aa74c0e52289cf3c54783f74ed16fc13338637e8d78b70b1bfd82ffa7849c
7
- data.tar.gz: cad6605c7296b828d1078ef09def60152267dc3d07196481a51f1b5f49cec70b5a0b0b9b8fcc1add4739d28bf8ad6b38c7a62197111c0c047a5771ce1504cc4a
6
+ metadata.gz: 611f367a1baab8aa025f761abbd9bf6e10cc60ab9c4475d7487eea37e54d9b95e63bd87999d96a018586d198ee59a1635b237756d17480efc255895cdf144059
7
+ data.tar.gz: 5b958d96eb931ff86b0fe98ac437a6d1a4c87c2c9cc6363845ad35082317ab2b0de9566ad22e791831d0e2385172659df42ad2db27bac8cc5bc60646d8cc1029
data/README.md CHANGED
@@ -54,6 +54,8 @@ Besides `base_controller_class`, you can also set the following for `MissionCont
54
54
  - `logger`: the logger you want Mission Control Jobs to use. Defaults to `ActiveSupport::Logger.new(nil)` (no logging). Notice that this is different from Active Job's logger or Active Job's backend's configured logger.
55
55
  - `delay_between_bulk_operation_batches`: how long to wait between batches when performing bulk operations, such as _discard all_ or _retry all_ jobs—defaults to `0`
56
56
  - `adapters`: a list of adapters that you want Mission Control to use and extend. By default this will be the adapter you have set for `active_job.queue_adapter`.
57
+ - `internal_query_count_limit`: in count queries, the maximum number of records that will be counted if the adapter needs to limit these queries. True counts above this number will be returned as `INFINITY`. This keeps count queries fast—defaults to `500,000`
58
+ - `scheduled_job_delay_threshold`: the time duration before a scheduled job is considered delayed. Defaults to `1.minute` (a job is considered delayed if it hasn't transitioned from the `scheduled` status 1 minute after the scheduled time).
57
59
 
58
60
  This library extends Active Job with a querying interface and the following setting:
59
61
  - `config.active_job.default_page_size`: the internal batch size that Active Job will use when sending queries to the underlying adapter and the batch size for the bulk operations defined above—defaults to `1000`.
@@ -159,7 +161,7 @@ Typing `jobs_help`, you'll get clear instructions about how to switch between ap
159
161
  ```
160
162
  >> jobs_help
161
163
  You can connect to a job server with
162
- connect_to <app_id>:<server_id>
164
+ connect_to "<app_id>:<server_id>"
163
165
 
164
166
  Available job servers:
165
167
  * bc4:resque_ashburn
@@ -185,19 +187,19 @@ ActiveJob.jobs
185
187
  ActiveJob.jobs.failed
186
188
 
187
189
  # All pending jobs in some queue
188
- ActiveJob.jobs.pending.where(queue: "some_queue")
190
+ ActiveJob.jobs.pending.where(queue_name: "some_queue")
189
191
 
190
192
  # All failed jobs of a given class
191
- ActiveJob.jobs.failed.where(job_class: "SomeJob")
193
+ ActiveJob.jobs.failed.where(job_class_name: "SomeJob")
192
194
 
193
195
  # All pending jobs of a given class with limit and offset
194
- ActiveJob.jobs.pending.where(job_class: "SomeJob").limit(10).offset(5)
196
+ ActiveJob.jobs.pending.where(job_class_name: "SomeJob").limit(10).offset(5)
195
197
 
196
198
  # For adapters that support these statuses:
197
199
  # All scheduled/in-progress/finished jobs of a given class
198
- ActiveJob.jobs.scheudled.where(job_class: "SomeJob")
199
- ActiveJob.jobs.in_progress.where(job_class: "SomeJob")
200
- ActiveJob.jobs.finished.where(job_class: "SomeJob")
200
+ ActiveJob.jobs.scheduled.where(job_class_name: "SomeJob")
201
+ ActiveJob.jobs.in_progress.where(job_class_name: "SomeJob")
202
+ ActiveJob.jobs.finished.where(job_class_name: "SomeJob")
201
203
 
202
204
  # For adapters that support filtering by worker:
203
205
  # All jobs in progress being run by a given worker
@@ -211,13 +213,13 @@ Some examples of bulk operations:
211
213
  ActiveJob.jobs.failed.retry_all
212
214
 
213
215
  # Retry all the jobs of a given class (only possible for failed jobs)
214
- ActiveJob.jobs.failed.where(job_class: "SomeJob").retry_all
216
+ ActiveJob.jobs.failed.where(job_class_name: "SomeJob").retry_all
215
217
 
216
218
  # Discard all failed jobs
217
219
  ActiveJob.jobs.failed.discard_all
218
220
 
219
221
  # Discard all pending jobs of a given class
220
- ActiveJob.jobs.pending.where(job_class: "SomeJob").discard_all
222
+ ActiveJob.jobs.pending.where(job_class_name: "SomeJob").discard_all
221
223
  # Or all pending jobs in a given queue:
222
224
  ActiveJob.jobs.pending.where(queue_name: "some-queue").discard_all
223
225
  ```
@@ -2,19 +2,23 @@ module MissionControl::Jobs::AdapterFeatures
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- helper_method :supported_job_statuses, :queue_pausing_supported?, :workers_exposed?
5
+ helper_method :supported_job_statuses, :queue_pausing_supported?, :workers_exposed?, :recurring_tasks_supported?
6
6
  end
7
7
 
8
8
  private
9
- def workers_exposed?
10
- MissionControl::Jobs::Current.server.queue_adapter.exposes_workers?
11
- end
12
-
13
9
  def supported_job_statuses
14
- MissionControl::Jobs::Current.server.queue_adapter.supported_statuses & ActiveJob::JobsRelation::STATUSES
10
+ MissionControl::Jobs::Current.server.queue_adapter.supported_job_statuses & ActiveJob::JobsRelation::STATUSES
15
11
  end
16
12
 
17
13
  def queue_pausing_supported?
18
14
  MissionControl::Jobs::Current.server.queue_adapter.supports_queue_pausing?
19
15
  end
16
+
17
+ def workers_exposed?
18
+ MissionControl::Jobs::Current.server.queue_adapter.exposes_workers?
19
+ end
20
+
21
+ def recurring_tasks_supported?
22
+ MissionControl::Jobs::Current.server.queue_adapter.supports_recurring_tasks?
23
+ end
20
24
  end
@@ -12,6 +12,6 @@ module MissionControl::Jobs::FailedJobsBulkOperations
12
12
  # or causing replication lag in MySQL). This should be enough for most scenarios. For
13
13
  # cases where we need to retry a huge sets of jobs, we offer a runbook that uses the API.
14
14
  def bulk_limited_filtered_failed_jobs
15
- ApplicationJob.jobs.failed.where(**@job_filters).limit(MAX_NUMBER_OF_JOBS_FOR_BULK_OPERATIONS)
15
+ ActiveJob.jobs.failed.where(**@job_filters).limit(MAX_NUMBER_OF_JOBS_FOR_BULK_OPERATIONS)
16
16
  end
17
17
  end
@@ -7,7 +7,7 @@ module MissionControl::Jobs::NotFoundRedirections
7
7
  end
8
8
 
9
9
  rescue_from(MissionControl::Jobs::Errors::ResourceNotFound) do |error|
10
- redirect_to root_url, alert: error.message
10
+ redirect_to best_location_for_resource_not_found_error(error), alert: error.message
11
11
  end
12
12
  end
13
13
 
@@ -22,4 +22,12 @@ module MissionControl::Jobs::NotFoundRedirections
22
22
  root_path
23
23
  end
24
24
  end
25
+
26
+ def best_location_for_resource_not_found_error(error)
27
+ if error.message.match?(/recurring task/i)
28
+ application_recurring_tasks_path(@application)
29
+ else
30
+ root_url
31
+ end
32
+ end
25
33
  end
@@ -7,6 +7,6 @@ module MissionControl::Jobs::QueueScoped
7
7
 
8
8
  private
9
9
  def set_queue
10
- @queue = ActiveJob::Base.queues[params[:queue_id]] or raise MissionControl::Jobs::Errors::ResourceNotFound, "Queue '#{params[:queue_id]}' not found"
10
+ @queue = ActiveJob.queues[params[:queue_id]] or raise MissionControl::Jobs::Errors::ResourceNotFound, "Queue '#{params[:queue_id]}' not found"
11
11
  end
12
12
  end
@@ -14,7 +14,7 @@ class MissionControl::Jobs::BulkDiscardsController < MissionControl::Jobs::Appli
14
14
  bulk_limited_filtered_failed_jobs
15
15
  else
16
16
  # we don't want to apply any limit since "discarding all" without parameters can be optimized in the adapter as a much faster operation
17
- ApplicationJob.jobs.failed
17
+ ActiveJob.jobs.failed
18
18
  end
19
19
  end
20
20
  end
@@ -8,6 +8,6 @@ class MissionControl::Jobs::DiscardsController < MissionControl::Jobs::Applicati
8
8
 
9
9
  private
10
10
  def jobs_relation
11
- ApplicationJob.jobs.failed
11
+ ActiveJob.jobs.failed
12
12
  end
13
13
  end
@@ -0,0 +1,13 @@
1
+ class MissionControl::Jobs::DispatchesController < MissionControl::Jobs::ApplicationController
2
+ include MissionControl::Jobs::JobScoped
3
+
4
+ def create
5
+ @job.dispatch
6
+ redirect_to application_jobs_url(@application, :blocked), notice: "Dispatched job with id #{@job.job_id}"
7
+ end
8
+
9
+ private
10
+ def jobs_relation
11
+ ApplicationJob.jobs.blocked
12
+ end
13
+ end
@@ -5,7 +5,7 @@ class MissionControl::Jobs::JobsController < MissionControl::Jobs::ApplicationCo
5
5
 
6
6
  def index
7
7
  @job_class_names = jobs_with_status.job_class_names
8
- @queue_names = ApplicationJob.queues.map(&:name)
8
+ @queue_names = ActiveJob.queues.map(&:name)
9
9
 
10
10
  @jobs_page = MissionControl::Jobs::Page.new(filtered_jobs_with_status, page: params[:page].to_i)
11
11
  @jobs_count = @jobs_page.total_count
@@ -24,11 +24,11 @@ class MissionControl::Jobs::JobsController < MissionControl::Jobs::ApplicationCo
24
24
  end
25
25
 
26
26
  def jobs_with_status
27
- ApplicationJob.jobs.with_status(jobs_status)
27
+ ActiveJob.jobs.with_status(jobs_status)
28
28
  end
29
29
 
30
30
  def filtered_jobs
31
- ApplicationJob.jobs.where(**@job_filters)
31
+ ActiveJob.jobs.where(**@job_filters)
32
32
  end
33
33
 
34
34
  helper_method :jobs_status
@@ -11,14 +11,14 @@ class MissionControl::Jobs::QueuesController < MissionControl::Jobs::Application
11
11
 
12
12
  private
13
13
  def set_queue
14
- @queue = ApplicationJob.queues[params[:id]]
14
+ @queue = ActiveJob.queues[params[:id]]
15
15
  end
16
16
 
17
17
  def filtered_queues
18
- if prefix = ApplicationJob.queue_name_prefix
19
- ApplicationJob.queues.select { |queue| queue.name.start_with?(prefix) }
18
+ if prefix = ActiveJob::Base.queue_name_prefix
19
+ ActiveJob.queues.select { |queue| queue.name.start_with?(prefix) }
20
20
  else
21
- ApplicationJob.queues
21
+ ActiveJob.queues
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,23 @@
1
+ class MissionControl::Jobs::RecurringTasksController < MissionControl::Jobs::ApplicationController
2
+ before_action :ensure_supported_recurring_tasks
3
+ before_action :set_recurring_task, only: :show
4
+
5
+ def index
6
+ @recurring_tasks = MissionControl::Jobs::Current.server.recurring_tasks
7
+ end
8
+
9
+ def show
10
+ @jobs_page = MissionControl::Jobs::Page.new(@recurring_task.jobs, page: params[:page].to_i)
11
+ end
12
+
13
+ private
14
+ def ensure_supported_recurring_tasks
15
+ unless recurring_tasks_supported?
16
+ redirect_to root_url, alert: "This server doesn't support recurring tasks"
17
+ end
18
+ end
19
+
20
+ def set_recurring_task
21
+ @recurring_task = MissionControl::Jobs::Current.server.find_recurring_task(params[:id])
22
+ end
23
+ end
@@ -8,6 +8,6 @@ class MissionControl::Jobs::RetriesController < MissionControl::Jobs::Applicatio
8
8
 
9
9
  private
10
10
  def jobs_relation
11
- ApplicationJob.jobs.failed
11
+ ActiveJob.jobs.failed
12
12
  end
13
13
  end
@@ -2,7 +2,8 @@ class MissionControl::Jobs::WorkersController < MissionControl::Jobs::Applicatio
2
2
  before_action :ensure_exposed_workers
3
3
 
4
4
  def index
5
- @workers = MissionControl::Jobs::Current.server.workers.sort_by { |worker| -worker.jobs.count }
5
+ @workers_page = MissionControl::Jobs::Page.new(workers_relation, page: params[:page].to_i)
6
+ @workers_count = @workers_page.total_count
6
7
  end
7
8
 
8
9
  def show
@@ -15,4 +16,8 @@ class MissionControl::Jobs::WorkersController < MissionControl::Jobs::Applicatio
15
16
  redirect_to root_url, alert: "This server doesn't expose workers"
16
17
  end
17
18
  end
19
+
20
+ def workers_relation
21
+ MissionControl::Jobs::Current.server.workers_relation
22
+ end
18
23
  end
@@ -18,14 +18,18 @@ module MissionControl::Jobs::JobsHelper
18
18
  def attribute_names_for_job_status(status)
19
19
  case status.to_s
20
20
  when "failed" then [ "Error", "" ]
21
- when "blocked" then [ "Queue", "Blocked by", "Block expiry" ]
21
+ when "blocked" then [ "Queue", "Blocked by", "Block expiry", "" ]
22
22
  when "finished" then [ "Queue", "Finished" ]
23
- when "scheduled" then [ "Queue", "Scheduled" ]
23
+ when "scheduled" then [ "Queue", "Scheduled", "" ]
24
24
  when "in_progress" then [ "Queue", "Run by", "Running for" ]
25
25
  else []
26
26
  end
27
27
  end
28
28
 
29
+ def job_delayed?(job)
30
+ job.scheduled_at.before?(MissionControl::Jobs.scheduled_job_delay_threshold.ago)
31
+ end
32
+
29
33
  private
30
34
  def renderable_job_arguments_for(job)
31
35
  job.serialized_arguments.collect do |argument|
@@ -8,6 +8,7 @@ module MissionControl::Jobs::NavigationHelper
8
8
  end
9
9
 
10
10
  sections[:workers] = [ "Workers", application_workers_path(@application) ] if workers_exposed?
11
+ sections[:recurring_tasks] = [ "Recurring tasks", application_recurring_tasks_path(@application) ] if recurring_tasks_supported?
11
12
  end
12
13
  end
13
14
 
@@ -45,7 +46,7 @@ module MissionControl::Jobs::NavigationHelper
45
46
  end
46
47
 
47
48
  def jobs_count_with_status(status)
48
- count = ApplicationJob.jobs.with_status(status).count
49
+ count = ActiveJob.jobs.with_status(status).count
49
50
  count.infinite? ? "..." : number_to_human(count)
50
51
  end
51
52
  end
@@ -1,16 +1,16 @@
1
1
  class MissionControl::Jobs::Page
2
2
  DEFAULT_PAGE_SIZE = 10
3
3
 
4
- attr_reader :jobs_relation, :index, :page_size
4
+ attr_reader :records, :index, :page_size
5
5
 
6
- def initialize(jobs_relation, page: 1, page_size: DEFAULT_PAGE_SIZE)
7
- @jobs_relation = jobs_relation
6
+ def initialize(relation, page: 1, page_size: DEFAULT_PAGE_SIZE)
7
+ @relation = relation
8
8
  @page_size = page_size
9
9
  @index = [ page, 1 ].max
10
10
  end
11
11
 
12
- def jobs
13
- jobs_relation.limit(page_size).offset(offset)
12
+ def records
13
+ @relation.limit(page_size).offset(offset)
14
14
  end
15
15
 
16
16
  def first?
@@ -18,7 +18,7 @@ class MissionControl::Jobs::Page
18
18
  end
19
19
 
20
20
  def last?
21
- index == pages_count || empty? || jobs.empty?
21
+ index == pages_count || empty? || records.empty?
22
22
  end
23
23
 
24
24
  def empty?
@@ -34,11 +34,11 @@ class MissionControl::Jobs::Page
34
34
  end
35
35
 
36
36
  def pages_count
37
- (total_count.to_f / 10).ceil unless total_count.infinite?
37
+ (total_count.to_f / page_size).ceil unless total_count.infinite?
38
38
  end
39
39
 
40
40
  def total_count
41
- @total_count ||= jobs_relation.count # Potentially expensive when filtering and a lot of jobs, with adapter in charge of doing the filtering in memory
41
+ @total_count ||= @relation.count # Potentially expensive when filtering a lot of records, with the adapter in charge of doing the filtering in memory
42
42
  end
43
43
 
44
44
  private
@@ -0,0 +1,17 @@
1
+ class MissionControl::Jobs::RecurringTask
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :id, :job_class_name, :arguments, :schedule, :last_enqueued_at
5
+
6
+ def initialize(queue_adapter: ActiveJob::Base.queue_adapter, **kwargs)
7
+ @queue_adapter = queue_adapter
8
+ super(**kwargs)
9
+ end
10
+
11
+ def jobs
12
+ ActiveJob::JobsRelation.new(queue_adapter: queue_adapter).where(recurring_task_id: id)
13
+ end
14
+
15
+ private
16
+ attr_reader :queue_adapter
17
+ end
@@ -1,5 +1,5 @@
1
1
  <nav class="navbar" role="navigation" aria-label="main navigation">
2
- <div class="navbar-menu is-active">
2
+ <div class="navbar-menu is-active mb-4">
3
3
  <div class="navbar-start">
4
4
  </div>
5
5
 
@@ -1,5 +1,4 @@
1
1
  <% if job.failed? %>
2
- <a id="error"></a>
3
2
  <h2 class="subtitle">Error information</h2>
4
3
 
5
4
  <table class="table">
@@ -10,7 +10,7 @@
10
10
  </tr>
11
11
  <tr>
12
12
  <th>Job id</th>
13
- <td><%= job.job_id %> </td>
13
+ <td><%= job.job_id %></td>
14
14
  </tr>
15
15
  <tr>
16
16
  <th>Queue</th>
@@ -1,15 +1,13 @@
1
1
  <table class="jobs <%= jobs_status %> table queues is-hoverable is-fullwidth">
2
- <tbody>
3
2
  <thead>
4
- <tr>
5
- <th style="width: 35%;">Job</th>
6
- <% attribute_names_for_job_status(jobs_status).each do |attribute| %>
7
- <th><%= attribute %></th>
8
- <% end %>
9
- </tr>
3
+ <tr>
4
+ <th style="width: 35%;">Job</th>
5
+ <% attribute_names_for_job_status(jobs_status).each do |attribute| %>
6
+ <th><%= attribute %></th>
7
+ <% end %>
8
+ </tr>
10
9
  </thead>
11
-
12
- <%= render partial: "mission_control/jobs/jobs/job", collection: jobs_page.jobs %>
13
-
10
+ <tbody>
11
+ <%= render partial: "mission_control/jobs/jobs/job", collection: jobs_page.records %>
14
12
  </tbody>
15
13
  </table>
@@ -8,6 +8,9 @@
8
8
  <% if job.failed? %>
9
9
  <%= render "mission_control/jobs/jobs/failed/actions", job: job %>
10
10
  <% end %>
11
+ <% if job.blocked? %>
12
+ <%= render "mission_control/jobs/jobs/blocked/actions", job: job %>
13
+ <% end %>
11
14
  </div>
12
15
  </div>
13
16
  </h1>
@@ -0,0 +1,3 @@
1
+ <div class="buttons is-right">
2
+ <%= button_to "Dispatch", application_job_dispatch_path(@application, job.job_id), class: "button is-warning is-light mr-0" %>
3
+ </div>
@@ -1,3 +1,6 @@
1
1
  <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
2
  <td><div class="is-family-monospace is-size-7"><%= job.blocked_by %></div></td>
3
3
  <td><%= bidirectional_time_distance_in_words_with_title(job.blocked_until) %></td>
4
+ <td class="pr-0">
5
+ <%= render "mission_control/jobs/jobs/blocked/actions", job: job %>
6
+ </td>
@@ -3,7 +3,7 @@
3
3
  <% if @jobs_page.empty? && !active_filters? %>
4
4
  <%= blank_status_notice "There are no #{jobs_status.dasherize} jobs #{blank_status_emoji(jobs_status)}" %>
5
5
  <% else %>
6
- <div class="level">
6
+ <div class="level is-flex-wrap-wrap">
7
7
  <%= render "mission_control/jobs/jobs/filters", job_class_names: @job_class_names, queue_names: @queue_names %>
8
8
  <%= render "mission_control/jobs/jobs/toolbar", jobs_count: @jobs_count %>
9
9
  </div>
@@ -13,7 +13,7 @@
13
13
  <% else %>
14
14
  <%= render "mission_control/jobs/jobs/jobs_page", jobs_page: @jobs_page %>
15
15
 
16
- <%= render "mission_control/jobs/shared/pagination_toolbar", jobs_page: @jobs_page %>
16
+ <%= render "mission_control/jobs/shared/pagination_toolbar", page: @jobs_page, filter_param: jobs_filter_param %>
17
17
  <% end %>
18
18
  <% end %>
19
19
 
@@ -0,0 +1,4 @@
1
+ <div class="buttons is-right">
2
+ <%= button_to "Discard", application_job_discard_path(@application, job.job_id), class: "button is-danger is-light mr-0",
3
+ form: { data: { turbo_confirm: "This will delete the job and can't be undone. Are you sure?" } } %>
4
+ </div>
@@ -1,7 +1,10 @@
1
1
  <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
2
  <td>
3
3
  <%= bidirectional_time_distance_in_words_with_title(job.scheduled_at) %>
4
- <% if job.scheduled_at.before? 1.minute.ago %>
4
+ <% if job_delayed?(job) %>
5
5
  <div class="is-danger tag ml-4">delayed</div>
6
6
  <% end %>
7
7
  </td>
8
+ <td class="pr-0">
9
+ <%= render "mission_control/jobs/jobs/scheduled/actions", job: job %>
10
+ </td>
@@ -14,4 +14,4 @@
14
14
  </div>
15
15
  </h1>
16
16
 
17
- <h2 class="subtitle"><%= queue.size %> pending jobs</h2>
17
+ <h2 class="subtitle"><%= pluralize queue.size, "pending job" %></h2>
@@ -14,12 +14,12 @@
14
14
  </tr>
15
15
  </thead>
16
16
 
17
- <%= render partial: "mission_control/jobs/queues/job", collection: @jobs_page.jobs %>
17
+ <%= render partial: "mission_control/jobs/queues/job", collection: @jobs_page.records %>
18
18
 
19
19
  </tbody>
20
20
  </table>
21
21
 
22
- <%= render "mission_control/jobs/shared/pagination_toolbar", jobs_page: @jobs_page %>
22
+ <%= render "mission_control/jobs/shared/pagination_toolbar", page: @jobs_page, filter_param: {} %>
23
23
  <% end %>
24
24
 
25
25
 
@@ -0,0 +1,16 @@
1
+ <table class="table">
2
+ <tbody>
3
+ <tr>
4
+ <th>Job class</th>
5
+ <td><%= recurring_task.job_class_name %></td>
6
+ </tr>
7
+ <tr>
8
+ <th>Arguments</th>
9
+ <td><div class="is-family-monospace"><%= recurring_task.arguments.join(",") %></div></td>
10
+ </tr>
11
+ <tr>
12
+ <th>Schedule</th>
13
+ <td><%= recurring_task.schedule %></td>
14
+ </tr>
15
+ </tbody>
16
+ </table>
@@ -0,0 +1,14 @@
1
+ <tr class="recurring_task">
2
+ <td>
3
+ <%= link_to recurring_task.id, application_recurring_task_path(@application, recurring_task.id) %>
4
+ </td>
5
+ <td>
6
+ <%= link_to recurring_task.job_class_name, application_recurring_task_path(@application, recurring_task.id) %>
7
+
8
+ <% if recurring_task.arguments.present? %>
9
+ <div class="is-family-monospace"><%= recurring_task.arguments.join(",") %></div>
10
+ <% end %>
11
+ </td>
12
+ <td> <%= recurring_task.schedule %> </td>
13
+ <td><div class="has-text-grey"><%= recurring_task.last_enqueued_at ? bidirectional_time_distance_in_words_with_title(recurring_task.last_enqueued_at) : "Never" %></div></td>
14
+ </tr>
@@ -0,0 +1,7 @@
1
+ <h1 class="title">
2
+ <div class="level">
3
+ <div class="level-left">
4
+ <%= recurring_task.id %>
5
+ </div>
6
+ </div>
7
+ </h1>
@@ -0,0 +1,16 @@
1
+ <% navigation(title: "Recurring tasks", section: :recurring_tasks) %>
2
+
3
+ <table class="recurring-tasks table jobs is-hoverable is-fullwidth">
4
+ <tbody>
5
+ <thead>
6
+ <tr>
7
+ <th></th>
8
+ <th>Job</th>
9
+ <th>Schedule</th>
10
+ <th>Last enqueued at</th>
11
+ </tr>
12
+ </thead>
13
+
14
+ <%= render partial: "mission_control/jobs/recurring_tasks/recurring_task", collection: @recurring_tasks %>
15
+ </tbody>
16
+ </table>
@@ -0,0 +1,14 @@
1
+ <% navigation(title: @recurring_task.id, section: :recurring_tasks) %>
2
+
3
+ <%= render "mission_control/jobs/recurring_tasks/title", recurring_task: @recurring_task %>
4
+ <%= render "mission_control/jobs/recurring_tasks/general_information", recurring_task: @recurring_task %>
5
+
6
+ <% if @jobs_page.empty? %>
7
+ <%= blank_status_notice "No jobs found for this recurring task" %>
8
+ <% else %>
9
+ <h2 class="subtitle"><%= pluralize @recurring_task.jobs.count, "job" %></h2>
10
+
11
+ <%= render "mission_control/jobs/shared/jobs", jobs: @jobs_page.records %>
12
+
13
+ <%= render "mission_control/jobs/shared/pagination_toolbar", page: @jobs_page, filter_param: jobs_filter_param %>
14
+ <% end %>
@@ -14,6 +14,13 @@
14
14
  </td>
15
15
 
16
16
  <td>
17
- <div class="has-text-grey"><%= job.started_at ? time_distance_in_words_with_title(job.started_at) : "(Finished)" %></div>
17
+ <div class="has-text-grey">
18
+ <% if job.started_at %>
19
+ Running for <%= time_distance_in_words_with_title(job.started_at) %>
20
+ <% elsif job.finished_at %>
21
+ Finished <%= time_ago_in_words_with_title(job.finished_at) %> ago
22
+ <% else %>
23
+ Pending
24
+ <% end %>
18
25
  </td>
19
26
  </tr>
@@ -0,0 +1,14 @@
1
+ <table class="jobs table is-hoverable is-fullwidth">
2
+ <tbody>
3
+ <thead>
4
+ <tr>
5
+ <th style="width: 30%;">Job</th>
6
+ <th></th>
7
+ <th style="width: 20%;"></th>
8
+ </tr>
9
+ </thead>
10
+
11
+ <%= render partial: "mission_control/jobs/shared/job", collection: jobs %>
12
+
13
+ </tbody>
14
+ </table>
@@ -1,5 +1,5 @@
1
1
  <nav class="buttons is-right" role="navigation" aria-label="pagination">
2
- <span class="mr-3"><%= jobs_page.index %> / <%= jobs_page.pages_count || "..." %></span>
3
- <%= link_to "Previous page", url_for(page: jobs_page.previous_index, **jobs_filter_param), class: "pagination-previous", disabled: jobs_page.first? %>
4
- <%= link_to "Next page", url_for(page: jobs_page.next_index, **jobs_filter_param), class: "pagination-next", disabled: jobs_page.last? %>
2
+ <span class="mr-3"><%= page.index %> / <%= page.pages_count || "..." %></span>
3
+ <%= link_to "Previous page", url_for(page: page.previous_index, **filter_param), class: "pagination-previous", disabled: page.first? %>
4
+ <%= link_to "Next page", url_for(page: page.next_index, **filter_param), class: "pagination-next", disabled: page.last? %>
5
5
  </nav>