maintenance_tasks 1.6.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 +23 -8
- data/app/controllers/maintenance_tasks/tasks_controller.rb +2 -1
- data/app/helpers/maintenance_tasks/tasks_helper.rb +19 -0
- data/app/jobs/concerns/maintenance_tasks/task_job_concern.rb +16 -30
- data/app/models/maintenance_tasks/csv_collection_builder.rb +4 -3
- data/app/models/maintenance_tasks/run.rb +130 -14
- data/app/models/maintenance_tasks/task.rb +11 -5
- data/app/models/maintenance_tasks/task_data.rb +12 -1
- data/app/views/maintenance_tasks/runs/_run.html.erb +4 -0
- data/app/views/maintenance_tasks/runs/info/_custom.html.erb +0 -0
- data/app/views/maintenance_tasks/tasks/_custom.html.erb +0 -0
- data/app/views/maintenance_tasks/tasks/_task.html.erb +4 -0
- data/app/views/maintenance_tasks/tasks/show.html.erb +11 -5
- data/db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb +8 -0
- data/lib/maintenance_tasks/engine.rb +10 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6019b1623a8cc72e877154f52e8437339598f0cab121189d78692e0989e86e61
|
4
|
+
data.tar.gz: 21563dc6dffadd2e58dd551fe2b7d71297b2da36500722f5d9fed91892b1fd6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93228d08b49fab144297cb44a0aa4b9be53144ff13b88c2eba384ef29fdb47b9a8caefaf94aaf1fbfbf4584f4d544396720c17d86f3bad31508fd66dfd7507b8
|
7
|
+
data.tar.gz: cab4cebb685fddf978eeebd62a5c16867215f849d424b9ba948beba0e93f42a5fe11ee1eccc15174c1494fa16a2fa100d3a7745c5eacef2527d425895805cf29
|
data/README.md
CHANGED
@@ -114,8 +114,9 @@ title,content
|
|
114
114
|
My Title,Hello World!
|
115
115
|
```
|
116
116
|
|
117
|
-
The files uploaded to your Active Storage service provider will be renamed
|
117
|
+
The files uploaded to your Active Storage service provider will be renamed
|
118
118
|
to include an ISO8601 timestamp and the Task name in snake case format.
|
119
|
+
The CSV is expected to have a trailing newline at the end of the file.
|
119
120
|
|
120
121
|
### Processing Batch Collections
|
121
122
|
|
@@ -200,6 +201,20 @@ Tasks can define multiple throttle conditions. Throttle conditions are inherited
|
|
200
201
|
by descendants, and new conditions will be appended without impacting existing
|
201
202
|
conditions.
|
202
203
|
|
204
|
+
The backoff can also be specified as a proc:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
# app/tasks/maintenance/update_posts_throttled_task.rb
|
208
|
+
|
209
|
+
module Maintenance
|
210
|
+
class UpdatePostsThrottledTask < MaintenanceTasks::Task
|
211
|
+
throttle_on(backoff: -> { RandomBackoffGenerator.generate_duration } ) do
|
212
|
+
DatabaseStatus.unhealthy?
|
213
|
+
end
|
214
|
+
...
|
215
|
+
end
|
216
|
+
end
|
217
|
+
```
|
203
218
|
### Custom Task Parameters
|
204
219
|
|
205
220
|
Tasks may need additional information, supplied via parameters, to run.
|
@@ -241,12 +256,12 @@ The Task provides callbacks that hook into its life cycle.
|
|
241
256
|
|
242
257
|
Available callbacks are:
|
243
258
|
|
244
|
-
`after_start`
|
245
|
-
`after_pause`
|
246
|
-
`after_interrupt`
|
247
|
-
`after_cancel`
|
248
|
-
`after_complete`
|
249
|
-
`after_error`
|
259
|
+
* `after_start`
|
260
|
+
* `after_pause`
|
261
|
+
* `after_interrupt`
|
262
|
+
* `after_cancel`
|
263
|
+
* `after_complete`
|
264
|
+
* `after_error`
|
250
265
|
|
251
266
|
```ruby
|
252
267
|
module Maintenance
|
@@ -542,7 +557,7 @@ you can define an error handler:
|
|
542
557
|
|
543
558
|
MaintenanceTasks.error_handler = ->(error, task_context, _errored_element) do
|
544
559
|
Bugsnag.notify(error) do |notification|
|
545
|
-
notification.
|
560
|
+
notification.add_metadata(:task, task_context)
|
546
561
|
end
|
547
562
|
end
|
548
563
|
```
|
@@ -24,11 +24,12 @@ module MaintenanceTasks
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Runs a given Task and redirects to the Task page.
|
27
|
-
def run
|
27
|
+
def run(&block)
|
28
28
|
task = Runner.run(
|
29
29
|
name: params.fetch(:id),
|
30
30
|
csv_file: params[:csv_file],
|
31
31
|
arguments: params.fetch(:task_arguments, {}).permit!.to_h,
|
32
|
+
&block
|
32
33
|
)
|
33
34
|
redirect_to(task_path(task))
|
34
35
|
rescue ActiveRecord::RecordInvalid => error
|
@@ -100,5 +100,24 @@ module MaintenanceTasks
|
|
100
100
|
only_path: true
|
101
101
|
)
|
102
102
|
end
|
103
|
+
|
104
|
+
# Return the appropriate field tag for the parameter
|
105
|
+
def parameter_field(form_builder, parameter_name)
|
106
|
+
case form_builder.object.class.attribute_types[parameter_name]
|
107
|
+
when ActiveModel::Type::Integer, ActiveModel::Type::Decimal,
|
108
|
+
ActiveModel::Type::Float
|
109
|
+
form_builder.number_field(parameter_name)
|
110
|
+
when ActiveModel::Type::DateTime
|
111
|
+
form_builder.datetime_field(parameter_name)
|
112
|
+
when ActiveModel::Type::Date
|
113
|
+
form_builder.date_field(parameter_name)
|
114
|
+
when ActiveModel::Type::Time
|
115
|
+
form_builder.time_field(parameter_name)
|
116
|
+
when ActiveModel::Type::Boolean
|
117
|
+
form_builder.check_box(parameter_name)
|
118
|
+
else
|
119
|
+
form_builder.text_area(parameter_name, class: "textarea")
|
120
|
+
end
|
121
|
+
end
|
103
122
|
end
|
104
123
|
end
|
@@ -12,8 +12,8 @@ module MaintenanceTasks
|
|
12
12
|
before_perform(:before_perform)
|
13
13
|
|
14
14
|
on_start(:on_start)
|
15
|
-
on_complete(:on_complete)
|
16
15
|
on_shutdown(:on_shutdown)
|
16
|
+
on_complete(:on_complete)
|
17
17
|
|
18
18
|
after_perform(:after_perform)
|
19
19
|
|
@@ -63,9 +63,16 @@ module MaintenanceTasks
|
|
63
63
|
Array, or CSV.
|
64
64
|
MSG
|
65
65
|
end
|
66
|
+
throttle_enumerator(collection_enum)
|
67
|
+
end
|
66
68
|
|
69
|
+
def throttle_enumerator(collection_enum)
|
67
70
|
@task.throttle_conditions.reduce(collection_enum) do |enum, condition|
|
68
|
-
enumerator_builder.build_throttle_enumerator(
|
71
|
+
enumerator_builder.build_throttle_enumerator(
|
72
|
+
enum,
|
73
|
+
throttle_on: condition[:throttle_on],
|
74
|
+
backoff: condition[:backoff].call
|
75
|
+
)
|
69
76
|
end
|
70
77
|
end
|
71
78
|
|
@@ -105,33 +112,19 @@ module MaintenanceTasks
|
|
105
112
|
def on_start
|
106
113
|
count = @task.count
|
107
114
|
count = @enumerator&.size if count == :no_count
|
108
|
-
@run.
|
109
|
-
@task.run_callbacks(:start)
|
110
|
-
end
|
111
|
-
|
112
|
-
def on_complete
|
113
|
-
@run.status = :succeeded
|
114
|
-
@run.ended_at = Time.now
|
115
|
-
@task.run_callbacks(:complete)
|
115
|
+
@run.start(count)
|
116
116
|
end
|
117
117
|
|
118
118
|
def on_shutdown
|
119
|
-
|
120
|
-
@run.status = :cancelled
|
121
|
-
@task.run_callbacks(:cancel)
|
122
|
-
@run.ended_at = Time.now
|
123
|
-
elsif @run.pausing?
|
124
|
-
@run.status = :paused
|
125
|
-
@task.run_callbacks(:pause)
|
126
|
-
else
|
127
|
-
@run.status = :interrupted
|
128
|
-
@task.run_callbacks(:interrupt)
|
129
|
-
end
|
130
|
-
|
119
|
+
@run.job_shutdown
|
131
120
|
@run.cursor = cursor_position
|
132
121
|
@ticker.persist
|
133
122
|
end
|
134
123
|
|
124
|
+
def on_complete
|
125
|
+
@run.complete
|
126
|
+
end
|
127
|
+
|
135
128
|
# We are reopening a private part of Job Iteration's API here, so we should
|
136
129
|
# ensure the method is still defined upstream. This way, in the case where
|
137
130
|
# the method changes upstream, we catch it at load time instead of at
|
@@ -150,7 +143,7 @@ module MaintenanceTasks
|
|
150
143
|
end
|
151
144
|
|
152
145
|
def after_perform
|
153
|
-
@run.
|
146
|
+
@run.persist_transition
|
154
147
|
if defined?(@reenqueue_iteration_job) && @reenqueue_iteration_job
|
155
148
|
reenqueue_iteration_job(should_ignore: false)
|
156
149
|
end
|
@@ -171,15 +164,8 @@ module MaintenanceTasks
|
|
171
164
|
task_context = {}
|
172
165
|
end
|
173
166
|
errored_element = @errored_element if defined?(@errored_element)
|
174
|
-
run_error_callback
|
175
167
|
ensure
|
176
168
|
MaintenanceTasks.error_handler.call(error, task_context, errored_element)
|
177
169
|
end
|
178
|
-
|
179
|
-
def run_error_callback
|
180
|
-
@task.run_callbacks(:error) if defined?(@task)
|
181
|
-
rescue
|
182
|
-
nil
|
183
|
-
end
|
184
170
|
end
|
185
171
|
end
|
@@ -15,9 +15,10 @@ module MaintenanceTasks
|
|
15
15
|
CSV.new(task.csv_content, headers: true)
|
16
16
|
end
|
17
17
|
|
18
|
-
# The number of rows to be processed. Excludes the header row from the
|
19
|
-
# and
|
20
|
-
# an approximation based on the number of
|
18
|
+
# The number of rows to be processed. Excludes the header row from the
|
19
|
+
# count and assumes a trailing newline is at the end of the CSV file.
|
20
|
+
# Note that this number is an approximation based on the number of
|
21
|
+
# newlines.
|
21
22
|
#
|
22
23
|
# @return [Integer] the approximate number of rows to process.
|
23
24
|
def count(task)
|
@@ -66,9 +66,40 @@ module MaintenanceTasks
|
|
66
66
|
|
67
67
|
# Sets the run status to enqueued, making sure the transition is validated
|
68
68
|
# in case it's already enqueued.
|
69
|
+
#
|
70
|
+
# Rescues and retries status transition if an ActiveRecord::StaleObjectError
|
71
|
+
# is encountered.
|
69
72
|
def enqueued!
|
70
73
|
status_will_change!
|
71
74
|
super
|
75
|
+
rescue ActiveRecord::StaleObjectError
|
76
|
+
reload_status
|
77
|
+
retry
|
78
|
+
end
|
79
|
+
|
80
|
+
CALLBACKS_TRANSITION = {
|
81
|
+
cancelled: :cancel,
|
82
|
+
interrupted: :interrupt,
|
83
|
+
paused: :pause,
|
84
|
+
succeeded: :complete,
|
85
|
+
}.transform_keys(&:to_s)
|
86
|
+
private_constant :CALLBACKS_TRANSITION
|
87
|
+
|
88
|
+
# Saves the run, persisting the transition of its status, and all other
|
89
|
+
# changes to the object.
|
90
|
+
def persist_transition
|
91
|
+
save!
|
92
|
+
callback = CALLBACKS_TRANSITION[status]
|
93
|
+
run_task_callbacks(callback) if callback
|
94
|
+
rescue ActiveRecord::StaleObjectError
|
95
|
+
success = succeeded?
|
96
|
+
reload_status
|
97
|
+
if success
|
98
|
+
self.status = :succeeded
|
99
|
+
else
|
100
|
+
job_shutdown
|
101
|
+
end
|
102
|
+
retry
|
72
103
|
end
|
73
104
|
|
74
105
|
# Increments +tick_count+ by +number_of_ticks+ and +time_running+ by
|
@@ -86,6 +117,11 @@ module MaintenanceTasks
|
|
86
117
|
time_running: duration,
|
87
118
|
touch: true
|
88
119
|
)
|
120
|
+
if locking_enabled?
|
121
|
+
locking_column = self.class.locking_column
|
122
|
+
self[locking_column] += 1
|
123
|
+
clear_attribute_change(locking_column)
|
124
|
+
end
|
89
125
|
end
|
90
126
|
|
91
127
|
# Marks the run as errored and persists the error data.
|
@@ -100,20 +136,34 @@ module MaintenanceTasks
|
|
100
136
|
backtrace: MaintenanceTasks.backtrace_cleaner.clean(error.backtrace),
|
101
137
|
ended_at: Time.now,
|
102
138
|
)
|
139
|
+
run_task_callbacks(:error)
|
140
|
+
rescue ActiveRecord::StaleObjectError
|
141
|
+
reload_status
|
142
|
+
retry
|
103
143
|
end
|
104
144
|
|
105
|
-
# Refreshes
|
106
|
-
# ensures ActiveModel::Dirty
|
145
|
+
# Refreshes the status and lock version attributes on the Active Record
|
146
|
+
# object, and ensures ActiveModel::Dirty doesn't mark the object as changed.
|
147
|
+
#
|
107
148
|
# This allows us to get the Run's most up-to-date status without needing
|
108
149
|
# to reload the entire record.
|
109
150
|
#
|
110
151
|
# @return [MaintenanceTasks::Run] the Run record with its updated status.
|
111
152
|
def reload_status
|
112
|
-
|
113
|
-
self.class.
|
153
|
+
columns_to_reload = if locking_enabled?
|
154
|
+
[:status, self.class.locking_column]
|
155
|
+
else
|
156
|
+
[:status]
|
157
|
+
end
|
158
|
+
updated_status, updated_lock_version = self.class.uncached do
|
159
|
+
self.class.where(id: id).pluck(*columns_to_reload).first
|
114
160
|
end
|
161
|
+
|
115
162
|
self.status = updated_status
|
116
|
-
|
163
|
+
if updated_lock_version
|
164
|
+
self[self.class.locking_column] = updated_lock_version
|
165
|
+
end
|
166
|
+
clear_attribute_changes(columns_to_reload)
|
117
167
|
self
|
118
168
|
end
|
119
169
|
|
@@ -173,21 +223,65 @@ module MaintenanceTasks
|
|
173
223
|
seconds_to_finished.seconds
|
174
224
|
end
|
175
225
|
|
176
|
-
#
|
226
|
+
# Marks a Run as running.
|
177
227
|
#
|
178
228
|
# If the run is stopping already, it will not transition to running.
|
229
|
+
# Rescues and retries status transition if an ActiveRecord::StaleObjectError
|
230
|
+
# is encountered.
|
179
231
|
def running
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
232
|
+
if locking_enabled?
|
233
|
+
begin
|
234
|
+
running! unless stopping?
|
235
|
+
rescue ActiveRecord::StaleObjectError
|
236
|
+
reload_status
|
237
|
+
retry
|
238
|
+
end
|
239
|
+
else
|
240
|
+
# Preserve swap-and-replace solution for data races until users
|
241
|
+
# run migration to upgrade to optimistic locking solution
|
242
|
+
return if stopping?
|
243
|
+
updated = self.class.where(id: id).where.not(status: STOPPING_STATUSES)
|
244
|
+
.update_all(status: :running, updated_at: Time.now) > 0
|
245
|
+
if updated
|
246
|
+
self.status = :running
|
247
|
+
clear_attribute_changes([:status])
|
248
|
+
else
|
249
|
+
reload_status
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Starts a Run, setting its started_at timestamp and tick_total.
|
255
|
+
#
|
256
|
+
# @param count [Integer] the total iterations to be performed, as
|
257
|
+
# specified by the Task.
|
258
|
+
def start(count)
|
259
|
+
update!(started_at: Time.now, tick_total: count)
|
260
|
+
run_task_callbacks(:start)
|
261
|
+
rescue ActiveRecord::StaleObjectError
|
262
|
+
reload_status
|
263
|
+
retry
|
264
|
+
end
|
265
|
+
|
266
|
+
# Handles transitioning the status on a Run when the job shuts down.
|
267
|
+
def job_shutdown
|
268
|
+
if cancelling?
|
269
|
+
self.status = :cancelled
|
270
|
+
self.ended_at = Time.now
|
271
|
+
elsif pausing?
|
272
|
+
self.status = :paused
|
186
273
|
else
|
187
|
-
|
274
|
+
self.status = :interrupted
|
188
275
|
end
|
189
276
|
end
|
190
277
|
|
278
|
+
# Handles the completion of a Run, setting a status of succeeded and the
|
279
|
+
# ended_at timestamp.
|
280
|
+
def complete
|
281
|
+
self.status = :succeeded
|
282
|
+
self.ended_at = Time.now
|
283
|
+
end
|
284
|
+
|
191
285
|
# Cancels a Run.
|
192
286
|
#
|
193
287
|
# If the Run is paused, it will transition directly to cancelled, since the
|
@@ -201,10 +295,26 @@ module MaintenanceTasks
|
|
201
295
|
# will be updated.
|
202
296
|
def cancel
|
203
297
|
if paused? || stuck?
|
204
|
-
|
298
|
+
self.status = :cancelled
|
299
|
+
self.ended_at = Time.now
|
300
|
+
persist_transition
|
205
301
|
else
|
206
302
|
cancelling!
|
207
303
|
end
|
304
|
+
rescue ActiveRecord::StaleObjectError
|
305
|
+
reload_status
|
306
|
+
retry
|
307
|
+
end
|
308
|
+
|
309
|
+
# Marks a Run as pausing.
|
310
|
+
#
|
311
|
+
# Rescues and retries status transition if an ActiveRecord::StaleObjectError
|
312
|
+
# is encountered.
|
313
|
+
def pausing!
|
314
|
+
super
|
315
|
+
rescue ActiveRecord::StaleObjectError
|
316
|
+
reload_status
|
317
|
+
retry
|
208
318
|
end
|
209
319
|
|
210
320
|
# Returns whether a Run is stuck, which is defined as having a status of
|
@@ -297,6 +407,12 @@ module MaintenanceTasks
|
|
297
407
|
|
298
408
|
private
|
299
409
|
|
410
|
+
def run_task_callbacks(callback)
|
411
|
+
task.run_callbacks(callback)
|
412
|
+
rescue
|
413
|
+
nil
|
414
|
+
end
|
415
|
+
|
300
416
|
def arguments_match_task_attributes
|
301
417
|
invalid_argument_keys = arguments.keys - task.attribute_names
|
302
418
|
if invalid_argument_keys.any?
|
@@ -59,7 +59,8 @@ module MaintenanceTasks
|
|
59
59
|
"To resolve this issue run: bin/rails active_storage:install"
|
60
60
|
end
|
61
61
|
|
62
|
-
self.collection_builder_strategy =
|
62
|
+
self.collection_builder_strategy =
|
63
|
+
MaintenanceTasks::CsvCollectionBuilder.new
|
63
64
|
end
|
64
65
|
|
65
66
|
# Returns whether the Task handles CSV.
|
@@ -98,14 +99,19 @@ module MaintenanceTasks
|
|
98
99
|
|
99
100
|
# Add a condition under which this Task will be throttled.
|
100
101
|
#
|
101
|
-
# @param backoff [ActiveSupport::Duration]
|
102
|
-
# can be specified. This is the time to wait before retrying the Task
|
103
|
-
# If
|
102
|
+
# @param backoff [ActiveSupport::Duration, #call] a custom backoff
|
103
|
+
# can be specified. This is the time to wait before retrying the Task,
|
104
|
+
# defaulting to 30 seconds. If provided as a Duration, the backoff is
|
105
|
+
# wrapped in a proc. Alternatively,an object responding to call can be
|
106
|
+
# used. It must return an ActiveSupport::Duration.
|
104
107
|
# @yieldreturn [Boolean] where the throttle condition is being met,
|
105
108
|
# indicating that the Task should throttle.
|
106
109
|
def throttle_on(backoff: 30.seconds, &condition)
|
110
|
+
backoff_as_proc = backoff
|
111
|
+
backoff_as_proc = -> { backoff } unless backoff.respond_to?(:call)
|
112
|
+
|
107
113
|
self.throttle_conditions += [
|
108
|
-
{ throttle_on: condition, backoff:
|
114
|
+
{ throttle_on: condition, backoff: backoff_as_proc },
|
109
115
|
]
|
110
116
|
end
|
111
117
|
|
@@ -74,7 +74,11 @@ module MaintenanceTasks
|
|
74
74
|
def code
|
75
75
|
return if deleted?
|
76
76
|
task = Task.named(name)
|
77
|
-
file =
|
77
|
+
file = if Object.respond_to?(:const_source_location)
|
78
|
+
Object.const_source_location(task.name).first
|
79
|
+
else
|
80
|
+
task.instance_method(:process).source_location.first
|
81
|
+
end
|
78
82
|
File.read(file)
|
79
83
|
end
|
80
84
|
|
@@ -142,6 +146,13 @@ module MaintenanceTasks
|
|
142
146
|
end
|
143
147
|
end
|
144
148
|
|
149
|
+
# @return [MaintenanceTasks::Task, nil] an instance of the Task class.
|
150
|
+
# @return [nil] if the Task file was deleted.
|
151
|
+
def new
|
152
|
+
return if deleted?
|
153
|
+
MaintenanceTasks::Task.named(name).new
|
154
|
+
end
|
155
|
+
|
145
156
|
private
|
146
157
|
|
147
158
|
def runs
|
@@ -10,6 +10,10 @@
|
|
10
10
|
<%= render "maintenance_tasks/runs/info/#{run.status}", run: run %>
|
11
11
|
</div>
|
12
12
|
|
13
|
+
<div class="content" id="custom-content">
|
14
|
+
<%= render "maintenance_tasks/runs/info/custom", run: run %>
|
15
|
+
</div>
|
16
|
+
|
13
17
|
<%= render "maintenance_tasks/runs/csv", run: run %>
|
14
18
|
<%= tag.hr if run.csv_file.present? && run.arguments.present? %>
|
15
19
|
<%= render "maintenance_tasks/runs/arguments", run: run %>
|
File without changes
|
File without changes
|
@@ -15,6 +15,10 @@
|
|
15
15
|
<%= render "maintenance_tasks/runs/info/#{run.status}", run: run %>
|
16
16
|
</div>
|
17
17
|
|
18
|
+
<div class="content" id="custom-content">
|
19
|
+
<%= render "maintenance_tasks/runs/info/custom", run: run %>
|
20
|
+
</div>
|
21
|
+
|
18
22
|
<%= render "maintenance_tasks/runs/csv", run: run %>
|
19
23
|
<%= tag.hr if run.csv_file.present? && run.arguments.present? %>
|
20
24
|
<%= render "maintenance_tasks/runs/arguments", run: run %>
|
@@ -16,6 +16,10 @@
|
|
16
16
|
<%= render "maintenance_tasks/runs/info/#{last_run.status}", run: last_run %>
|
17
17
|
</div>
|
18
18
|
|
19
|
+
<div class="content" id="custom-content">
|
20
|
+
<%= render "maintenance_tasks/runs/info/custom", run: last_run %>
|
21
|
+
</div>
|
22
|
+
|
19
23
|
<%= render "maintenance_tasks/runs/csv", run: last_run %>
|
20
24
|
<%= tag.hr if last_run.csv_file.present? %>
|
21
25
|
<%= render "maintenance_tasks/runs/arguments", run: last_run %>
|
@@ -31,20 +35,22 @@
|
|
31
35
|
<%= form.file_field :csv_file %>
|
32
36
|
</div>
|
33
37
|
<% end %>
|
34
|
-
<%
|
38
|
+
<% parameter_names = @task.parameter_names %>
|
39
|
+
<% if parameter_names.any? %>
|
35
40
|
<div class="block">
|
36
|
-
<%= form.fields_for :task_arguments do |ff| %>
|
37
|
-
<%
|
41
|
+
<%= form.fields_for :task_arguments, @task.new do |ff| %>
|
42
|
+
<% parameter_names.each do |parameter_name| %>
|
38
43
|
<div class="field">
|
39
|
-
<%= ff.label
|
44
|
+
<%= ff.label parameter_name, parameter_name, class: "label is-family-monospace" %>
|
40
45
|
<div class="control">
|
41
|
-
<%= ff
|
46
|
+
<%= parameter_field(ff, parameter_name) %>
|
42
47
|
</div>
|
43
48
|
</div>
|
44
49
|
<% end %>
|
45
50
|
<% end %>
|
46
51
|
</div>
|
47
52
|
<% end %>
|
53
|
+
<%= render "maintenance_tasks/tasks/custom", form: form %>
|
48
54
|
<div class="block">
|
49
55
|
<%= form.submit 'Run', class: "button is-success", disabled: @task.deleted? %>
|
50
56
|
</div>
|
@@ -8,7 +8,16 @@ module MaintenanceTasks
|
|
8
8
|
class Engine < ::Rails::Engine
|
9
9
|
isolate_namespace MaintenanceTasks
|
10
10
|
|
11
|
-
initializer "
|
11
|
+
initializer "maintenance_tasks.warn_classic_autoloader" do
|
12
|
+
unless Rails.autoloaders.zeitwerk_enabled?
|
13
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
14
|
+
Autoloading in classic mode is deprecated and support will be removed in the next
|
15
|
+
release of Maintenance Tasks. Please use Zeitwerk to autoload your application.
|
16
|
+
MSG
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
initializer "maintenance_tasks.eager_load_for_classic_autoloader" do
|
12
21
|
eager_load! unless Rails.autoloaders.zeitwerk_enabled?
|
13
22
|
end
|
14
23
|
|
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
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- app/views/maintenance_tasks/runs/_run.html.erb
|
115
115
|
- app/views/maintenance_tasks/runs/info/_cancelled.html.erb
|
116
116
|
- app/views/maintenance_tasks/runs/info/_cancelling.html.erb
|
117
|
+
- app/views/maintenance_tasks/runs/info/_custom.html.erb
|
117
118
|
- app/views/maintenance_tasks/runs/info/_enqueued.html.erb
|
118
119
|
- app/views/maintenance_tasks/runs/info/_errored.html.erb
|
119
120
|
- app/views/maintenance_tasks/runs/info/_interrupted.html.erb
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- app/views/maintenance_tasks/runs/info/_pausing.html.erb
|
122
123
|
- app/views/maintenance_tasks/runs/info/_running.html.erb
|
123
124
|
- app/views/maintenance_tasks/runs/info/_succeeded.html.erb
|
125
|
+
- app/views/maintenance_tasks/tasks/_custom.html.erb
|
124
126
|
- app/views/maintenance_tasks/tasks/_task.html.erb
|
125
127
|
- app/views/maintenance_tasks/tasks/index.html.erb
|
126
128
|
- app/views/maintenance_tasks/tasks/show.html.erb
|
@@ -128,6 +130,7 @@ files:
|
|
128
130
|
- db/migrate/20201211151756_create_maintenance_tasks_runs.rb
|
129
131
|
- db/migrate/20210225152418_remove_index_on_task_name.rb
|
130
132
|
- db/migrate/20210517131953_add_arguments_to_maintenance_tasks_runs.rb
|
133
|
+
- db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb
|
131
134
|
- exe/maintenance_tasks
|
132
135
|
- lib/generators/maintenance_tasks/install_generator.rb
|
133
136
|
- lib/generators/maintenance_tasks/task_generator.rb
|
@@ -144,7 +147,7 @@ homepage: https://github.com/Shopify/maintenance_tasks
|
|
144
147
|
licenses:
|
145
148
|
- MIT
|
146
149
|
metadata:
|
147
|
-
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
|
148
151
|
allowed_push_host: https://rubygems.org
|
149
152
|
post_install_message:
|
150
153
|
rdoc_options: []
|