Skip to content

Commit bf3a0d6

Browse files
committed
Add pending job view template, simplify date range checks, add enqueued and scheduled filter fields, add tests for enqueued and scheduled jobs
1 parent e271fbb commit bf3a0d6

File tree

5 files changed

+111
-25
lines changed

5 files changed

+111
-25
lines changed

app/controllers/concerns/mission_control/jobs/job_filters.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,18 @@ def set_filters
1212
@job_filters = {
1313
job_class_name: params.dig(:filter, :job_class_name).presence,
1414
queue_name: params.dig(:filter, :queue_name).presence,
15-
finished_at: finished_at_range_params
15+
finished_at: date_range_params(:finished_at),
16+
enqueued_at: date_range_params(:enqueued_at),
17+
scheduled_at: date_range_params(:scheduled_at)
1618
}.compact
1719
end
1820

1921
def active_filters?
2022
@job_filters.any?
2123
end
2224

23-
def finished_at_range_params
24-
range_start, range_end = params.dig(:filter, :finished_at_start), params.dig(:filter, :finished_at_end)
25+
def date_range_params(date_type)
26+
range_start, range_end = params.dig(:filter, :"#{date_type}_start"), params.dig(:filter, :"#{date_type}_end")
2527
if range_start || range_end
2628
(parse_with_time_zone(range_start)..parse_with_time_zone(range_end))
2729
end

app/views/mission_control/jobs/jobs/_filters.html.erb

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,63 @@
1313
</div>
1414

1515
<% if jobs_status == "finished" %>
16+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
17+
<label class="has-text-grey is-size-7">
18+
Finished from:
19+
</label>
20+
<div class="select is-rounded">
21+
<%= form.datetime_field :finished_at_start, value: @job_filters[:finished_at]&.begin, class: "input", placeholder: "Finished from" %>
22+
</div>
23+
</div>
24+
25+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
26+
<label class="has-text-grey is-size-7">
27+
Finished to:
28+
</label>
29+
<div class="select is-rounded">
30+
<%# TODO: add max date of today? %>
31+
<%= form.datetime_field :finished_at_end, value: @job_filters[:finished_at]&.end, class: "input", placeholder: "Finished to" %>
32+
</div>
33+
</div>
34+
<% end %>
35+
36+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
37+
<label class="has-text-grey is-size-7">
38+
Enqueued from:
39+
</label>
1640
<div class="select is-rounded">
17-
<%= form.datetime_field :finished_at_start, value: @job_filters[:finished_at]&.begin, class: "input", placeholder: "Finished from" %>
41+
<%= form.datetime_field :enqueued_at_start, value: @job_filters[:enqueued_at]&.begin, class: "input", placeholder: "Enqueued from" %>
1842
</div>
43+
</div>
1944

45+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
46+
<label class="has-text-grey is-size-7">
47+
Enqueued to:
48+
</label>
2049
<div class="select is-rounded">
21-
<%= form.datetime_field :finished_at_end, value: @job_filters[:finished_at]&.end, class: "input", placeholder: "Finished to" %>
50+
<%# TODO: add max date of today? %>
51+
<%= form.datetime_field :enqueued_at_end, value: @job_filters[:enqueued_at]&.end, class: "input", placeholder: "Enqueued to" %>
2252
</div>
23-
<% end %>
53+
</div>
54+
55+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
56+
<label class="has-text-grey is-size-7">
57+
Scheduled from:
58+
</label>
59+
<div class="select is-rounded">
60+
<%= form.datetime_field :scheduled_at_start, value: @job_filters[:scheduled_at]&.begin, class: "input", placeholder: "Scheduled from" %>
61+
</div>
62+
</div>
63+
64+
<div class="field is-flex is-flex-direction-column is-align-items-flex-start">
65+
<label class="has-text-grey is-size-7">
66+
Scheduled to:
67+
</label>
68+
<div class="select is-rounded">
69+
<%# TODO: add max date of today? %>
70+
<%= form.datetime_field :scheduled_at_end, value: @job_filters[:scheduled_at]&.end, class: "input", placeholder: "Scheduled to" %>
71+
</div>
72+
</div>
2473

2574
<%= hidden_field_tag :server_id, MissionControl::Jobs::Current.server.id %>
2675

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2+
<td><div class="has-text-grey">Ready to run</div></td>

