maintenance_tasks 1.4.0 → 1.8.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +229 -41
  3. data/app/controllers/maintenance_tasks/tasks_controller.rb +2 -1
  4. data/app/helpers/maintenance_tasks/application_helper.rb +1 -0
  5. data/app/helpers/maintenance_tasks/tasks_helper.rb +19 -0
  6. data/app/jobs/concerns/maintenance_tasks/task_job_concern.rb +28 -21
  7. data/app/models/maintenance_tasks/application_record.rb +1 -0
  8. data/app/models/maintenance_tasks/csv_collection_builder.rb +38 -0
  9. data/app/models/maintenance_tasks/no_collection_builder.rb +29 -0
  10. data/app/models/maintenance_tasks/null_collection_builder.rb +38 -0
  11. data/app/models/maintenance_tasks/progress.rb +8 -3
  12. data/app/models/maintenance_tasks/run.rb +157 -13
  13. data/app/models/maintenance_tasks/runner.rb +22 -9
  14. data/app/models/maintenance_tasks/runs_page.rb +1 -0
  15. data/app/models/maintenance_tasks/task.rb +236 -0
  16. data/app/models/maintenance_tasks/task_data.rb +15 -3
  17. data/app/validators/maintenance_tasks/run_status_validator.rb +2 -2
  18. data/app/views/maintenance_tasks/runs/_arguments.html.erb +22 -0
  19. data/app/views/maintenance_tasks/runs/_csv.html.erb +5 -0
  20. data/app/views/maintenance_tasks/runs/_run.html.erb +18 -1
  21. data/app/views/maintenance_tasks/runs/info/_custom.html.erb +0 -0
  22. data/app/views/maintenance_tasks/runs/info/_errored.html.erb +0 -2
  23. data/app/views/maintenance_tasks/runs/info/_running.html.erb +3 -5
  24. data/app/views/maintenance_tasks/tasks/_custom.html.erb +0 -0
  25. data/app/views/maintenance_tasks/tasks/_task.html.erb +19 -1
  26. data/app/views/maintenance_tasks/tasks/show.html.erb +32 -7
  27. data/config/routes.rb +1 -0
  28. data/db/migrate/20201211151756_create_maintenance_tasks_runs.rb +1 -0
  29. data/db/migrate/20210225152418_remove_index_on_task_name.rb +1 -0
  30. data/db/migrate/20210517131953_add_arguments_to_maintenance_tasks_runs.rb +1 -0
  31. data/db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb +8 -0
  32. data/lib/generators/maintenance_tasks/install_generator.rb +1 -0
  33. data/lib/generators/maintenance_tasks/task_generator.rb +13 -0
  34. data/lib/generators/maintenance_tasks/templates/no_collection_task.rb.tt +13 -0
  35. data/lib/generators/maintenance_tasks/templates/no_collection_task_test.rb.tt +12 -0
  36. data/lib/generators/maintenance_tasks/templates/task.rb.tt +3 -1
  37. data/lib/generators/maintenance_tasks/templates/task_test.rb.tt +4 -0
  38. data/lib/maintenance_tasks/cli.rb +6 -5
  39. data/lib/maintenance_tasks/engine.rb +15 -1
  40. data/lib/maintenance_tasks.rb +12 -1
  41. metadata +15 -7
  42. data/app/models/maintenance_tasks/csv_collection.rb +0 -33
  43. data/app/tasks/maintenance_tasks/task.rb +0 -137
  44. data/app/views/maintenance_tasks/runs/_info.html.erb +0 -16
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module MaintenanceTasks
3
4
  # Class that represents the data related to a Task. Such information can be
4
5
  # sourced from a Task or from existing Run records for a Task that was since
@@ -40,7 +41,7 @@ module MaintenanceTasks
40
41
  def available_tasks
41
42
  task_names = Task.available_tasks.map(&:name)
42
43
  available_task_runs = Run.where(task_name: task_names)
