maintenance_tasks 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -0
- data/app/jobs/concerns/maintenance_tasks/task_job_concern.rb +0 -1
- data/app/models/maintenance_tasks/run.rb +3 -2
- data/app/models/maintenance_tasks/runner.rb +6 -5
- data/app/models/maintenance_tasks/task_data.rb +1 -1
- data/app/validators/maintenance_tasks/run_status_validator.rb +1 -2
- data/app/views/maintenance_tasks/runs/_arguments.html.erb +22 -0
- data/app/views/maintenance_tasks/runs/_csv.html.erb +5 -0
- data/app/views/maintenance_tasks/runs/_run.html.erb +14 -1
- data/app/views/maintenance_tasks/runs/info/_errored.html.erb +0 -2
- data/app/views/maintenance_tasks/runs/info/_running.html.erb +3 -5
- data/app/views/maintenance_tasks/tasks/_task.html.erb +15 -1
- data/app/views/maintenance_tasks/tasks/show.html.erb +23 -4
- data/lib/maintenance_tasks.rb +10 -0
- data/lib/maintenance_tasks/engine.rb +4 -0
- metadata +6 -5
- data/app/views/maintenance_tasks/runs/_info.html.erb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c13ec8d79682d304378d636955e9726cd1d67ebb167a549a2d6479f7eea6712
|
4
|
+
data.tar.gz: bf7026b08f0f442c3c074118dfca1cbae4babd7d234b97dc63cf66cdf94db67b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b41ee8a4ccaf28d590d7acd2a81fd5123dd3e81b552454082313d3a183b5840eb3ff130ab6c0a40c3e05112899680cee03bbec74c39e11bf0f91dff9955edb1
|
7
|
+
data.tar.gz: 42321e823247c83d58ead579070a5b007c7c0089601c7bcf587af311be715eb791102b94c2fdff513010816977c4c318297bb9f946726b3bd08066bc0ce295b2
|
data/README.md
CHANGED
@@ -537,6 +537,23 @@ MaintenanceTasks.active_storage_service = :internal
|
|
537
537
|
There is no need to configure this option if your application uses only one
|
538
538
|
storage service per environment.
|
539
539
|
|
540
|
+
#### Customizing the backtrace cleaner
|
541
|
+
|
542
|
+
`MaintenanceTasks.backtrace_cleaner` can be configured to specify a backtrace
|
543
|
+
cleaner to use when a Task errors and the backtrace is cleaned and persisted.
|
544
|
+
An `ActiveSupport::BacktraceCleaner` should be used.
|
545
|
+
|
546
|
+
```ruby
|
547
|
+
# config/initializers/maintenance_tasks.rb
|
548
|
+
cleaner = ActiveSupport::BacktraceCleaner.new
|
549
|
+
cleaner.add_silencer { |line| line =~ /ignore_this_dir/ }
|
550
|
+
|
551
|
+
MaintenanceTasks.backtrace_cleaner = cleaner
|
552
|
+
```
|
553
|
+
|
554
|
+
If none is specified, the default `Rails.backtrace_cleaner` will be used to
|
555
|
+
clean backtraces.
|
556
|
+
|
540
557
|
## Upgrading
|
541
558
|
|
542
559
|
Use bundler to check for and upgrade to newer versions. After installing a new
|
@@ -548,6 +565,16 @@ $ bin/rails generate maintenance_tasks:install
|
|
548
565
|
|
549
566
|
This ensures that new migrations are installed and run as well.
|
550
567
|
|
568
|
+
**What if I've deleted my previous Maintenance Task migrations?**
|
569
|
+
|
570
|
+
The install command will attempt to reinstall these old migrations and migrating
|
571
|
+
the database will cause problems. Use `bin/rails generate maintenance_tasks:install:migrations`
|
572
|
+
to copy the gem's migrations to your `db/migrate` folder. Check the release
|
573
|
+
notes to see if any new migrations were added since your last gem upgrade.
|
574
|
+
Ensure that these are kept, but remove any migrations that already ran.
|
575
|
+
|
576
|
+
Run the migrations using `bin/rails db:migrate`.
|
577
|
+
|
551
578
|
## Contributing
|
552
579
|
|
553
580
|
Would you like to report an issue or contribute with code? We accept issues and
|
@@ -564,6 +591,7 @@ are merged.
|
|
564
591
|
Once a release is ready, follow these steps:
|
565
592
|
|
566
593
|
* Update `spec.version` in `maintenance_tasks.gemspec`.
|
594
|
+
* Run `bundle install` to bump the `Gemfile.lock` version of the gem.
|
567
595
|
* Open a PR and merge on approval.
|
568
596
|
* Deploy via [Shipit][shipit] and see the new version on
|
569
597
|
<https://rubygems.org/gems/maintenance_tasks>.
|
@@ -27,6 +27,7 @@ module MaintenanceTasks
|
|
27
27
|
]
|
28
28
|
COMPLETED_STATUSES = [:succeeded, :errored, :cancelled]
|
29
29
|
COMPLETED_RUNS_LIMIT = 10
|
30
|
+
STUCK_TASK_TIMEOUT = 5.minutes
|
30
31
|
|
31
32
|
enum status: STATUSES.to_h { |status| [status, status.to_s] }
|
32
33
|
|
@@ -90,7 +91,7 @@ module MaintenanceTasks
|
|
90
91
|
status: :errored,
|
91
92
|
error_class: error.class.to_s,
|
92
93
|
error_message: error.message,
|
93
|
-
backtrace:
|
94
|
+
backtrace: MaintenanceTasks.backtrace_cleaner.clean(error.backtrace),
|
94
95
|
ended_at: Time.now,
|
95
96
|
)
|
96
97
|
end
|
@@ -190,7 +191,7 @@ module MaintenanceTasks
|
|
190
191
|
#
|
191
192
|
# @return [Boolean] whether the Run is stuck.
|
192
193
|
def stuck?
|
193
|
-
cancelling? && updated_at <=
|
194
|
+
cancelling? && updated_at <= STUCK_TASK_TIMEOUT.ago
|
194
195
|
end
|
195
196
|
|
196
197
|
# Performs validation on the presence of a :csv_file attachment.
|
@@ -51,17 +51,18 @@ module MaintenanceTasks
|
|
51
51
|
run = Run.active.find_by(task_name: name) ||
|
52
52
|
Run.new(task_name: name, arguments: arguments)
|
53
53
|
run.csv_file.attach(csv_file) if csv_file
|
54
|
-
|
55
|
-
run.
|
56
|
-
enqueue(run)
|
54
|
+
job = MaintenanceTasks.job.constantize.new(run)
|
55
|
+
run.job_id = job.job_id
|
57
56
|
yield run if block_given?
|
57
|
+
run.enqueued!
|
58
|
+
enqueue(run, job)
|
58
59
|
Task.named(name)
|
59
60
|
end
|
60
61
|
|
61
62
|
private
|
62
63
|
|
63
|
-
def enqueue(run)
|
64
|
-
unless
|
64
|
+
def enqueue(run, job)
|
65
|
+
unless job.enqueue
|
65
66
|
raise "The job to perform #{run.task_name} could not be enqueued. "\
|
66
67
|
"Enqueuing has been prevented by a callback."
|
67
68
|
end
|
@@ -40,7 +40,7 @@ module MaintenanceTasks
|
|
40
40
|
def available_tasks
|
41
41
|
task_names = Task.available_tasks.map(&:name)
|
42
42
|
available_task_runs = Run.where(task_name: task_names)
|
43
|
-
last_runs = Run.where(
|
43
|
+
last_runs = Run.with_attached_csv.where(
|
44
44
|
id: available_task_runs.select("MAX(id) as id").group(:task_name)
|
45
45
|
)
|
46
46
|
|
@@ -48,9 +48,8 @@ module MaintenanceTasks
|
|
48
48
|
"errored",
|
49
49
|
],
|
50
50
|
# paused -> enqueued occurs when the task is resumed after being paused.
|
51
|
-
# paused -> cancelling when the user cancels the task after it is paused.
|
52
51
|
# paused -> cancelled when the user cancels the task after it is paused.
|
53
|
-
"paused" => ["enqueued", "
|
52
|
+
"paused" => ["enqueued", "cancelled"],
|
54
53
|
# interrupted -> running occurs when the task is resumed after being
|
55
54
|
# interrupted by the job infrastructure.
|
56
55
|
# interrupted -> pausing occurs when the task is paused by the user while
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% if run.arguments.present? %>
|
2
|
+
<div class="table-container">
|
3
|
+
<h6 class="title is-6">Arguments:</h6>
|
4
|
+
<table class="table">
|
5
|
+
<tbody>
|
6
|
+
<% run.arguments.each do |key, value| %>
|
7
|
+
<tr>
|
8
|
+
<td class="is-family-monospace"><%= key %></td>
|
9
|
+
<td>
|
10
|
+
<% next if value.nil? || value.empty? %>
|
11
|
+
<% if value.include?("\n") %>
|
12
|
+
<pre><%= value %><pre>
|
13
|
+
<% else %>
|
14
|
+
<code><%= value %><code>
|
15
|
+
<% end %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
</tbody>
|
20
|
+
</table>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
@@ -1,3 +1,16 @@
|
|
1
1
|
<div class="box">
|
2
|
-
|
2
|
+
<h5 class="title is-5">
|
3
|
+
<%= time_tag run.created_at, title: run.created_at %>
|
4
|
+
<%= status_tag run.status %>
|
5
|
+
</h5>
|
6
|
+
|
7
|
+
<%= progress run %>
|
8
|
+
|
9
|
+
<div class="content">
|
10
|
+
<%= render "maintenance_tasks/runs/info/#{run.status}", run: run %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<%= render "maintenance_tasks/runs/csv", run: run %>
|
14
|
+
<%= tag.hr if run.csv_file.present? && run.arguments.present? %>
|
15
|
+
<%= render "maintenance_tasks/runs/arguments", run: run %>
|
3
16
|
</div>
|
@@ -1,5 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<% end %>
|
5
|
-
</p>
|
1
|
+
<% if (time_to_completion = run.time_to_completion) %>
|
2
|
+
<p>Running for <%= time_running_in_words(run) %>. <%= distance_of_time_in_words(time_to_completion).capitalize %> remaining.</p>
|
3
|
+
<% end %>
|
@@ -4,5 +4,19 @@
|
|
4
4
|
<%= status_tag(task.status) %>
|
5
5
|
</h3>
|
6
6
|
|
7
|
-
|
7
|
+
<% if (run = task.last_run) %>
|
8
|
+
<h5 class="title is-5">
|
9
|
+
<%= time_tag run.created_at, title: run.created_at %>
|
10
|
+
</h5>
|
11
|
+
|
12
|
+
<%= progress run %>
|
13
|
+
|
14
|
+
<div class="content">
|
15
|
+
<%= render "maintenance_tasks/runs/info/#{run.status}", run: run %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<%= render "maintenance_tasks/runs/csv", run: run %>
|
19
|
+
<%= tag.hr if run.csv_file.present? && run.arguments.present? %>
|
20
|
+
<%= render "maintenance_tasks/runs/arguments", run: run %>
|
21
|
+
<% end %>
|
8
22
|
</div>
|
@@ -4,10 +4,25 @@
|
|
4
4
|
<%= @task %> <%= status_tag(@task.status) %>
|
5
5
|
</h1>
|
6
6
|
|
7
|
-
|
7
|
+
<% last_run = @task.last_run %>
|
8
|
+
<% if last_run %>
|
9
|
+
<h5 class="title is-5">
|
10
|
+
<%= time_tag last_run.created_at, title: last_run.created_at %>
|
11
|
+
</h5>
|
12
|
+
|
13
|
+
<%= progress last_run %>
|
14
|
+
|
15
|
+
<div class="content">
|
16
|
+
<%= render "maintenance_tasks/runs/info/#{last_run.status}", run: last_run %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<%= render "maintenance_tasks/runs/csv", run: last_run %>
|
20
|
+
<%= tag.hr if last_run.csv_file.present? %>
|
21
|
+
<%= render "maintenance_tasks/runs/arguments", run: last_run %>
|
22
|
+
<%= tag.hr if last_run.arguments.present? %>
|
23
|
+
<% end %>
|
8
24
|
|
9
25
|
<div class="buttons">
|
10
|
-
<% last_run = @task.last_run %>
|
11
26
|
<% if last_run.nil? || last_run.completed? %>
|
12
27
|
<%= form_with url: run_task_path(@task), method: :put do |form| %>
|
13
28
|
<% if @task.csv_task? %>
|
@@ -20,8 +35,12 @@
|
|
20
35
|
<div class="block">
|
21
36
|
<%= form.fields_for :task_arguments do |ff| %>
|
22
37
|
<% @task.parameter_names.each do |parameter| %>
|
23
|
-
|
24
|
-
|
38
|
+
<div class="field">
|
39
|
+
<%= ff.label parameter, parameter, class: "label is-family-monospace" %>
|
40
|
+
<div class="control">
|
41
|
+
<%= ff.text_area parameter, class: "textarea" %>
|
42
|
+
</div>
|
43
|
+
</div>
|
25
44
|
<% end %>
|
26
45
|
<% end %>
|
27
46
|
</div>
|
data/lib/maintenance_tasks.rb
CHANGED
@@ -52,6 +52,16 @@ module MaintenanceTasks
|
|
52
52
|
# app's config/storage.yml.
|
53
53
|
mattr_accessor :active_storage_service
|
54
54
|
|
55
|
+
# @!attribute backtrace_cleaner
|
56
|
+
# @scope class
|
57
|
+
#
|
58
|
+
# The Active Support backtrace cleaner that will be used to clean the
|
59
|
+
# backtrace of a Task that errors.
|
60
|
+
#
|
61
|
+
# @return [ActiveSupport::BacktraceCleaner, nil] the backtrace cleaner to
|
62
|
+
# use when cleaning a Run's backtrace.
|
63
|
+
mattr_accessor :backtrace_cleaner
|
64
|
+
|
55
65
|
# @private
|
56
66
|
def self.error_handler
|
57
67
|
return @error_handler if defined?(@error_handler)
|
@@ -11,6 +11,10 @@ module MaintenanceTasks
|
|
11
11
|
eager_load! unless Rails.autoloaders.zeitwerk_enabled?
|
12
12
|
end
|
13
13
|
|
14
|
+
initializer "maintenance_tasks.configs" do
|
15
|
+
MaintenanceTasks.backtrace_cleaner = Rails.backtrace_cleaner
|
16
|
+
end
|
17
|
+
|
14
18
|
config.to_prepare do
|
15
19
|
_ = TaskJobConcern # load this for JobIteration compatibility check
|
16
20
|
unless Rails.autoloaders.zeitwerk_enabled?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maintenance_tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -108,7 +108,8 @@ files:
|
|
108
108
|
- app/validators/maintenance_tasks/run_status_validator.rb
|
109
109
|
- app/views/layouts/maintenance_tasks/_navbar.html.erb
|
110
110
|
- app/views/layouts/maintenance_tasks/application.html.erb
|
111
|
-
- app/views/maintenance_tasks/runs/
|
111
|
+
- app/views/maintenance_tasks/runs/_arguments.html.erb
|
112
|
+
- app/views/maintenance_tasks/runs/_csv.html.erb
|
112
113
|
- app/views/maintenance_tasks/runs/_run.html.erb
|
113
114
|
- app/views/maintenance_tasks/runs/info/_cancelled.html.erb
|
114
115
|
- app/views/maintenance_tasks/runs/info/_cancelling.html.erb
|
@@ -142,7 +143,7 @@ homepage: https://github.com/Shopify/maintenance_tasks
|
|
142
143
|
licenses:
|
143
144
|
- MIT
|
144
145
|
metadata:
|
145
|
-
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.
|
146
|
+
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.5.0
|
146
147
|
allowed_push_host: https://rubygems.org
|
147
148
|
post_install_message:
|
148
149
|
rdoc_options: []
|
@@ -159,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
160
|
- !ruby/object:Gem::Version
|
160
161
|
version: '0'
|
161
162
|
requirements: []
|
162
|
-
rubygems_version: 3.2.
|
163
|
+
rubygems_version: 3.2.20
|
163
164
|
signing_key:
|
164
165
|
specification_version: 4
|
165
166
|
summary: A Rails engine for queuing and managing maintenance tasks
|
@@ -1,16 +0,0 @@
|
|
1
|
-
<h5 class="title is-5">
|
2
|
-
<%= time_tag run.created_at, title: run.created_at %>
|
3
|
-
<%= status_tag run.status if with_status %>
|
4
|
-
</h5>
|
5
|
-
|
6
|
-
<%= progress run %>
|
7
|
-
|
8
|
-
<div class="content">
|
9
|
-
<%= render "maintenance_tasks/runs/info/#{run.status}", run: run %>
|
10
|
-
</div>
|
11
|
-
|
12
|
-
<% if run.csv_file.present? %>
|
13
|
-
<div class="block">
|
14
|
-
<%= link_to('Download CSV', csv_file_download_path(run)) %>
|
15
|
-
</div>
|
16
|
-
<% end %>
|