maintenance_tasks 1.4.0 → 1.5.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 +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 %>
|