lib/active_job/jobs_relation.rb

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def initialize(queue_adapter: ActiveJob::Base.queue_adapter, default_page_size:
5151
# * <tt>:queue_name</tt> - To only include the jobs in the provided queue.
5252
# * <tt>:worker_id</tt> - To only include the jobs processed by the provided worker.
5353
# * <tt>:recurring_task_id</tt> - To only include the jobs corresponding to runs of a recurring task.
54+
# * <tt>:finished_at</tt> - (Range) To only include the jobs finished between the provided range
55+
# * <tt>:scheduled_at</tt> - (Range) To only include the jobs scheduled between the provided range
56+
# * <tt>:enqueued_at</tt> - (Range) To only include the jobs enqueued between the provided range
5457
def where(job_class_name: nil, queue_name: nil, worker_id: nil, recurring_task_id: nil, finished_at: nil, scheduled_at: nil, enqueued_at: nil)
5558
# Remove nil arguments to avoid overriding parameters when concatenating +where+ clauses
5659
arguments = { job_class_name: job_class_name,
@@ -60,7 +63,7 @@ def where(job_class_name: nil, queue_name: nil, worker_id: nil, recurring_task_i
6063
finished_at: finished_at,
6164
scheduled_at: scheduled_at,
6265
enqueued_at: enqueued_at
63-
}.compact.collect { |key, value| [ key, value.to_s ] }.to_h
66+
}.compact
6467

6568
# TODO: is this collect needed? .collect { |key, value| [ key, value.to_s ] }.to_h
6669

@@ -271,36 +274,24 @@ def loaded?
271274

272275
# Filtering for not natively supported filters is performed in memory
273276
def filter(jobs)
274-
jobs.filter { |job| satisfy_filter?(job) }
277+
jobs.filter { |job| satisfies_filters?(job) }
275278
end
276279

277-
def satisfy_date_filter?(filter_value, job_value)
278-
return false if job_value.nil?
280+
def satisfies_filter?(filter_value, job_value)
281+
return filter_value.cover?(job_value) if filter_value.is_a?(Range) # TODO: needed? && job_value.is_a?(ActiveSupport::TimeWithZone)
279282

280-
# Treat date ranges
281-
if filter_value.include?("..")
282-
start_date, end_date = filter_value.split("..").map { |date| Time.zone.parse(date) }
283-
filter_range = (start_date..end_date)
284-
return filter_range.cover?(job_value)
285-
end
286-
287-
filter = Time.zone.parse(filter_value)
288-
job_value >= filter
283+
filter_value == job_value
289284
end
290285

291-
def satisfy_filter?(job)
286+
def satisfies_filters?(job)
292287
filters.all? do |property|
293288
filter_value = public_send(property)
294289
job_value = job.public_send(property)
295290

296-
is_date_filter?(property) ? satisfy_date_filter?(filter_value, job_value) : filter_value == job_value
291+
satisfies_filter?(filter_value, job_value)
297292
end
298293
end
299294

300-
def is_date_filter?(property)
301-
[ :finished_at, :scheduled_at, :enqueued_at ].include?(property)
302-
end
303-
304295
def filters
305296
@filters ||= FILTERS.select { |property| public_send(property).present? && !queue_adapter.supports_job_filter?(self, property) }
306297
end

test/controllers/jobs_controller_test.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,48 @@ class MissionControl::Jobs::JobsControllerTest < ActionDispatch::IntegrationTest
6363
assert_select "tr.job", 1
6464
end
6565

66+
test "get pending jobs filtered by enqueued_at date" do
67+
job = DummyJob.perform_later(42)
68+
69+
get mission_control_jobs.application_jobs_url(@application, :pending)
70+
assert_response :ok
71+
assert_select "tr.job", 1
72+
73+
get mission_control_jobs.application_jobs_url(@application, :pending, filter: { enqueued_at_start: 1.hour.from_now.to_s })
74+
assert_response :ok
75+
assert_select "tr.job", 0
76+
77+
get mission_control_jobs.application_jobs_url(@application, :pending, filter: { enqueued_at_start: 1.hour.ago.to_s, enqueued_at_end: 1.hour.from_now })
78+
assert_response :ok
79+
assert_select "tr.job", 1
80+
81+
get mission_control_jobs.application_jobs_url(@application, :pending, filter: { enqueued_at_end: 1.hour.from_now })
82+
assert_response :ok
83+
assert_select "tr.job", 1
84+
end
85+
86+
test "get scheduled jobs filtered by scheduled_at date" do
87+
job = DummyJob.set(wait: 30.minutes).perform_later(42)
88+
89+
get mission_control_jobs.application_jobs_url(@application, :scheduled)
90+
assert_response :ok
91+
assert_select "tr.job", 1
92+
93+
get mission_control_jobs.application_jobs_url(@application, :scheduled, filter: { scheduled_at_start: 1.hour.from_now.to_s })
94+
assert_response :ok
95+
assert_select "tr.job", 0
96+
97+
get mission_control_jobs.application_jobs_url(@application, :scheduled, filter: { scheduled_at_start: 15.minutes.from_now.to_s, scheduled_at_end: 45.minutes.from_now })
98+
assert_response :ok
99+
assert_select "tr.job", 1
100+
101+
get mission_control_jobs.application_jobs_url(@application, :scheduled, filter: { scheduled_at_end: 45.minutes.from_now })
102+
assert_response :ok
103+
assert_select "tr.job", 1
104+
end
105+
106+
# TODO: hitting clear on the date input should refresh the list?
107+
66108
test "redirect to queue when job doesn't exist" do
67109
job = DummyJob.perform_later(42)
68110

0 commit comments

Comments
 (0)