maintenance_tasks 1.3.0 → 1.7.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 +288 -45
- data/app/controllers/maintenance_tasks/tasks_controller.rb +7 -2
- data/app/helpers/maintenance_tasks/application_helper.rb +1 -0
- data/app/helpers/maintenance_tasks/tasks_helper.rb +19 -14
- data/app/jobs/concerns/maintenance_tasks/task_job_concern.rb +44 -23
- data/app/models/maintenance_tasks/application_record.rb +1 -0
- data/app/models/maintenance_tasks/csv_collection_builder.rb +33 -0
- data/app/models/maintenance_tasks/null_collection_builder.rb +31 -0
- data/app/models/maintenance_tasks/progress.rb +8 -3
- data/app/models/maintenance_tasks/run.rb +224 -18
- data/app/models/maintenance_tasks/runner.rb +26 -7
- data/app/models/maintenance_tasks/runs_page.rb +1 -0
- data/app/models/maintenance_tasks/task.rb +225 -0
- data/app/models/maintenance_tasks/task_data.rb +24 -3
- data/app/validators/maintenance_tasks/run_status_validator.rb +2 -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 +18 -1
- data/app/views/maintenance_tasks/runs/info/_custom.html.erb +0 -0
- data/app/views/maintenance_tasks/runs/info/_errored.html.erb +0 -2
- data/app/views/maintenance_tasks/runs/info/_paused.html.erb +2 -2
- data/app/views/maintenance_tasks/runs/info/_running.html.erb +3 -5
- data/app/views/maintenance_tasks/tasks/_custom.html.erb +0 -0
- data/app/views/maintenance_tasks/tasks/_task.html.erb +19 -1
- data/app/views/maintenance_tasks/tasks/index.html.erb +2 -2
- data/app/views/maintenance_tasks/tasks/show.html.erb +37 -2
- data/config/routes.rb +1 -0
- data/db/migrate/20201211151756_create_maintenance_tasks_runs.rb +1 -0
- data/db/migrate/20210225152418_remove_index_on_task_name.rb +1 -0
- data/db/migrate/20210517131953_add_arguments_to_maintenance_tasks_runs.rb +7 -0
- data/db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb +8 -0
- data/lib/generators/maintenance_tasks/install_generator.rb +1 -0
- data/lib/generators/maintenance_tasks/templates/task.rb.tt +3 -1
- data/lib/maintenance_tasks/cli.rb +11 -4
- data/lib/maintenance_tasks/engine.rb +15 -1
- data/lib/maintenance_tasks.rb +14 -1
- data/lib/patches/active_record_batch_enumerator.rb +23 -0
- metadata +15 -11
- data/app/models/maintenance_tasks/csv_collection.rb +0 -33
- data/app/tasks/maintenance_tasks/task.rb +0 -133
- data/app/views/maintenance_tasks/runs/_info.html.erb +0 -16
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.7.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:
|
11
|
+
date: 2022-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -97,21 +97,24 @@ files:
|
|
97
97
|
- app/jobs/concerns/maintenance_tasks/task_job_concern.rb
|
98
98
|
- app/jobs/maintenance_tasks/task_job.rb
|
99
99
|
- app/models/maintenance_tasks/application_record.rb
|
100
|
-
- app/models/maintenance_tasks/
|
100
|
+
- app/models/maintenance_tasks/csv_collection_builder.rb
|
101
|
+
- app/models/maintenance_tasks/null_collection_builder.rb
|
101
102
|
- app/models/maintenance_tasks/progress.rb
|
102
103
|
- app/models/maintenance_tasks/run.rb
|
103
104
|
- app/models/maintenance_tasks/runner.rb
|
104
105
|
- app/models/maintenance_tasks/runs_page.rb
|
106
|
+
- app/models/maintenance_tasks/task.rb
|
105
107
|
- app/models/maintenance_tasks/task_data.rb
|
106
108
|
- app/models/maintenance_tasks/ticker.rb
|
107
|
-
- app/tasks/maintenance_tasks/task.rb
|
108
109
|
- app/validators/maintenance_tasks/run_status_validator.rb
|
109
110
|
- app/views/layouts/maintenance_tasks/_navbar.html.erb
|
110
111
|
- app/views/layouts/maintenance_tasks/application.html.erb
|
111
|
-
- app/views/maintenance_tasks/runs/
|
112
|
+
- app/views/maintenance_tasks/runs/_arguments.html.erb
|
113
|
+
- app/views/maintenance_tasks/runs/_csv.html.erb
|
112
114
|
- app/views/maintenance_tasks/runs/_run.html.erb
|
113
115
|
- app/views/maintenance_tasks/runs/info/_cancelled.html.erb
|
114
116
|
- app/views/maintenance_tasks/runs/info/_cancelling.html.erb
|
117
|
+
- app/views/maintenance_tasks/runs/info/_custom.html.erb
|
115
118
|
- app/views/maintenance_tasks/runs/info/_enqueued.html.erb
|
116
119
|
- app/views/maintenance_tasks/runs/info/_errored.html.erb
|
117
120
|
- app/views/maintenance_tasks/runs/info/_interrupted.html.erb
|
@@ -119,12 +122,15 @@ files:
|
|
119
122
|
- app/views/maintenance_tasks/runs/info/_pausing.html.erb
|
120
123
|
- app/views/maintenance_tasks/runs/info/_running.html.erb
|
121
124
|
- app/views/maintenance_tasks/runs/info/_succeeded.html.erb
|
125
|
+
- app/views/maintenance_tasks/tasks/_custom.html.erb
|
122
126
|
- app/views/maintenance_tasks/tasks/_task.html.erb
|
123
127
|
- app/views/maintenance_tasks/tasks/index.html.erb
|
124
128
|
- app/views/maintenance_tasks/tasks/show.html.erb
|
125
129
|
- config/routes.rb
|
126
130
|
- db/migrate/20201211151756_create_maintenance_tasks_runs.rb
|
127
131
|
- db/migrate/20210225152418_remove_index_on_task_name.rb
|
132
|
+
- db/migrate/20210517131953_add_arguments_to_maintenance_tasks_runs.rb
|
133
|
+
- db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb
|
128
134
|
- exe/maintenance_tasks
|
129
135
|
- lib/generators/maintenance_tasks/install_generator.rb
|
130
136
|
- lib/generators/maintenance_tasks/task_generator.rb
|
@@ -135,17 +141,15 @@ files:
|
|
135
141
|
- lib/maintenance_tasks.rb
|
136
142
|
- lib/maintenance_tasks/cli.rb
|
137
143
|
- lib/maintenance_tasks/engine.rb
|
144
|
+
- lib/patches/active_record_batch_enumerator.rb
|
138
145
|
- lib/tasks/maintenance_tasks_tasks.rake
|
139
146
|
homepage: https://github.com/Shopify/maintenance_tasks
|
140
147
|
licenses:
|
141
148
|
- MIT
|
142
149
|
metadata:
|
143
|
-
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.
|
150
|
+
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.7.0
|
144
151
|
allowed_push_host: https://rubygems.org
|
145
|
-
post_install_message:
|
146
|
-
Thank you for installing Maintenance Tasks 1.3.0. To complete, please run:
|
147
|
-
|
148
|
-
rails generate maintenance_tasks:install
|
152
|
+
post_install_message:
|
149
153
|
rdoc_options: []
|
150
154
|
require_paths:
|
151
155
|
- lib
|
@@ -160,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
164
|
- !ruby/object:Gem::Version
|
161
165
|
version: '0'
|
162
166
|
requirements: []
|
163
|
-
rubygems_version: 3.2.
|
167
|
+
rubygems_version: 3.2.20
|
164
168
|
signing_key:
|
165
169
|
specification_version: 4
|
166
170
|
summary: A Rails engine for queuing and managing maintenance tasks
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "csv"
|
4
|
-
|
5
|
-
module MaintenanceTasks
|
6
|
-
# Module that is included into Task classes by Task.csv_collection for
|
7
|
-
# processing CSV files.
|
8
|
-
#
|
9
|
-
# @api private
|
10
|
-
module CsvCollection
|
11
|
-
# The contents of a CSV file to be processed by a Task.
|
12
|
-
#
|
13
|
-
# @return [String] the content of the CSV file to process.
|
14
|
-
attr_accessor :csv_content
|
15
|
-
|
16
|
-
# Defines the collection to be iterated over, based on the provided CSV.
|
17
|
-
#
|
18
|
-
# @return [CSV] the CSV object constructed from the specified CSV content,
|
19
|
-
# with headers.
|
20
|
-
def collection
|
21
|
-
CSV.new(csv_content, headers: true)
|
22
|
-
end
|
23
|
-
|
24
|
-
# The number of rows to be processed. Excludes the header row from the count
|
25
|
-
# and assumed a trailing new line in the CSV file. Note that this number is
|
26
|
-
# an approximation based on the number of new lines.
|
27
|
-
#
|
28
|
-
# @return [Integer] the approximate number of rows to process.
|
29
|
-
def count
|
30
|
-
csv_content.count("\n") - 1
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module MaintenanceTasks
|
3
|
-
# Base class that is inherited by the host application's task classes.
|
4
|
-
class Task
|
5
|
-
extend ActiveSupport::DescendantsTracker
|
6
|
-
|
7
|
-
class NotFoundError < NameError; end
|
8
|
-
|
9
|
-
# The throttle conditions for a given Task. This is provided as an array of
|
10
|
-
# hashes, with each hash specifying two keys: throttle_condition and
|
11
|
-
# backoff. Note that Tasks inherit conditions from their superclasses.
|
12
|
-
#
|
13
|
-
# @api private
|
14
|
-
class_attribute :throttle_conditions, default: []
|
15
|
-
|
16
|
-
class << self
|
17
|
-
# Finds a Task with the given name.
|
18
|
-
#
|
19
|
-
# @param name [String] the name of the Task to be found.
|
20
|
-
#
|
21
|
-
# @return [Task] the Task with the given name.
|
22
|
-
#
|
23
|
-
# @raise [NotFoundError] if a Task with the given name does not exist.
|
24
|
-
def named(name)
|
25
|
-
task = name.safe_constantize
|
26
|
-
raise NotFoundError.new("Task #{name} not found.", name) unless task
|
27
|
-
unless task.is_a?(Class) && task < Task
|
28
|
-
raise NotFoundError.new("#{name} is not a Task.", name)
|
29
|
-
end
|
30
|
-
task
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns a list of concrete classes that inherit from the Task
|
34
|
-
# superclass.
|
35
|
-
#
|
36
|
-
# @return [Array<Class>] the list of classes.
|
37
|
-
def available_tasks
|
38
|
-
load_constants
|
39
|
-
descendants
|
40
|
-
end
|
41
|
-
|
42
|
-
# Make this Task a task that handles CSV.
|
43
|
-
#
|
44
|
-
# An input to upload a CSV will be added in the form to start a Run. The
|
45
|
-
# collection and count method are implemented.
|
46
|
-
def csv_collection
|
47
|
-
if !defined?(ActiveStorage) || !ActiveStorage::Attachment.table_exists?
|
48
|
-
raise NotImplementedError, "Active Storage needs to be installed\n"\
|
49
|
-
"To resolve this issue run: bin/rails active_storage:install"
|
50
|
-
end
|
51
|
-
include(CsvCollection)
|
52
|
-
end
|
53
|
-
|
54
|
-
# Processes one item.
|
55
|
-
#
|
56
|
-
# Especially useful for tests.
|
57
|
-
#
|
58
|
-
# @param item the item to process.
|
59
|
-
def process(item)
|
60
|
-
new.process(item)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns the collection for this Task.
|
64
|
-
#
|
65
|
-
# Especially useful for tests.
|
66
|
-
#
|
67
|
-
# @return the collection.
|
68
|
-
def collection
|
69
|
-
new.collection
|
70
|
-
end
|
71
|
-
|
72
|
-
# Returns the count of items for this Task.
|
73
|
-
#
|
74
|
-
# Especially useful for tests.
|
75
|
-
#
|
76
|
-
# @return the count of items.
|
77
|
-
def count
|
78
|
-
new.count
|
79
|
-
end
|
80
|
-
|
81
|
-
# Add a condition under which this Task will be throttled.
|
82
|
-
#
|
83
|
-
# @param backoff [ActiveSupport::Duration] optionally, a custom backoff
|
84
|
-
# can be specified. This is the time to wait before retrying the Task.
|
85
|
-
# If no value is specified, it defaults to 30 seconds.
|
86
|
-
# @yieldreturn [Boolean] where the throttle condition is being met,
|
87
|
-
# indicating that the Task should throttle.
|
88
|
-
def throttle_on(backoff: 30.seconds, &condition)
|
89
|
-
self.throttle_conditions += [
|
90
|
-
{ throttle_on: condition, backoff: backoff },
|
91
|
-
]
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def load_constants
|
97
|
-
namespace = MaintenanceTasks.tasks_module.safe_constantize
|
98
|
-
return unless namespace
|
99
|
-
namespace.constants.map { |constant| namespace.const_get(constant) }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Placeholder method to raise in case a subclass fails to implement the
|
104
|
-
# expected instance method.
|
105
|
-
#
|
106
|
-
# @raise [NotImplementedError] with a message advising subclasses to
|
107
|
-
# implement an override for this method.
|
108
|
-
def collection
|
109
|
-
raise NoMethodError, "#{self.class.name} must implement `collection`."
|
110
|
-
end
|
111
|
-
|
112
|
-
# Placeholder method to raise in case a subclass fails to implement the
|
113
|
-
# expected instance method.
|
114
|
-
#
|
115
|
-
# @param _item [Object] the current item from the enumerator being iterated.
|
116
|
-
#
|
117
|
-
# @raise [NotImplementedError] with a message advising subclasses to
|
118
|
-
# implement an override for this method.
|
119
|
-
def process(_item)
|
120
|
-
raise NoMethodError, "#{self.class.name} must implement `process`."
|
121
|
-
end
|
122
|
-
|
123
|
-
# Total count of iterations to be performed.
|
124
|
-
#
|
125
|
-
# Tasks override this method to define the total amount of iterations
|
126
|
-
# expected at the start of the run. Return +nil+ if the amount is
|
127
|
-
# undefined, or counting would be prohibitive for your database.
|
128
|
-
#
|
129
|
-
# @return [Integer, nil]
|
130
|
-
def count
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
@@ -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 %>
|