maintenance_tasks 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c3c4c94cf355432e0d558e68bfc3f275972164c8ed932d2505b7c6450f0d124
4
- data.tar.gz: 1b80ad4b58b9546d5ab2af77d2d0e64f8bd8b72dc6641ff445d33a67dae03860
3
+ metadata.gz: 8c13ec8d79682d304378d636955e9726cd1d67ebb167a549a2d6479f7eea6712
4
+ data.tar.gz: bf7026b08f0f442c3c074118dfca1cbae4babd7d234b97dc63cf66cdf94db67b
5
5
  SHA512:
6
- metadata.gz: 7402e24bfbc370c6af54b441d2b1050f252ee44f51ab11612875fed7fa6822645420422dc33405b1665596e66f85f8fe1f8b1e443d023d451a626913afe6dc98
7
- data.tar.gz: 8f4666aba4abc6f01d77b238de6b6d511d24a5d4932f5ec2499f0e91faefe2e8a3b18435109864c821495b2efde464dd3212a76eae5276b4e622eb1cb6f7da3c
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>.
@@ -93,7 +93,6 @@ module MaintenanceTasks
93
93
  if @task.respond_to?(:csv_content=)
94
94
  @task.csv_content = @run.csv_file.download
95
95
  end
96
- @run.job_id = job_id
97
96
 
98
97
  @run.running! unless @run.stopping?
99
98
 
@@ -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: Rails.backtrace_cleaner.clean(error.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 <= 5.minutes.ago
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.enqueued!
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 MaintenanceTasks.job.constantize.perform_later(run)
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", "cancelling", "cancelled"],
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 %>
@@ -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,16 @@
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
+ <%= 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>
@@ -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,19 @@
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
+ <%= 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
- <%= 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
+ <%= 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
- <%= ff.label parameter, "#{parameter}: ", class: "label" %>
24
- <%= ff.text_area parameter, class: "textarea" %>
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>
@@ -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.0
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-06-07 00:00:00.000000000 Z
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/_info.html.erb
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.4.0
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.17
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 %>