43
- last_runs = Run.where(
44
+ last_runs = Run.with_attached_csv.where(
44
45
  id: available_task_runs.select("MAX(id) as id").group(:task_name)
45
46
  )
46
47
 
@@ -73,7 +74,11 @@ module MaintenanceTasks
73
74
  def code
74
75
  return if deleted?
75
76
  task = Task.named(name)
76
- file = task.instance_method(:process).source_location.first
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
77
82
  File.read(file)
78
83
  end
79
84
 
@@ -129,7 +134,7 @@ module MaintenanceTasks
129
134
 
130
135
  # @return [Boolean] whether the Task inherits from CsvTask.
131
136
  def csv_task?
132
- !deleted? && Task.named(name) < CsvCollection
137
+ !deleted? && Task.named(name).has_csv_content?
133
138
  end
134
139
 
135
140
  # @return [Array<String>] the names of parameters the Task accepts.
@@ -141,6 +146,13 @@ module MaintenanceTasks
141
146
  end
142
147
  end
143
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
+
144
156
  private
145
157
 
146
158
  def runs
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module MaintenanceTasks
3
4
  # Custom validator class responsible for ensuring that transitions between
4
5
  # Run statuses are valid.
@@ -48,9 +49,8 @@ module MaintenanceTasks
48
49
  "errored",
49
50
  ],
50
51
  # 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
52
  # paused -> cancelled when the user cancels the task after it is paused.
53
- "paused" => ["enqueued", "cancelling", "cancelled"],
53
+ "paused" => ["enqueued", "cancelled"],
54
54
  # interrupted -> running occurs when the task is resumed after being
55
55
  # interrupted by the job infrastructure.
56
56
  # 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 %>
@@ -0,0 +1,5 @@
1
+ <% if run.csv_file.present? %>
2
+ <div class="block">
3
+ <%= link_to("Download CSV", csv_file_download_path(run)) %>
4
+ </div>
5
+ <% end %>
@@ -1,3 +1,20 @@
1
1
  <div class="box">
2
- <%= render 'maintenance_tasks/runs/info', run: run, with_status: true %>
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
+ <div class="content" id="custom-content">
14
+ <%= render "maintenance_tasks/runs/info/custom", run: run %>
15
+ </div>
16
+
17
+ <%= render "maintenance_tasks/runs/csv", run: run %>
18
+ <%= tag.hr if run.csv_file.present? && run.arguments.present? %>
19
+ <%= render "maintenance_tasks/runs/arguments", run: run %>
3
20
  </div>
@@ -3,8 +3,6 @@
3
3
  <%= time_ago run.ended_at %>.
4
4
  </p>
5
5
 
6
- </p>
7
-
8
6
  <div class="card">
9
7
  <header class="card-header">
10
8
  <p class="card-header-title">
@@ -1,5 +1,3 @@
1
- <p>
2
- <% if (time_to_completion = run.time_to_completion) %>
3
- <%= distance_of_time_in_words(time_to_completion).capitalize %> remaining.
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,23 @@
4
4
  <%= status_tag(task.status) %>
5
5
  </h3>
6
6
 
7
- <%= render 'maintenance_tasks/runs/info', run: task.last_run, with_status: false if task.last_run %>
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
+ <div class="content" id="custom-content">
19
+ <%= render "maintenance_tasks/runs/info/custom", run: run %>
20
+ </div>
21
+
22
+ <%= render "maintenance_tasks/runs/csv", run: run %>
23
+ <%= tag.hr if run.csv_file.present? && run.arguments.present? %>
24
+ <%= render "maintenance_tasks/runs/arguments", run: run %>
25
+ <% end %>
8
26
  </div>
@@ -4,10 +4,29 @@
4
4
  <%= @task %> <%= status_tag(@task.status) %>
5
5
  </h1>
6
6
 
7
- <%= render 'maintenance_tasks/runs/info', run: @task.last_run, with_status: false if @task.last_run %>
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
+ <div class="content" id="custom-content">
20
+ <%= render "maintenance_tasks/runs/info/custom", run: last_run %>
21
+ </div>
22
+
23
+ <%= render "maintenance_tasks/runs/csv", run: last_run %>
24
+ <%= tag.hr if last_run.csv_file.present? %>
25
+ <%= render "maintenance_tasks/runs/arguments", run: last_run %>
26
+ <%= tag.hr if last_run.arguments.present? %>
27
+ <% end %>
8
28
 
9
29
  <div class="buttons">
10
- <% last_run = @task.last_run %>
11
30
  <% if last_run.nil? || last_run.completed? %>
12
31
  <%= form_with url: run_task_path(@task), method: :put do |form| %>
