mission_control-jobs 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/app/controllers/concerns/mission_control/jobs/job_filters.rb +3 -3
- data/app/controllers/concerns/mission_control/jobs/not_found_redirections.rb +4 -1
- data/app/controllers/mission_control/jobs/application_controller.rb +2 -1
- data/app/controllers/mission_control/jobs/queues_controller.rb +1 -1
- data/app/helpers/mission_control/jobs/jobs_helper.rb +6 -1
- data/app/helpers/mission_control/jobs/navigation_helper.rb +4 -0
- data/app/views/layouts/mission_control/jobs/_application_selection.html.erb +2 -2
- data/app/views/layouts/mission_control/jobs/application.html.erb +1 -0
- data/app/views/mission_control/jobs/jobs/_error_information.html.erb +6 -4
- data/app/views/mission_control/jobs/jobs/_general_information.html.erb +6 -0
- data/app/views/mission_control/jobs/jobs/_raw_data.html.erb +1 -1
- data/app/views/mission_control/jobs/jobs/blocked/_job.html.erb +1 -1
- data/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb +3 -0
- data/app/views/mission_control/jobs/queues/index.html.erb +2 -1
- data/app/views/mission_control/jobs/shared/_pagination_toolbar.html.erb +2 -0
- data/lib/active_job/job_proxy.rb +3 -1
- data/lib/active_job/jobs_relation.rb +3 -3
- data/lib/active_job/queue_adapters/resque_ext.rb +15 -2
- data/lib/active_job/queue_adapters/solid_queue_ext.rb +16 -2
- data/lib/mission_control/jobs/arguments_filter.rb +24 -0
- data/lib/mission_control/jobs/engine.rb +7 -1
- data/lib/mission_control/jobs/host_route_helpers.rb +33 -0
- data/lib/mission_control/jobs/version.rb +1 -1
- data/lib/mission_control/jobs.rb +7 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4f358c4160d8065ff1069ba50a20305eaab8c6beebdca8eddb8a3426f3ea4771
|
|
4
|
+
data.tar.gz: 11e94ea39f4700cfa9a4d35eeb032e5bb721d62f6eb3b033911832737239a61a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35ef96bedf4688eb227212f910687239b2d2418935a27a450102351507bb0cf0abb6377d2a27e1f91b9985d638bac4263e18fc5a75806d2e35f721357818c939
|
|
7
|
+
data.tar.gz: 430fef8fade1f488a6a73f69600dd743d361f07e50cf6df8bbba38de0b152058ae8023bea962d51966558ae72de01024b399cb12113380d3d46a9e007623f25c
|
data/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Rails.application.routes.draw do
|
|
|
24
24
|
mount MissionControl::Jobs::Engine, at: "/jobs"
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Once you set up [Authentication](#authentication), you should be able to access Mission Control Job's UI, where you can browse the existing queues, jobs pending in these queues, jobs in different statuses, and discard and retry failed jobs:
|
|
28
28
|
|
|
29
29
|

|
|
30
30
|
|
|
@@ -113,7 +113,9 @@ Besides `base_controller_class`, you can also set the following for `MissionCont
|
|
|
113
113
|
- `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`
|
|
114
114
|
- `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).
|
|
115
115
|
- `show_console_help`: whether to show the console help. If you don't want the console help message, set this to `false`—defaults to `true`.
|
|
116
|
+
- `back_to_main_app_path`: an optional string path for the "Back to main app" link. Example: `'/admin'`. Defaults to the host app's `root_path` when available.
|
|
116
117
|
- `backtrace_cleaner`: a backtrace cleaner used for optionally filtering backtraces on the Failed Jobs detail page. Defaults to `Rails::BacktraceCleaner.new`. See the [Advanced configuration](#advanced-configuration) section for how to configure/override this setting on a per application/server basis.
|
|
118
|
+
- `filter_arguments`: an array of strings representing the job argument keys you want to filter out in the UI. This is useful for hiding sensitive user data. Currently, only root-level hash keys are supported.
|
|
117
119
|
|
|
118
120
|
This library extends Active Job with a querying interface and the following setting:
|
|
119
121
|
- `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`.
|
|
@@ -10,8 +10,8 @@ module MissionControl::Jobs::JobFilters
|
|
|
10
10
|
private
|
|
11
11
|
def set_filters
|
|
12
12
|
@job_filters = {
|
|
13
|
-
job_class_name: params.dig(:filter, :job_class_name).presence,
|
|
14
|
-
queue_name: params.dig(:filter, :queue_name).presence,
|
|
13
|
+
job_class_name: params.dig(:filter, :job_class_name).to_s.strip.presence,
|
|
14
|
+
queue_name: params.dig(:filter, :queue_name).to_s.strip.presence,
|
|
15
15
|
finished_at: finished_at_range_params
|
|
16
16
|
}.compact
|
|
17
17
|
end
|
|
@@ -36,6 +36,6 @@ module MissionControl::Jobs::JobFilters
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def parse_with_time_zone(date)
|
|
39
|
-
|
|
39
|
+
Time.zone.parse(date) if date.present?
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -24,8 +24,11 @@ module MissionControl::Jobs::NotFoundRedirections
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def best_location_for_resource_not_found_error(error)
|
|
27
|
-
|
|
27
|
+
case error.message
|
|
28
|
+
when /recurring task/i
|
|
28
29
|
application_recurring_tasks_path(@application)
|
|
30
|
+
when /queue/i
|
|
31
|
+
application_queues_path(@application)
|
|
29
32
|
else
|
|
30
33
|
root_url
|
|
31
34
|
end
|
|
@@ -9,6 +9,7 @@ class MissionControl::Jobs::ApplicationController < MissionControl::Jobs.base_co
|
|
|
9
9
|
helper MissionControl::Jobs::ApplicationHelper unless self < MissionControl::Jobs::ApplicationHelper
|
|
10
10
|
helper Importmap::ImportmapTagsHelper unless self < Importmap::ImportmapTagsHelper
|
|
11
11
|
|
|
12
|
+
include MissionControl::Jobs::HostRouteHelpers
|
|
12
13
|
include MissionControl::Jobs::BasicAuthentication
|
|
13
14
|
include MissionControl::Jobs::ApplicationScoped, MissionControl::Jobs::NotFoundRedirections
|
|
14
15
|
include MissionControl::Jobs::AdapterFeatures
|
|
@@ -18,7 +19,7 @@ class MissionControl::Jobs::ApplicationController < MissionControl::Jobs.base_co
|
|
|
18
19
|
|
|
19
20
|
private
|
|
20
21
|
def default_url_options
|
|
21
|
-
|
|
22
|
+
super.merge(server_id: MissionControl::Jobs::Current.server)
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def set_current_locale(&block)
|
|
@@ -11,6 +11,6 @@ class MissionControl::Jobs::QueuesController < MissionControl::Jobs::Application
|
|
|
11
11
|
|
|
12
12
|
private
|
|
13
13
|
def set_queue
|
|
14
|
-
@queue = ActiveJob.queues[params[:id]]
|
|
14
|
+
@queue = ActiveJob.queues[params[:id]] or raise MissionControl::Jobs::Errors::ResourceNotFound, "Queue '#{params[:id]}' not found"
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -38,6 +38,10 @@ module MissionControl::Jobs::JobsHelper
|
|
|
38
38
|
job.scheduled_at.before?(MissionControl::Jobs.scheduled_job_delay_threshold.ago)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
def blocked_job_expiration(job)
|
|
42
|
+
"Expires #{bidirectional_time_distance_in_words_with_title(job.blocked_until)}".html_safe if job.blocked_until
|
|
43
|
+
end
|
|
44
|
+
|
|
41
45
|
private
|
|
42
46
|
def renderable_job_arguments_for(job)
|
|
43
47
|
job.serialized_arguments.collect do |argument|
|
|
@@ -67,7 +71,8 @@ module MissionControl::Jobs::JobsHelper
|
|
|
67
71
|
elsif argument["_aj_serialized"]
|
|
68
72
|
ActiveJob::Arguments.deserialize([ argument ]).first
|
|
69
73
|
else
|
|
70
|
-
|
|
74
|
+
MissionControl::Jobs.job_arguments_filter.apply_to(argument)
|
|
75
|
+
.without("_aj_symbol_keys", "_aj_ruby2_keywords")
|
|
71
76
|
.transform_values { |v| as_renderable_argument(v) }
|
|
72
77
|
.map { |k, v| "#{k}: #{v}" }
|
|
73
78
|
.join(", ")
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
module MissionControl::Jobs::NavigationHelper
|
|
2
2
|
attr_reader :page_title, :current_section
|
|
3
3
|
|
|
4
|
+
def back_to_main_app_path
|
|
5
|
+
MissionControl::Jobs.back_to_main_app_path.presence || main_app.try(:root_path)
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
def navigation_sections
|
|
5
9
|
{ queues: [ "Queues", application_queues_path(@application) ] }.tap do |sections|
|
|
6
10
|
supported_job_statuses.without(:pending).each do |status|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
|
2
2
|
<div class="navbar-menu is-active mb-4">
|
|
3
3
|
<div class="navbar-start">
|
|
4
|
-
<% if
|
|
5
|
-
<%= link_to "Back to main app",
|
|
4
|
+
<% if (path = back_to_main_app_path) %>
|
|
5
|
+
<%= link_to "Back to main app", path %>
|
|
6
6
|
<% end %>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
9
9
|
<meta name="turbo-cache-control" content="no-cache">
|
|
10
|
+
<meta name="turbo-prefetch" content="false">
|
|
10
11
|
|
|
11
12
|
<%= stylesheet_link_tag "mission_control/jobs/bulma.min" %>
|
|
12
13
|
<%= stylesheet_link_tag "mission_control/jobs/application", "data-turbo-track": "reload" %>
|
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
</tbody>
|
|
15
15
|
</table>
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
<%= turbo_frame_tag "job-backtrace" do %>
|
|
18
|
+
<% if @server.backtrace_cleaner %>
|
|
19
|
+
<%= render "mission_control/jobs/jobs/failed/backtrace_toggle", application: @application, job: job %>
|
|
20
|
+
<% end %>
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
<pre class="is-family-monospace mb-4 backtrace-content"><%= failed_job_backtrace(job, @server) %></pre>
|
|
23
|
+
<% end %>
|
|
22
24
|
<% end %>
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
<%= time_distance_in_words_with_title(job.enqueued_at.to_datetime) %> ago
|
|
27
27
|
</td>
|
|
28
28
|
</tr>
|
|
29
|
+
<% if job.executions > 0 %>
|
|
30
|
+
<tr>
|
|
31
|
+
<th>Retries</th>
|
|
32
|
+
<td><%= job.executions %></td>
|
|
33
|
+
</tr>
|
|
34
|
+
<% end %>
|
|
29
35
|
<% if job.scheduled? %>
|
|
30
36
|
<tr>
|
|
31
37
|
<th>Scheduled</th>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
|
|
2
2
|
<td>
|
|
3
3
|
<div class="is-family-monospace is-size-7"><%= job.blocked_by %></div>
|
|
4
|
-
<div class="has-text-grey is-size-7"><%=
|
|
4
|
+
<div class="has-text-grey is-size-7"><%= blocked_job_expiration(job) %></div>
|
|
5
5
|
</td>
|
|
6
6
|
<td class="pr-0">
|
|
7
7
|
<%= render "mission_control/jobs/jobs/blocked/actions", job: job %>
|
|
@@ -1,6 +1,9 @@
|
|
|
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.executions > 0 %>
|
|
5
|
+
<div class="is-warning tag ml-4"><%= job.executions.ordinalize %> retry</div>
|
|
6
|
+
<% end %>
|
|
4
7
|
<% if job_delayed?(job) %>
|
|
5
8
|
<div class="is-danger tag ml-4">delayed</div>
|
|
6
9
|
<% end %>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<% navigation(title: "Queues", section: :queues) %>
|
|
2
2
|
|
|
3
3
|
<table class="queues table is-hoverable is-fullwidth">
|
|
4
|
-
<tbody>
|
|
5
4
|
<thead>
|
|
6
5
|
<tr>
|
|
7
6
|
<th>Queue</th>
|
|
@@ -10,6 +9,8 @@
|
|
|
10
9
|
</tr>
|
|
11
10
|
</thead>
|
|
12
11
|
|
|
12
|
+
<tbody>
|
|
13
|
+
|
|
13
14
|
<%= render partial: "mission_control/jobs/queues/queue", collection: @queues %>
|
|
14
15
|
|
|
15
16
|
</tbody>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<nav class="buttons is-right" role="navigation" aria-label="pagination">
|
|
2
2
|
<span class="mr-3"><%= page.index %> / <%= page.pages_count || "..." %></span>
|
|
3
|
+
<%= link_to "↞", url_for(page: 1, **filter_param), class: "pagination-previous", disabled: page.first? %>
|
|
3
4
|
<%= link_to "Previous page", url_for(page: page.previous_index, **filter_param), class: "pagination-previous", disabled: page.first? %>
|
|
4
5
|
<%= link_to "Next page", url_for(page: page.next_index, **filter_param), class: "pagination-next", disabled: page.last? %>
|
|
6
|
+
<%= link_to "↠", url_for(page: page.pages_count, **filter_param), class: "pagination-next", disabled: page.last? %>
|
|
5
7
|
</nav>
|
data/lib/active_job/job_proxy.rb
CHANGED
|
@@ -7,6 +7,8 @@ class ActiveJob::JobProxy < ActiveJob::Base
|
|
|
7
7
|
class UnsupportedError < StandardError; end
|
|
8
8
|
|
|
9
9
|
attr_reader :job_class_name
|
|
10
|
+
# Raw data with the sensitive user data filtered out.
|
|
11
|
+
attr_accessor :filtered_raw_data
|
|
10
12
|
|
|
11
13
|
def initialize(job_data)
|
|
12
14
|
super
|
|
@@ -25,7 +27,7 @@ class ActiveJob::JobProxy < ActiveJob::Base
|
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def duration
|
|
28
|
-
finished_at - scheduled_at
|
|
30
|
+
finished_at - (scheduled_at || enqueued_at)
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
ActiveJob::JobsRelation::STATUSES.each do |status|
|
|
@@ -26,7 +26,7 @@ class ActiveJob::JobsRelation
|
|
|
26
26
|
FILTERS = %i[ queue_name job_class_name ]
|
|
27
27
|
|
|
28
28
|
PROPERTIES = %i[ queue_name status offset_value limit_value job_class_name worker_id recurring_task_id finished_at ]
|
|
29
|
-
attr_reader
|
|
29
|
+
attr_reader(*PROPERTIES, :default_page_size)
|
|
30
30
|
|
|
31
31
|
delegate :last, :[], :reverse, to: :to_a
|
|
32
32
|
delegate :logger, to: MissionControl::Jobs
|
|
@@ -61,7 +61,7 @@ class ActiveJob::JobsRelation
|
|
|
61
61
|
finished_at: finished_at
|
|
62
62
|
}.compact
|
|
63
63
|
|
|
64
|
-
clone_with
|
|
64
|
+
clone_with(**arguments)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def with_status(status)
|
|
@@ -219,7 +219,7 @@ class ActiveJob::JobsRelation
|
|
|
219
219
|
|
|
220
220
|
private
|
|
221
221
|
attr_reader :queue_adapter, :loaded_jobs
|
|
222
|
-
attr_writer
|
|
222
|
+
attr_writer(*PROPERTIES)
|
|
223
223
|
|
|
224
224
|
def set_defaults
|
|
225
225
|
self.offset_value = 0
|
|
@@ -185,16 +185,29 @@ module ActiveJob::QueueAdapters::ResqueExt
|
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
def deserialize_resque_job(resque_job_hash, index)
|
|
188
|
-
args_hash =
|
|
189
|
-
ActiveJob::JobProxy.new(args_hash
|
|
188
|
+
args_hash = extract_args_hash(resque_job_hash)
|
|
189
|
+
ActiveJob::JobProxy.new(args_hash).tap do |job|
|
|
190
190
|
job.last_execution_error = execution_error_from_resque_job(resque_job_hash)
|
|
191
191
|
job.raw_data = resque_job_hash
|
|
192
|
+
job.filtered_raw_data = filter_raw_data_arguments(resque_job_hash)
|
|
192
193
|
job.position = jobs_relation.offset_value + index
|
|
193
194
|
job.failed_at = resque_job_hash["failed_at"]&.to_datetime&.utc
|
|
194
195
|
job.status = job.failed_at.present? ? :failed : :pending
|
|
195
196
|
end
|
|
196
197
|
end
|
|
197
198
|
|
|
199
|
+
def filter_raw_data_arguments(raw_data)
|
|
200
|
+
raw_data.deep_dup.tap do |filtered_data|
|
|
201
|
+
if args_hash = extract_args_hash(filtered_data)
|
|
202
|
+
args_hash["arguments"] = MissionControl::Jobs.job_arguments_filter.apply_to(args_hash["arguments"])
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def extract_args_hash(raw_data)
|
|
208
|
+
(raw_data.dig("payload", "args") || raw_data.dig("args"))&.first
|
|
209
|
+
end
|
|
210
|
+
|
|
198
211
|
def execution_error_from_resque_job(resque_job_hash)
|
|
199
212
|
if resque_job_hash["exception"].present?
|
|
200
213
|
ActiveJob::ExecutionError.new \
|
|
@@ -4,12 +4,14 @@ module ActiveJob::QueueAdapters::SolidQueueExt
|
|
|
4
4
|
|
|
5
5
|
def queues
|
|
6
6
|
queues = SolidQueue::Queue.all
|
|
7
|
-
|
|
7
|
+
queue_names = queues.map(&:name)
|
|
8
|
+
pauses = SolidQueue::Pause.where(queue_name: queue_names).index_by(&:queue_name)
|
|
9
|
+
sizes = SolidQueue::ReadyExecution.where(queue_name: queue_names).group(:queue_name).count
|
|
8
10
|
|
|
9
11
|
queues.collect do |queue|
|
|
10
12
|
{
|
|
11
13
|
name: queue.name,
|
|
12
|
-
size: queue.
|
|
14
|
+
size: sizes[queue.name] || 0,
|
|
13
15
|
active: pauses[queue.name].nil?
|
|
14
16
|
}
|
|
15
17
|
end
|
|
@@ -99,6 +101,7 @@ module ActiveJob::QueueAdapters::SolidQueueExt
|
|
|
99
101
|
job.status = job_status
|
|
100
102
|
job.last_execution_error = execution_error_from_solid_queue_job(solid_queue_job) if job_status == :failed
|
|
101
103
|
job.raw_data = solid_queue_job.as_json
|
|
104
|
+
job.filtered_raw_data = filter_raw_data_arguments(job.raw_data)
|
|
102
105
|
job.failed_at = solid_queue_job&.failed_execution&.created_at if job_status == :failed
|
|
103
106
|
job.finished_at = solid_queue_job.finished_at
|
|
104
107
|
job.blocked_by = solid_queue_job.concurrency_key
|
|
@@ -109,6 +112,12 @@ module ActiveJob::QueueAdapters::SolidQueueExt
|
|
|
109
112
|
end
|
|
110
113
|
end
|
|
111
114
|
|
|
115
|
+
def filter_raw_data_arguments(raw_data)
|
|
116
|
+
raw_data.deep_dup.tap do |filtered_raw_data|
|
|
117
|
+
filtered_raw_data["arguments"]["arguments"] = MissionControl::Jobs.job_arguments_filter.apply_to(filtered_raw_data.dig("arguments", "arguments"))
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
112
121
|
def status_from_solid_queue_job(solid_queue_job)
|
|
113
122
|
SolidQueueJobs::STATUS_MAP.invert[solid_queue_job.status]
|
|
114
123
|
end
|
|
@@ -120,6 +129,11 @@ module ActiveJob::QueueAdapters::SolidQueueExt
|
|
|
120
129
|
message: solid_queue_job.failed_execution.message,
|
|
121
130
|
backtrace: solid_queue_job.failed_execution.backtrace || []
|
|
122
131
|
end
|
|
132
|
+
rescue JSON::ParserError
|
|
133
|
+
ActiveJob::ExecutionError.new \
|
|
134
|
+
error_class: "",
|
|
135
|
+
message: solid_queue_job.failed_execution.error_before_type_cast,
|
|
136
|
+
backtrace: []
|
|
123
137
|
end
|
|
124
138
|
|
|
125
139
|
def dispatch_immediately(job)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Replaces argument values with [FILTERED] for any keys that match a filter.
|
|
2
|
+
class MissionControl::Jobs::ArgumentsFilter
|
|
3
|
+
FILTERED = "[FILTERED]"
|
|
4
|
+
|
|
5
|
+
def initialize(filter)
|
|
6
|
+
@filter = filter
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def apply_to(arguments)
|
|
10
|
+
case arguments
|
|
11
|
+
when Array
|
|
12
|
+
arguments.map { |a| apply_to(a) }
|
|
13
|
+
when Hash
|
|
14
|
+
arguments.map do |k, v|
|
|
15
|
+
[ k, filter.include?(k.to_s) ? FILTERED : v ]
|
|
16
|
+
end.to_h
|
|
17
|
+
else
|
|
18
|
+
arguments
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
attr_reader :filter
|
|
24
|
+
end
|
|
@@ -34,12 +34,18 @@ module MissionControl
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
initializer "mission_control-jobs.host_route_helpers" do |app|
|
|
38
|
+
ActiveSupport.on_load(:after_routes_loaded) do
|
|
39
|
+
MissionControl::Jobs::HostRouteHelpers.define_from(app.routes, MissionControl::Jobs::Engine.routes)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
37
43
|
initializer "mission_control-jobs.http_basic_auth" do |app|
|
|
38
44
|
MissionControl::Jobs.http_basic_auth_user ||= app.credentials.dig(:mission_control, :http_basic_auth_user)
|
|
39
45
|
MissionControl::Jobs.http_basic_auth_password ||= app.credentials.dig(:mission_control, :http_basic_auth_password)
|
|
40
46
|
end
|
|
41
47
|
|
|
42
|
-
initializer "mission_control-jobs.active_job.extensions" do
|
|
48
|
+
initializer "mission_control-jobs.active_job.extensions", before: "active_job.set_configs" do
|
|
43
49
|
ActiveSupport.on_load :active_job do
|
|
44
50
|
include ActiveJob::Querying
|
|
45
51
|
include ActiveJob::Executing
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Route helpers of the host app that the engine doesn't define itself, routed through +main_app+.
|
|
2
|
+
#
|
|
3
|
+
# Mission Control's controllers inherit from the host app's +ApplicationController+ (see
|
|
4
|
+
# +base_controller_class+), so host code such as a +before_action+ redirecting to
|
|
5
|
+
# +new_session_path+ runs inside the engine, where route helpers resolve against the engine's
|
|
6
|
+
# routes and raise +ActionController::UrlGenerationError+. This module defines, for every route
|
|
7
|
+
# helper the host app has and the engine doesn't, a method delegating to the host app's routes,
|
|
8
|
+
# so that code keeps working unchanged.
|
|
9
|
+
#
|
|
10
|
+
# Helpers defined by both, like +root_path+, keep resolving to the engine's, as in any isolated
|
|
11
|
+
# engine; use +main_app.root_path+ for the host's.
|
|
12
|
+
module MissionControl::Jobs::HostRouteHelpers
|
|
13
|
+
class << self
|
|
14
|
+
def define_from(host_routes, engine_routes)
|
|
15
|
+
undefine_all
|
|
16
|
+
|
|
17
|
+
(host_routes.named_routes.helper_names - engine_routes.named_routes.helper_names).each do |name|
|
|
18
|
+
define_method(name) { |*args| main_app.public_send(name, *args) }
|
|
19
|
+
defined_helpers << name
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def undefine_all
|
|
25
|
+
defined_helpers.each { |name| remove_method(name) }
|
|
26
|
+
defined_helpers.clear
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def defined_helpers
|
|
30
|
+
@defined_helpers ||= []
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/mission_control/jobs.rb
CHANGED
|
@@ -25,11 +25,18 @@ module MissionControl
|
|
|
25
25
|
|
|
26
26
|
mattr_accessor :show_console_help, default: true
|
|
27
27
|
mattr_accessor :backtrace_cleaner
|
|
28
|
+
mattr_accessor :back_to_main_app_path
|
|
28
29
|
|
|
29
30
|
mattr_accessor :importmap, default: Importmap::Map.new
|
|
30
31
|
|
|
31
32
|
mattr_accessor :http_basic_auth_user
|
|
32
33
|
mattr_accessor :http_basic_auth_password
|
|
33
34
|
mattr_accessor :http_basic_auth_enabled, default: true
|
|
35
|
+
|
|
36
|
+
mattr_accessor :filter_arguments, default: []
|
|
37
|
+
|
|
38
|
+
def self.job_arguments_filter
|
|
39
|
+
MissionControl::Jobs::ArgumentsFilter.new(filter_arguments)
|
|
40
|
+
end
|
|
34
41
|
end
|
|
35
42
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mission_control-jobs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jorge Manrubia
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-08-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -465,6 +465,7 @@ files:
|
|
|
465
465
|
- lib/mission_control/jobs/adapter.rb
|
|
466
466
|
- lib/mission_control/jobs/application.rb
|
|
467
467
|
- lib/mission_control/jobs/applications.rb
|
|
468
|
+
- lib/mission_control/jobs/arguments_filter.rb
|
|
468
469
|
- lib/mission_control/jobs/authentication.rb
|
|
469
470
|
- lib/mission_control/jobs/console/connect_to.rb
|
|
470
471
|
- lib/mission_control/jobs/console/context.rb
|
|
@@ -472,6 +473,7 @@ files:
|
|
|
472
473
|
- lib/mission_control/jobs/engine.rb
|
|
473
474
|
- lib/mission_control/jobs/errors/incompatible_adapter.rb
|
|
474
475
|
- lib/mission_control/jobs/errors/resource_not_found.rb
|
|
476
|
+
- lib/mission_control/jobs/host_route_helpers.rb
|
|
475
477
|
- lib/mission_control/jobs/i18n_config.rb
|
|
476
478
|
- lib/mission_control/jobs/identified_by_name.rb
|
|
477
479
|
- lib/mission_control/jobs/identified_elements.rb
|