maintenance_tasks 2.8.0 → 2.10.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 +63 -3
- data/app/controllers/maintenance_tasks/runs_controller.rb +4 -1
- data/app/controllers/maintenance_tasks/tasks_controller.rb +5 -8
- data/app/helpers/maintenance_tasks/tasks_helper.rb +29 -5
- data/app/models/maintenance_tasks/run.rb +13 -33
- data/app/models/maintenance_tasks/runs_page.rb +3 -0
- data/app/models/maintenance_tasks/task_data_show.rb +53 -4
- data/app/views/maintenance_tasks/runs/_run.html.erb +9 -9
- data/app/views/maintenance_tasks/tasks/show.html.erb +4 -4
- data/config/routes.rb +4 -3
- data/lib/patches/active_record_batch_enumerator.rb +17 -16
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 347d742ae5f71881fe2d54f7fff83b4129144eb72af60c2364a8069fc41412fe
|
4
|
+
data.tar.gz: 20ff959d1c2db4a003883955ef938414a462f16fa843d8f4ec526ff3333a0609
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f9e56bd030e2a6918d7e8e136108d6097cbcdaa8b73ebb9683072878f8789cb0b7da1b67c122d7dddf97553ca3dcb37b4e1af7670cbdf931825ec965cbbf9af
|
7
|
+
data.tar.gz: 384ec37a77b25d689ff46f965fd6cddd4ddc7669f520a99db808edc76c290c21ed8925b5d791839dd0d61738da6b944267fa65535b91ebd4ee6d8913293bb824
|
data/README.md
CHANGED
@@ -90,6 +90,13 @@ take a look at the [Active Job documentation][active-job-docs].
|
|
90
90
|
[async-adapter]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html
|
91
91
|
[active-job-docs]: https://guides.rubyonrails.org/active_job_basics.html#setting-the-backend
|
92
92
|
|
93
|
+
### Action Controller & Action View Dependency
|
94
|
+
|
95
|
+
The Maintenance Tasks framework relies on Action Controller and Action View to
|
96
|
+
render the UI. If you're using Rails in API-only mode, see [Using Maintenance
|
97
|
+
Tasks in API-only
|
98
|
+
applications](#using-maintenance-tasks-in-api-only-applications).
|
99
|
+
|
93
100
|
### Autoloading
|
94
101
|
|
95
102
|
The Maintenance Tasks framework does not support autoloading in `:classic` mode.
|
@@ -485,6 +492,23 @@ to run. Since arguments are specified in the user interface via text area
|
|
485
492
|
inputs, it’s important to check that they conform to the format your Task
|
486
493
|
expects, and to sanitize any inputs if necessary.
|
487
494
|
|
495
|
+
#### Validating Task Parameters
|
496
|
+
|
497
|
+
Task attributes can be validated using Active Model Validations. Attributes are
|
498
|
+
validated before a Task is enqueued.
|
499
|
+
|
500
|
+
If an attribute uses an inclusion validator with a supported `in:` option, the
|
501
|
+
set of values will be used to populate a dropdown in the user interface. The
|
502
|
+
following types are supported:
|
503
|
+
|
504
|
+
* Arrays
|
505
|
+
* Procs and lambdas that optionally accept the Task instance, and return an Array.
|
506
|
+
* Callable objects that receive one argument, the Task instance, and return an Array.
|
507
|
+
* Methods that return an Array, called on the Task instance.
|
508
|
+
|
509
|
+
For enumerables that don't match the supported types, a text field will be
|
510
|
+
rendered instead.
|
511
|
+
|
488
512
|
### Custom cursor columns to improve performance
|
489
513
|
|
490
514
|
The [job-iteration gem][job-iteration], on which this gem depends, adds an
|
@@ -541,8 +565,8 @@ your application.
|
|
541
565
|
|
542
566
|
Usage example:
|
543
567
|
|
544
|
-
|
545
|
-
|
568
|
+
```ruby
|
569
|
+
ActiveSupport::Notifications.subscribe("succeeded.maintenance_tasks") do |*, payload|
|
546
570
|
task_name = payload[:task_name]
|
547
571
|
arguments = payload[:arguments]
|
548
572
|
metadata = payload[:metadata]
|
@@ -871,6 +895,42 @@ a Task can be in:
|
|
871
895
|
* **succeeded**: A Task that finished successfully.
|
872
896
|
* **errored**: A Task that encountered an unhandled exception while performing.
|
873
897
|
|
898
|
+
### Using Maintenance Tasks in API-only applications
|
899
|
+
|
900
|
+
The Maintenance Tasks engine uses Rails sessions for flash messages and storing
|
901
|
+
the CSRF token. For the engine to work in an API-only Rails application, you
|
902
|
+
need to add a [session middleware][] and the `ActionDispatch::Flash`
|
903
|
+
middleware. The engine also defines a strict [Content Security Policy][], make
|
904
|
+
sure to include `ActionDispatch::ContentSecurityPolicy::Middleware` in your
|
905
|
+
app's middleware stack to ensure the CSP is delivered to the user's browser.
|
906
|
+
|
907
|
+
[session middleware]: https://guides.rubyonrails.org/api_app.html#using-session-middlewares
|
908
|
+
[Content Security Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
909
|
+
|
910
|
+
Configuring Rails applications is beyond the scope of this documentation, but
|
911
|
+
one way to do this is to add these lines to your application configuration:
|
912
|
+
|
913
|
+
```ruby
|
914
|
+
# config/application.rb
|
915
|
+
module YourApplication
|
916
|
+
class Application < Rails::Application
|
917
|
+
# ...
|
918
|
+
config.api_only = true
|
919
|
+
|
920
|
+
config.middleware.insert_before ::Rack::Head, ::ActionDispatch::Flash
|
921
|
+
config.middleware.insert_before ::Rack::Head, ::ActionDispatch::ContentSecurityPolicy::Middleware
|
922
|
+
config.session_store :cookie_store, key: "_#{railtie_name.chomp("_application")}_session", secure: true
|
923
|
+
config.middleware.insert_before ::ActionDispatch::Flash, config.session_store, config.session_options
|
924
|
+
config.middleware.insert_before config.session_store, ActionDispatch::Cookies
|
925
|
+
end
|
926
|
+
end
|
927
|
+
```
|
928
|
+
|
929
|
+
You can read more in the [Using Rails for API-only Applications][rails api] Rails
|
930
|
+
guide.
|
931
|
+
|
932
|
+
[rails api]: https://guides.rubyonrails.org/api_app.html
|
933
|
+
|
874
934
|
### How Maintenance Tasks runs a Task
|
875
935
|
|
876
936
|
Maintenance tasks can be running for a long time, and the purpose of the gem is
|
@@ -1128,7 +1188,7 @@ The value for `MaintenanceTasks.stuck_task_duration` must be an
|
|
1128
1188
|
`ActiveSupport::Duration`. If no value is specified, it will default to 5
|
1129
1189
|
minutes.
|
1130
1190
|
|
1131
|
-
|
1191
|
+
#### Metadata
|
1132
1192
|
|
1133
1193
|
`MaintenanceTasks.metadata` can be configured to specify a proc from which to
|
1134
1194
|
get extra information about the run. Since this proc will be ran in the context
|
@@ -6,6 +6,7 @@ module MaintenanceTasks
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class RunsController < ApplicationController
|
9
|
+
helper TasksHelper
|
9
10
|
before_action :set_run, except: :create
|
10
11
|
|
11
12
|
# Creates a Run for a given Task and redirects to the Task page.
|
@@ -19,7 +20,9 @@ module MaintenanceTasks
|
|
19
20
|
)
|
20
21
|
redirect_to(task_path(task))
|
21
22
|
rescue ActiveRecord::RecordInvalid => error
|
22
|
-
|
23
|
+
flash.now.alert = error.message
|
24
|
+
@task = TaskDataShow.prepare(error.record.task_name, arguments: error.record.arguments)
|
25
|
+
render(template: "maintenance_tasks/tasks/show")
|
23
26
|
rescue ActiveRecord::ValueTooLong => error
|
24
27
|
task_name = params.fetch(:task_id)
|
25
28
|
redirect_to(task_path(task_name), alert: error.message)
|
@@ -18,14 +18,11 @@ module MaintenanceTasks
|
|
18
18
|
# Renders the page responsible for providing Task actions to users.
|
19
19
|
# Shows running and completed instances of the Task.
|
20
20
|
def show
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if @task.active_runs.none? && @runs_page.records.none?
|
27
|
-
Task.named(task_name)
|
28
|
-
end
|
21
|
+
@task = TaskDataShow.prepare(
|
22
|
+
params.fetch(:id),
|
23
|
+
runs_cursor: params[:cursor],
|
24
|
+
arguments: params.except(:id, :controller, :action).permit!,
|
25
|
+
)
|
29
26
|
end
|
30
27
|
|
31
28
|
private
|
@@ -102,8 +102,13 @@ module MaintenanceTasks
|
|
102
102
|
end
|
103
103
|
|
104
104
|
# Resolves values covered by the inclusion validator for a task attribute.
|
105
|
-
#
|
106
|
-
#
|
105
|
+
# Supported option types:
|
106
|
+
# - Arrays
|
107
|
+
# - Procs and lambdas that optionally accept the Task instance, and return an Array.
|
108
|
+
# - Callable objects that receive one argument, the Task instance, and return an Array.
|
109
|
+
# - Methods that return an Array, called on the Task instance.
|
110
|
+
#
|
111
|
+
# Other types are not supported and will return nil.
|
107
112
|
#
|
108
113
|
# Returned values are used to populate a dropdown list of options.
|
109
114
|
#
|
@@ -111,20 +116,39 @@ module MaintenanceTasks
|
|
111
116
|
# @param parameter_name [String] The parameter name.
|
112
117
|
#
|
113
118
|
# @return [Array] value of the resolved inclusion option.
|
114
|
-
def resolve_inclusion_value(
|
119
|
+
def resolve_inclusion_value(task, parameter_name)
|
120
|
+
task_class = task.class
|
115
121
|
inclusion_validator = task_class.validators_on(parameter_name).find do |validator|
|
116
122
|
validator.kind == :inclusion
|
117
123
|
end
|
118
124
|
return unless inclusion_validator
|
119
125
|
|
120
126
|
in_option = inclusion_validator.options[:in] || inclusion_validator.options[:within]
|
121
|
-
|
127
|
+
resolved_in_option = case in_option
|
128
|
+
when Proc
|
129
|
+
if in_option.arity == 0
|
130
|
+
in_option.call
|
131
|
+
else
|
132
|
+
in_option.call(task)
|
133
|
+
end
|
134
|
+
when Symbol
|
135
|
+
method = task.method(in_option)
|
136
|
+
method.call if method.arity.zero?
|
137
|
+
else
|
138
|
+
if in_option.respond_to?(:call)
|
139
|
+
in_option.call(task)
|
140
|
+
else
|
141
|
+
in_option
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
resolved_in_option if resolved_in_option.is_a?(Array)
|
122
146
|
end
|
123
147
|
|
124
148
|
# Return the appropriate field tag for the parameter, based on its type.
|
125
149
|
# If the parameter has a `validates_inclusion_of` validator, return a dropdown list of options instead.
|
126
150
|
def parameter_field(form_builder, parameter_name)
|
127
|
-
inclusion_values = resolve_inclusion_value(form_builder.object
|
151
|
+
inclusion_values = resolve_inclusion_value(form_builder.object, parameter_name)
|
128
152
|
return form_builder.select(parameter_name, inclusion_values, prompt: "Select a value") if inclusion_values
|
129
153
|
|
130
154
|
case form_builder.object.class.attribute_types[parameter_name]
|
@@ -386,40 +386,20 @@ module MaintenanceTasks
|
|
386
386
|
nil
|
387
387
|
end
|
388
388
|
|
389
|
-
#
|
390
|
-
#
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
:arguments,
|
401
|
-
"are invalid: #{error_messages.join("; ")}",
|
402
|
-
)
|
403
|
-
end
|
404
|
-
rescue Task::NotFoundError
|
405
|
-
nil
|
406
|
-
end
|
407
|
-
else
|
408
|
-
# Performs validation on the arguments to use for the Task. If the Task is
|
409
|
-
# invalid, the errors are added to the Run.
|
410
|
-
def validate_task_arguments
|
411
|
-
arguments_match_task_attributes if arguments.present?
|
412
|
-
if task.invalid?
|
413
|
-
error_messages = task.errors
|
414
|
-
.map { |error| "#{error.attribute.inspect} #{error.message}" }
|
415
|
-
errors.add(
|
416
|
-
:arguments,
|
417
|
-
"are invalid: #{error_messages.join("; ")}",
|
418
|
-
)
|
419
|
-
end
|
420
|
-
rescue Task::NotFoundError
|
421
|
-
nil
|
389
|
+
# Performs validation on the arguments to use for the Task. If the Task is
|
390
|
+
# invalid, the errors are added to the Run.
|
391
|
+
def validate_task_arguments
|
392
|
+
arguments_match_task_attributes if arguments.present?
|
393
|
+
if task.invalid?
|
394
|
+
error_messages = task.errors
|
395
|
+
.map { |error| "#{error.attribute.inspect} #{error.message}" }
|
396
|
+
errors.add(
|
397
|
+
:arguments,
|
398
|
+
"are invalid: #{error_messages.join("; ")}",
|
399
|
+
)
|
422
400
|
end
|
401
|
+
rescue Task::NotFoundError
|
402
|
+
nil
|
423
403
|
end
|
424
404
|
|
425
405
|
# Fetches the attached ActiveStorage CSV file for the run. Checks first
|
@@ -21,6 +21,9 @@ module MaintenanceTasks
|
|
21
21
|
@cursor = cursor
|
22
22
|
end
|
23
23
|
|
24
|
+
# @return [String, nil] the cursor for the page of Runs.
|
25
|
+
attr_reader :cursor
|
26
|
+
|
24
27
|
# Returns the records for a Page, taking into account the cursor if one is
|
25
28
|
# present. Limits the number of records to 20.
|
26
29
|
#
|
@@ -11,17 +11,39 @@ module MaintenanceTasks
|
|
11
11
|
#
|
12
12
|
# @api private
|
13
13
|
class TaskDataShow
|
14
|
-
# Initializes a Task Data with a name
|
14
|
+
# Initializes a Task Data with a name.
|
15
15
|
#
|
16
16
|
# @param name [String] the name of the Task subclass.
|
17
|
-
|
17
|
+
# @param runs_cursor [String, nil] the cursor for the runs page.
|
18
|
+
# @param arguments [Hash, nil] the Task arguments.
|
19
|
+
def initialize(name, runs_cursor: nil, arguments: nil)
|
18
20
|
@name = name
|
21
|
+
@arguments = arguments
|
22
|
+
@runs_page = RunsPage.new(completed_runs, runs_cursor)
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# Prepares a Task Data from a task name.
|
27
|
+
#
|
28
|
+
# @param name [String] the name of the Task subclass.
|
29
|
+
# @param runs_cursor [String, nil] the cursor for the runs page.
|
30
|
+
# @param arguments [Hash, nil] the Task arguments.
|
31
|
+
# @raise [Task::NotFoundError] if the Task doesn't have runs (for the given cursor) and doesn't exist.
|
32
|
+
def prepare(name, runs_cursor: nil, arguments: nil)
|
33
|
+
new(name, runs_cursor:, arguments:)
|
34
|
+
.load_active_runs
|
35
|
+
.ensure_task_exists
|
36
|
+
end
|
19
37
|
end
|
20
38
|
|
21
39
|
# @return [String] the name of the Task.
|
22
40
|
attr_reader :name
|
23
41
|
alias_method :to_s, :name
|
24
42
|
|
43
|
+
# @return [RunsPage] the current page of completed runs, based on the cursor
|
44
|
+
# passed in initialize.
|
45
|
+
attr_reader :runs_page
|
46
|
+
|
25
47
|
# The Task's source code.
|
26
48
|
#
|
27
49
|
# @return [String] the contents of the file which defines the Task.
|
@@ -38,6 +60,11 @@ module MaintenanceTasks
|
|
38
60
|
File.read(file)
|
39
61
|
end
|
40
62
|
|
63
|
+
# @return [Boolean] whether the task data needs to be refreshed.
|
64
|
+
def refresh?
|
65
|
+
active_runs.any?
|
66
|
+
end
|
67
|
+
|
41
68
|
# Returns the set of currently active Run records associated with the Task.
|
42
69
|
#
|
43
70
|
# @return [ActiveRecord::Relation<MaintenanceTasks::Run>] the relation of
|
@@ -79,12 +106,34 @@ module MaintenanceTasks
|
|
79
106
|
end
|
80
107
|
end
|
81
108
|
|
82
|
-
# @return [MaintenanceTasks::Task
|
109
|
+
# @return [MaintenanceTasks::Task] an instance of the Task class.
|
83
110
|
# @return [nil] if the Task file was deleted.
|
84
111
|
def new
|
85
112
|
return if deleted?
|
86
113
|
|
87
|
-
MaintenanceTasks::Task.named(name).new
|
114
|
+
task = MaintenanceTasks::Task.named(name).new
|
115
|
+
begin
|
116
|
+
task.assign_attributes(@arguments) if @arguments
|
117
|
+
rescue ActiveModel::UnknownAttributeError
|
118
|
+
# nothing to do
|
119
|
+
end
|
120
|
+
task
|
121
|
+
end
|
122
|
+
|
123
|
+
# Preloads the records from the active_runs ActiveRecord::Relation
|
124
|
+
# @return [self]
|
125
|
+
def load_active_runs
|
126
|
+
active_runs.load
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
# @raise [Task::NotFoundError] if the Task doesn't have Runs (for the given cursor) and doesn't exist.
|
131
|
+
# @return [self]
|
132
|
+
def ensure_task_exists
|
133
|
+
if active_runs.none? && runs_page.records.none?
|
134
|
+
Task.named(name)
|
135
|
+
end
|
136
|
+
self
|
88
137
|
end
|
89
138
|
|
90
139
|
private
|
@@ -23,23 +23,23 @@
|
|
23
23
|
|
24
24
|
<div class="buttons">
|
25
25
|
<% if run.paused? %>
|
26
|
-
<%= button_to 'Resume', resume_task_run_path(@task, run),
|
27
|
-
<%= button_to 'Cancel', cancel_task_run_path(@task, run),
|
26
|
+
<%= button_to 'Resume', resume_task_run_path(@task, run), class: 'button is-primary', disabled: @task.deleted? %>
|
27
|
+
<%= button_to 'Cancel', cancel_task_run_path(@task, run), class: 'button is-danger' %>
|
28
28
|
<% elsif run.errored? %>
|
29
|
-
<%= button_to 'Resume', resume_task_run_path(@task, run),
|
29
|
+
<%= button_to 'Resume', resume_task_run_path(@task, run), class: 'button is-primary', disabled: @task.deleted? %>
|
30
30
|
<% elsif run.cancelling? %>
|
31
31
|
<% if run.stuck? %>
|
32
|
-
<%= button_to 'Cancel', cancel_task_run_path(@task, run),
|
32
|
+
<%= button_to 'Cancel', cancel_task_run_path(@task, run), class: 'button is-danger', disabled: @task.deleted? %>
|
33
33
|
<% end %>
|
34
34
|
<% elsif run.pausing? %>
|
35
|
-
<%= button_to 'Pausing', pause_task_run_path(@task, run),
|
36
|
-
<%= button_to 'Cancel', cancel_task_run_path(@task, run),
|
35
|
+
<%= button_to 'Pausing', pause_task_run_path(@task, run), class: 'button is-warning', disabled: true %>
|
36
|
+
<%= button_to 'Cancel', cancel_task_run_path(@task, run), class: 'button is-danger' %>
|
37
37
|
<% if run.stuck? %>
|
38
|
-
<%= button_to 'Force pause', pause_task_run_path(@task, run),
|
38
|
+
<%= button_to 'Force pause', pause_task_run_path(@task, run), class: 'button is-danger', disabled: @task.deleted? %>
|
39
39
|
<% end %>
|
40
40
|
<% elsif run.active? %>
|
41
|
-
<%= button_to 'Pause', pause_task_run_path(@task, run),
|
42
|
-
<%= button_to 'Cancel', cancel_task_run_path(@task, run),
|
41
|
+
<%= button_to 'Pause', pause_task_run_path(@task, run), class: 'button is-warning', disabled: @task.deleted? %>
|
42
|
+
<%= button_to 'Cancel', cancel_task_run_path(@task, run), class: 'button is-danger' %>
|
43
43
|
<% end%>
|
44
44
|
</div>
|
45
45
|
</div>
|
@@ -38,7 +38,7 @@
|
|
38
38
|
<pre><code><%= highlight_code(code) %></code></pre>
|
39
39
|
<% end %>
|
40
40
|
|
41
|
-
<%= tag.div(data: { refresh:
|
41
|
+
<%= tag.div(data: { refresh: @task.refresh? || "" }) do %>
|
42
42
|
<% if @task.active_runs.any? %>
|
43
43
|
<hr/>
|
44
44
|
|
@@ -47,13 +47,13 @@
|
|
47
47
|
<%= render partial: "maintenance_tasks/runs/run", collection: @task.active_runs %>
|
48
48
|
<% end %>
|
49
49
|
|
50
|
-
<% if @runs_page.records.present? %>
|
50
|
+
<% if @task.runs_page.records.present? %>
|
51
51
|
<hr/>
|
52
52
|
|
53
53
|
<h4 class="title is-4">Previous Runs</h4>
|
54
54
|
|
55
|
-
<%= render partial: "maintenance_tasks/runs/run", collection: @runs_page.records %>
|
55
|
+
<%= render partial: "maintenance_tasks/runs/run", collection: @task.runs_page.records %>
|
56
56
|
|
57
|
-
<%= link_to "Next page", task_path(@task, cursor: @runs_page.next_cursor) unless @runs_page.last? %>
|
57
|
+
<%= link_to "Next page", task_path(@task, cursor: @task.runs_page.next_cursor) unless @task.runs_page.last? %>
|
58
58
|
<% end %>
|
59
59
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -4,11 +4,12 @@ MaintenanceTasks::Engine.routes.draw do
|
|
4
4
|
resources :tasks, only: [:index, :show], format: false do
|
5
5
|
resources :runs, only: [:create], format: false do
|
6
6
|
member do
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
post "pause"
|
8
|
+
post "cancel"
|
9
|
+
post "resume"
|
10
10
|
end
|
11
11
|
end
|
12
|
+
get :runs, to: redirect("tasks/%{task_id}")
|
12
13
|
end
|
13
14
|
|
14
15
|
root to: "tasks#index"
|
@@ -1,23 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
5
|
-
module ActiveRecordBatchEnumerator
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
if Rails.gem_version < Gem::Version.new("7.0")
|
4
|
+
# Add attribute readers.
|
5
|
+
module ActiveRecordBatchEnumerator
|
6
|
+
# The primary key value from which the BatchEnumerator starts,
|
7
|
+
# inclusive of the value.
|
8
|
+
attr_reader :start
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
# The primary key value at which the BatchEnumerator ends,
|
11
|
+
# inclusive of the value.
|
12
|
+
attr_reader :finish
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
# The relation from which the BatchEnumerator yields batches.
|
15
|
+
attr_reader :relation
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# The size of the batches yielded by the BatchEnumerator.
|
18
|
+
def batch_size
|
19
|
+
@of
|
20
|
+
end
|
20
21
|
end
|
21
|
-
end
|
22
22
|
|
23
|
-
ActiveRecord::Batches::BatchEnumerator.include(ActiveRecordBatchEnumerator)
|
23
|
+
ActiveRecord::Batches::BatchEnumerator.include(ActiveRecordBatchEnumerator)
|
24
|
+
end
|
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: 2.
|
4
|
+
version: 2.10.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: 2024-
|
11
|
+
date: 2024-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '6.
|
19
|
+
version: '6.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '6.
|
26
|
+
version: '6.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activejob
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '6.
|
33
|
+
version: '6.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '6.
|
40
|
+
version: '6.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '6.
|
47
|
+
version: '6.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '6.
|
54
|
+
version: '6.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: csv
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '6.
|
89
|
+
version: '6.1'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '6.
|
96
|
+
version: '6.1'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: zeitwerk
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,7 +185,7 @@ homepage: https://github.com/Shopify/maintenance_tasks
|
|
185
185
|
licenses:
|
186
186
|
- MIT
|
187
187
|
metadata:
|
188
|
-
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v2.
|
188
|
+
source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v2.10.0
|
189
189
|
allowed_push_host: https://rubygems.org
|
190
190
|
post_install_message:
|
191
191
|
rdoc_options: []
|
@@ -195,14 +195,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
195
|
requirements:
|
196
196
|
- - ">="
|
197
197
|
- !ruby/object:Gem::Version
|
198
|
-
version: '3.
|
198
|
+
version: '3.1'
|
199
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
200
|
requirements:
|
201
201
|
- - ">="
|
202
202
|
- !ruby/object:Gem::Version
|
203
203
|
version: '0'
|
204
204
|
requirements: []
|
205
|
-
rubygems_version: 3.5.
|
205
|
+
rubygems_version: 3.5.23
|
206
206
|
signing_key:
|
207
207
|
specification_version: 4
|
208
208
|
summary: A Rails engine for queuing and managing maintenance tasks
|