13
32
  <% if @task.csv_task? %>
@@ -16,16 +35,22 @@
16
35
  <%= form.file_field :csv_file %>
17
36
  </div>
18
37
  <% end %>
19
- <% if @task.parameter_names.any? %>
38
+ <% parameter_names = @task.parameter_names %>
39
+ <% if parameter_names.any? %>
20
40
  <div class="block">
21
- <%= form.fields_for :task_arguments do |ff| %>
22
- <% @task.parameter_names.each do |parameter| %>
23
- <%= ff.label parameter, "#{parameter}: ", class: "label" %>
24
- <%= ff.text_area parameter, class: "textarea" %>
41
+ <%= form.fields_for :task_arguments, @task.new do |ff| %>
42
+ <% parameter_names.each do |parameter_name| %>
43
+ <div class="field">
44
+ <%= ff.label parameter_name, parameter_name, class: "label is-family-monospace" %>
45
+ <div class="control">
46
+ <%= parameter_field(ff, parameter_name) %>
47
+ </div>
48
+ </div>
25
49
  <% end %>
26
50
  <% end %>
27
51
  </div>
28
52
  <% end %>
53
+ <%= render "maintenance_tasks/tasks/custom", form: form %>
29
54
  <div class="block">
30
55
  <%= form.submit 'Run', class: "button is-success", disabled: @task.deleted? %>
31
56
  </div>
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  MaintenanceTasks::Engine.routes.draw do
3
4
  resources :tasks, only: [:index, :show], format: false do
4
5
  member do
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class CreateMaintenanceTasksRuns < ActiveRecord::Migration[6.0]
3
4
  def change
4
5
  create_table(:maintenance_tasks_runs) do |t|
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class RemoveIndexOnTaskName < ActiveRecord::Migration[6.0]
3
4
  def up
4
5
  change_table(:maintenance_tasks_runs) do |t|
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class AddArgumentsToMaintenanceTasksRuns < ActiveRecord::Migration[6.0]
3
4
  def change
4
5
  add_column(:maintenance_tasks_runs, :arguments, :text)
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddLockVersionToMaintenanceTasksRuns < ActiveRecord::Migration[6.0]
4
+ def change
5
+ add_column(:maintenance_tasks_runs, :lock_version, :integer,
6
+ default: 0, null: false)
7
+ end
8
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module MaintenanceTasks
3
4
  # Generator used to set up the engine in the host application. It handles
4
5
  # mounting the engine and installing migrations.
@@ -12,10 +12,17 @@ module MaintenanceTasks
12
12
  class_option :csv, type: :boolean, default: false,
13
13
  desc: "Generate a CSV Task."
14
14
 
15
+ class_option :no_collection, type: :boolean, default: false,
16
+ desc: "Generate a collection-less Task."
17
+
15
18
  check_class_collision suffix: "Task"
16
19
 
17
20
  # Creates the Task file.
18
21
  def create_task_file
22
+ if options[:csv] && options[:no_collection]
23
+ raise "Multiple Task type options provided. Please use either "\
24
+ "--csv or --no-collection."
25
+ end
19
26
  template_file = File.join(
20
27
  "app/tasks/#{tasks_module_file_path}",
21
28
  class_path,
@@ -23,6 +30,8 @@ module MaintenanceTasks
23
30
  )
24
31
  if options[:csv]
25
32
  template("csv_task.rb", template_file)
33
+ elsif no_collection?
34
+ template("no_collection_task.rb", template_file)
26
35
  else
27
36
  template("task.rb", template_file)
28
37
  end
@@ -76,5 +85,9 @@ module MaintenanceTasks
76
85
  def test_framework
77
86
  Rails.application.config.generators.options[:rails][:test_framework]
78
87
  end
88
+
89
+ def no_collection?
90
+ options[:no_collection]
91
+ end
79
92
  end
80
93
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= tasks_module %>
4
+ <% module_namespacing do -%>
5
+ class <%= class_name %>Task < MaintenanceTasks::Task
6
+ no_collection
7
+
8
+ def process
9
+ # The work to be done
10
+ end
11
+ end
12
+ <% end -%>
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module <%= tasks_module %>
5
+ <% module_namespacing do -%>
6
+ class <%= class_name %>TaskTest < ActiveSupport::TestCase
7
+ # test "#process performs a task iteration" do
8
+ # <%= tasks_module %>::<%= class_name %>Task.process
9
+ # end
10
+ end
11
+ <% end -%>
12
+ end
@@ -9,7 +9,9 @@ module <%= tasks_module %>
9
9
  end
10
10
 
11
11
  def process(element)
12
- # The work to be done in a single iteration of the task
12
+ # The work to be done in a single iteration of the task.
13
+ # This should be idempotent, as the same element may be processed more
14
+ # than once if the task is interrupted and resumed.
13
15
  end
14
16
 
15
17
  def count
@@ -5,7 +5,11 @@ module <%= tasks_module %>
5
5
  <% module_namespacing do -%>
6
6
  class <%= class_name %>TaskTest < ActiveSupport::TestCase
7
7
  # test "#process performs a task iteration" do
8
+ <%- if no_collection? -%>
9
+ # <%= tasks_module %>::<%= class_name %>Task.process
10
+ <%- else -%>
8
11
  # <%= tasks_module %>::<%= class_name %>Task.process(element)
12
+ <%- end -%>
9
13
  # end
10
14
  end
11
15
  <% end -%>
@@ -25,12 +25,13 @@ module MaintenanceTasks
25
25
  LONGDESC
26
26
 
27
27
  # Specify the CSV file to process for CSV Tasks
28
- option :csv, desc: "Supply a CSV file to be processed by a CSV Task, "\
29
- '--csv "path/to/csv/file.csv"'
30
-
28
+ desc = "Supply a CSV file to be processed by a CSV Task, "\
29
+ "--csv path/to/csv/file.csv"
30
+ option :csv, desc: desc
31
31
  # Specify arguments to supply to a Task supporting parameters
32
- option :arguments, type: :hash, desc: "Supply arguments for a Task that "\
33
- "accepts parameters as a set of <key>:<value> pairs."
32
+ desc = "Supply arguments for a Task that accepts parameters as a set of "\
33
+ "<key>:<value> pairs."
34
+ option :arguments, type: :hash, desc: desc
34
35
 
35
36
  # Command to run a Task.
36
37
  #
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "active_record/railtie"
3
4
 
4
5
  module MaintenanceTasks
@@ -7,10 +8,23 @@ module MaintenanceTasks
7
8
  class Engine < ::Rails::Engine
8
9
  isolate_namespace MaintenanceTasks
9
10
 
10
- initializer "eager_load_for_classic_autoloader" do
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
11
21
  eager_load! unless Rails.autoloaders.zeitwerk_enabled?
12
22
  end
13
23
 
24
+ initializer "maintenance_tasks.configs" do
25
+ MaintenanceTasks.backtrace_cleaner = Rails.backtrace_cleaner
26
+ end
27
+
14
28
  config.to_prepare do
15
29
  _ = TaskJobConcern # load this for JobIteration compatibility check
16
30
  unless Rails.autoloaders.zeitwerk_enabled?
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "action_controller"
3
4
  require "action_view"
4
5
  require "active_job"
@@ -52,6 +53,16 @@ module MaintenanceTasks
52
53
  # app's config/storage.yml.
53
54
  mattr_accessor :active_storage_service
54
55
 
56
+ # @!attribute backtrace_cleaner
57
+ # @scope class
58
+ #
59
+ # The Active Support backtrace cleaner that will be used to clean the
60
+ # backtrace of a Task that errors.
61
+ #
62
+ # @return [ActiveSupport::BacktraceCleaner, nil] the backtrace cleaner to
63
+ # use when cleaning a Run's backtrace.
64
+ mattr_accessor :backtrace_cleaner
65
+
55
66
  # @private
56
67
  def self.error_handler
57
68
  return @error_handler if defined?(@error_handler)
@@ -63,7 +74,7 @@ module MaintenanceTasks
63
74
  unless error_handler.arity == 3
64
75
  ActiveSupport::Deprecation.warn(
65
76
  "MaintenanceTasks.error_handler should be a lambda that takes three "\
66
- "arguments: error, task_context, and errored_element."
77
+ "arguments: error, task_context, and errored_element."
67
78
  )
68
79
  @error_handler = ->(error, _task_context, _errored_element) do
69
80
  error_handler.call(error)
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.0
4
+ version: 1.8.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-06-07 00:00:00.000000000 Z
11
+ date: 2022-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -97,21 +97,25 @@ 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/csv_collection.rb
100
+ - app/models/maintenance_tasks/csv_collection_builder.rb
101
+ - app/models/maintenance_tasks/no_collection_builder.rb
102
+ - app/models/maintenance_tasks/null_collection_builder.rb
101
103
  - app/models/maintenance_tasks/progress.rb
102
104
  - app/models/maintenance_tasks/run.rb
103
105
  - app/models/maintenance_tasks/runner.rb
104
106
  - app/models/maintenance_tasks/runs_page.rb
107
+ - app/models/maintenance_tasks/task.rb
105
108
  - app/models/maintenance_tasks/task_data.rb
106
109
  - app/models/maintenance_tasks/ticker.rb
107
- - app/tasks/maintenance_tasks/task.rb
108
110
  - app/validators/maintenance_tasks/run_status_validator.rb
109
111
  - app/views/layouts/maintenance_tasks/_navbar.html.erb
110
112
  - app/views/layouts/maintenance_tasks/application.html.erb
111
- - app/views/maintenance_tasks/runs/_info.html.erb
113
+ - app/views/maintenance_tasks/runs/_arguments.html.erb
114
+ - app/views/maintenance_tasks/runs/_csv.html.erb
112
115
  - app/views/maintenance_tasks/runs/_run.html.erb
113
116
  - app/views/maintenance_tasks/runs/info/_cancelled.html.erb
114
117
  - app/views/maintenance_tasks/runs/info/_cancelling.html.erb
118
+ - app/views/maintenance_tasks/runs/info/_custom.html.erb
115
119
  - app/views/maintenance_tasks/runs/info/_enqueued.html.erb
116
120
  - app/views/maintenance_tasks/runs/info/_errored.html.erb
117
121
  - app/views/maintenance_tasks/runs/info/_interrupted.html.erb
@@ -119,6 +123,7 @@ files:
119
123
  - app/views/maintenance_tasks/runs/info/_pausing.html.erb
120
124
  - app/views/maintenance_tasks/runs/info/_running.html.erb
121
125
  - app/views/maintenance_tasks/runs/info/_succeeded.html.erb
126
+ - app/views/maintenance_tasks/tasks/_custom.html.erb
122
127
  - app/views/maintenance_tasks/tasks/_task.html.erb
123
128
  - app/views/maintenance_tasks/tasks/index.html.erb
124
129
  - app/views/maintenance_tasks/tasks/show.html.erb
@@ -126,10 +131,13 @@ files:
126
131
  - db/migrate/20201211151756_create_maintenance_tasks_runs.rb
127
132
  - db/migrate/20210225152418_remove_index_on_task_name.rb
128
133
  - db/migrate/20210517131953_add_arguments_to_maintenance_tasks_runs.rb
134
+ - db/migrate/20211210152329_add_lock_version_to_maintenance_tasks_runs.rb
129
135
  - exe/maintenance_tasks
130
136
  - lib/generators/maintenance_tasks/install_generator.rb
131
137
  - lib/generators/maintenance_tasks/task_generator.rb
132
138
  - lib/generators/maintenance_tasks/templates/csv_task.rb.tt
139
+ - lib/generators/maintenance_tasks/templates/no_collection_task.rb.tt
140
+ - lib/generators/maintenance_tasks/templates/no_collection_task_test.rb.tt
133
141
  - lib/generators/maintenance_tasks/templates/task.rb.tt
134
142
  - lib/generators/maintenance_tasks/templates/task_spec.rb.tt
135
143
  - lib/generators/maintenance_tasks/templates/task_test.rb.tt
@@ -142,7 +150,7 @@ homepage: https://github.com/Shopify/maintenance_tasks
142
150
  licenses:
143
151
  - MIT
144
152
  metadata:
145
- source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.4.0
153
+ source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v1.8.0
146
154
  allowed_push_host: https://rubygems.org
147
155
  post_install_message:
148
156
  rdoc_options: []
@@ -159,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
167
  - !ruby/object:Gem::Version
160
168
  version: '0'
161
169
  requirements: []
162
- rubygems_version: 3.2.17
170
+ rubygems_version: 3.2.20
163
171
  signing_key:
164
172
  specification_version: 4
165
173
  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