sidekiq-tasks 1.1.1 → 1.2.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/CHANGELOG.md +14 -0
  4. data/README.md +96 -0
  5. data/docs/custom_storage.md +44 -11
  6. data/lib/sidekiq/tasks/config.rb +28 -9
  7. data/lib/sidekiq/tasks/job.rb +3 -2
  8. data/lib/sidekiq/tasks/magic_comments/comment.rb +28 -0
  9. data/lib/sidekiq/tasks/magic_comments/comments.rb +31 -0
  10. data/lib/sidekiq/tasks/magic_comments/handlers/base.rb +26 -0
  11. data/lib/sidekiq/tasks/magic_comments/handlers/disable.rb +17 -0
  12. data/lib/sidekiq/tasks/magic_comments/handlers/dry_run.rb +17 -0
  13. data/lib/sidekiq/tasks/magic_comments/handlers/enable.rb +17 -0
  14. data/lib/sidekiq/tasks/magic_comments/handlers/sidekiq_options.rb +32 -0
  15. data/lib/sidekiq/tasks/magic_comments/registration.rb +11 -0
  16. data/lib/sidekiq/tasks/magic_comments/registry.rb +19 -0
  17. data/lib/sidekiq/tasks/magic_comments/scanner.rb +83 -0
  18. data/lib/sidekiq/tasks/magic_comments.rb +20 -0
  19. data/lib/sidekiq/tasks/run.rb +161 -0
  20. data/lib/sidekiq/tasks/sidekiq_options_validator.rb +25 -0
  21. data/lib/sidekiq/tasks/storage/base.rb +22 -0
  22. data/lib/sidekiq/tasks/storage/redis.rb +47 -26
  23. data/lib/sidekiq/tasks/strategies/base.rb +5 -2
  24. data/lib/sidekiq/tasks/strategies/rake_task.rb +26 -2
  25. data/lib/sidekiq/tasks/strategies/rules/disable_with_comment.rb +2 -2
  26. data/lib/sidekiq/tasks/strategies/rules/enable_with_comment.rb +8 -56
  27. data/lib/sidekiq/tasks/task.rb +24 -7
  28. data/lib/sidekiq/tasks/task_metadata.rb +18 -2
  29. data/lib/sidekiq/tasks/version.rb +1 -1
  30. data/lib/sidekiq/tasks/web/extension.rb +2 -1
  31. data/lib/sidekiq/tasks/web/helpers/tag_helper.rb +1 -1
  32. data/lib/sidekiq/tasks/web/helpers/task_helper.rb +19 -0
  33. data/lib/sidekiq/tasks.rb +18 -1
  34. data/web/assets/tasks/css/components/alerts.css +25 -0
  35. data/web/assets/tasks/css/components/report.css +70 -0
  36. data/web/assets/tasks/css/ext.css +2 -0
  37. data/web/locales/en.yml +10 -0
  38. data/web/locales/fr.yml +10 -0
  39. data/web/views/task.erb +87 -3
  40. metadata +31 -1
data/lib/sidekiq/tasks.rb CHANGED
@@ -3,15 +3,19 @@
3
3
  require "rake"
4
4
 
5
5
  require_relative "tasks/errors"
6
+ require_relative "tasks/validations"
7
+ require_relative "tasks/sidekiq_options_validator"
8
+ require_relative "tasks/magic_comments"
6
9
  require_relative "tasks/storage"
7
10
  require_relative "tasks/strategies"
8
- require_relative "tasks/validations"
9
11
  require_relative "tasks/version"
10
12
 
11
13
  module Sidekiq
12
14
  module Tasks
13
15
  autoload :Config, "sidekiq/tasks/config"
14
16
  autoload :Job, "sidekiq/tasks/job"
17
+ autoload :Report, "sidekiq/tasks/run"
18
+ autoload :Run, "sidekiq/tasks/run"
15
19
  autoload :Set, "sidekiq/tasks/set"
16
20
  autoload :Task, "sidekiq/tasks/task"
17
21
  autoload :TaskMetadata, "sidekiq/tasks/task_metadata"
@@ -32,6 +36,19 @@ module Sidekiq
32
36
  def tasks
33
37
  @_tasks ||= Sidekiq::Tasks::Set.new(strategies.flat_map(&:tasks))
34
38
  end
39
+
40
+ # @return [Sidekiq::Tasks::Run] The run of the task being executed, see Sidekiq::Tasks::Run.current.
41
+ def current_run
42
+ Sidekiq::Tasks::Run.current
43
+ end
44
+
45
+ def dry_run?
46
+ current_run.dry_run?
47
+ end
48
+
49
+ def report
50
+ current_run.report
51
+ end
35
52
  end
36
53
  end
37
54
  end
@@ -0,0 +1,25 @@
1
+ .st-alert {
2
+ display: block;
3
+ padding: 12px 16px;
4
+ border-radius: 6px;
5
+ border: 1px solid transparent;
6
+ margin: 12px 0;
7
+ font-size: 13px;
8
+ line-height: 1.5;
9
+ }
10
+
11
+ .st-alert.failure {
12
+ color: var(--badge-failure-text);
13
+ background-color: var(--badge-failure-bg);
14
+ border-color: var(--badge-failure-border);
15
+ }
16
+
17
+ .st-alert-title {
18
+ font-weight: 600;
19
+ margin-bottom: 4px;
20
+ }
21
+
22
+ .st-alert-body code {
23
+ display: inline-block;
24
+ word-break: break-all;
25
+ }
@@ -0,0 +1,70 @@
1
+ :root {
2
+ --badge-dry-run-text: #5b3a8c;
3
+ --badge-dry-run-bg: #efe6fb;
4
+ --badge-dry-run-border: #d3c0f0;
5
+ --st-warning-text: #8a6d1d;
6
+ }
7
+
8
+ @media (prefers-color-scheme: dark) {
9
+ :root {
10
+ --badge-dry-run-text: #d3c0f0;
11
+ --badge-dry-run-bg: #2c2140;
12
+ --badge-dry-run-border: #5b3a8c;
13
+ --st-warning-text: #f5e6ab;
14
+ }
15
+ }
16
+
17
+ .st-status-badge.dry-run {
18
+ color: var(--badge-dry-run-text);
19
+ background-color: var(--badge-dry-run-bg);
20
+ border-color: var(--badge-dry-run-border);
21
+ }
22
+
23
+ .st-report-value {
24
+ margin-right: 12px;
25
+ white-space: nowrap;
26
+ }
27
+
28
+ .st-report-row details {
29
+ padding: 4px 0 8px;
30
+ }
31
+
32
+ .st-report-row summary {
33
+ cursor: pointer;
34
+ list-style: none;
35
+ }
36
+
37
+ .st-report-row summary::-webkit-details-marker {
38
+ display: none;
39
+ }
40
+
41
+ .st-report-row summary::before {
42
+ content: "▸ ";
43
+ }
44
+
45
+ .st-report-row details[open] > summary::before {
46
+ content: "▾ ";
47
+ }
48
+
49
+ .st-report-list {
50
+ max-height: 400px;
51
+ overflow-y: auto;
52
+ margin-bottom: 8px;
53
+ }
54
+
55
+ .st-report-table {
56
+ margin: 0;
57
+ }
58
+
59
+ .st-checkbox-label {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 8px;
63
+ font-weight: bold;
64
+ font-size: 14px;
65
+ }
66
+
67
+ .st-warning {
68
+ color: var(--st-warning-text);
69
+ margin: 0;
70
+ }
@@ -6,3 +6,5 @@
6
6
  @import url("components/pagination.css");
7
7
  @import url("components/status_badges.css");
8
8
  @import url("components/tooltips.css");
9
+ @import url("components/alerts.css");
10
+ @import url("components/report.css");
data/web/locales/en.yml CHANGED
@@ -27,3 +27,13 @@ en:
27
27
  failure: "Failure"
28
28
  enqueued_by: "Enqueued by"
29
29
  task_time: "%m/%d/%y %H:%M:%S"
30
+ options: "Options"
31
+ task_broken_title: "This task cannot be executed"
32
+ task_broken_message: "One of its magic comments is invalid:"
33
+ result: "Result"
34
+ dry_run: "Dry run"
35
+ dry_run_hint: "Uncheck to execute the task for real."
36
+ dry_run_unsupported: "This task does not handle dry run mode: it will be executed for real."
37
+ report_details: "Report details"
38
+ report_items_shown: "%{shown} displayed out of %{count}"
39
+ report_truncated: "Report truncated (size limit reached)"
data/web/locales/fr.yml CHANGED
@@ -27,3 +27,13 @@ fr:
27
27
  failure: "Echec"
28
28
  enqueued_by: "Lancée par"
29
29
  task_time: "%d/%m/%y %H:%M:%S"
30
+ options: "Options"
31
+ task_broken_title: "Cette tâche ne peut pas être exécutée"
32
+ task_broken_message: "Un de ses magic comments est invalide :"
33
+ result: "Résultat"
34
+ dry_run: "Simulation"
35
+ dry_run_hint: "Décocher pour exécuter réellement la tâche."
36
+ dry_run_unsupported: "Cette tâche ne gère pas le mode simulation : elle sera exécutée réellement."
37
+ report_details: "Détail du rapport"
38
+ report_items_shown: "%{shown} affichés sur %{count}"
39
+ report_truncated: "Rapport tronqué (limite de taille atteinte)"
data/web/views/task.erb CHANGED
@@ -14,6 +14,17 @@
14
14
  <h1><%= t("task") %></h1>
15
15
  </header>
16
16
 
17
+ <% if task.error? %>
18
+ <div class="st-alert failure">
19
+ <div class="st-alert-title"><%= t("task_broken_title") %></div>
20
+ <div class="st-alert-body">
21
+ <%= t("task_broken_message") %>
22
+ <br>
23
+ <code><%= task.error %></code>
24
+ </div>
25
+ </div>
26
+ <% end %>
27
+
17
28
  <table class="st-table">
18
29
  <tbody>
19
30
  <tr>
@@ -28,6 +39,12 @@
28
39
  <th><%= t("strategy") %></th>
29
40
  <td><%= task.strategy.name %></td>
30
41
  </tr>
42
+ <% unless task.error? || task.sidekiq_options.empty? %>
43
+ <tr>
44
+ <th><%= t("options") %></th>
45
+ <td><code><%= format_task_sidekiq_options(task) %></code></td>
46
+ </tr>
47
+ <% end %>
31
48
  <tr>
32
49
  <th><%= t("last_enqueued") %></th>
33
50
  <td><%= task.last_enqueue_at ? relative_time(task.last_enqueue_at) : "-" %></td>
@@ -57,18 +74,20 @@
57
74
  <th><%= t("executed") %></th>
58
75
  <th><%= t("duration") %></th>
59
76
  <th><%= t("status") %></th>
77
+ <th><%= t("result") %></th>
60
78
  </tr>
61
79
  </thead>
62
80
  <tbody>
63
- <% history_entries.each do |jid_history| %>
81
+ <% history_entries.each_with_index do |jid_history, index| %>
82
+ <% report = jid_history["report"] || {} %>
64
83
  <tr>
65
84
  <td><%= jid_history["jid"] %></td>
66
85
  <td>
67
- <code><%= jid_history["args"] %></code>
86
+ <code><%= ERB::Util.html_escape(jid_history["args"]) %></code>
68
87
  </td>
69
88
  <% if Sidekiq::Tasks.config.current_user %>
70
89
  <td>
71
- <code><%= jid_history["user"] || "-" %></code>
90
+ <code><%= ERB::Util.html_escape(jid_history["user"] || "-") %></code>
72
91
  </td>
73
92
  <% end %>
74
93
  <td>
@@ -87,8 +106,59 @@
87
106
  class: "st-status-badge #{task_status(jid_history)}",
88
107
  "data-tooltip": jid_history["error"]
89
108
  ) %>
109
+ <% if jid_history["dry_run"] %>
110
+ <span class="st-status-badge dry-run"><%= t("dry_run") %></span>
111
+ <% end %>
112
+ </td>
113
+ <td class="st-report-values">
114
+ <% (report["values"] || {}).each do |key, value| %>
115
+ <span class="st-report-value">
116
+ <strong><%= ERB::Util.html_escape(key) %></strong> <%= ERB::Util.html_escape(value) %>
117
+ </span>
118
+ <% end %>
119
+ <% if report["truncated"] %>
120
+ <small class="st-warning"><%= t("report_truncated") %></small>
121
+ <% end %>
90
122
  </td>
91
123
  </tr>
124
+ <% if report["lists"]&.any? %>
125
+ <tr class="st-report-row">
126
+ <td colspan="<%= Sidekiq::Tasks.config.current_user ? 8 : 7 %>">
127
+ <details <%= "open" if index.zero? && history_page == 1 %>>
128
+ <summary><%= t("report_details") %></summary>
129
+ <% report["lists"].each do |key, list| %>
130
+ <% columns = report_list_columns(list["items"]) %>
131
+ <h4>
132
+ <%= ERB::Util.html_escape(key) %> (<%= list["count"] %>)
133
+ <% if list["items"].size < list["count"] %>
134
+ <small><%= t("report_items_shown", shown: list["items"].size, count: list["count"]) %></small>
135
+ <% end %>
136
+ </h4>
137
+ <div class="st-report-list">
138
+ <table class="st-table st-report-table">
139
+ <% if columns %>
140
+ <thead>
141
+ <tr><% columns.each do |column| %><th><%= ERB::Util.html_escape(column) %></th><% end %></tr>
142
+ </thead>
143
+ <% end %>
144
+ <tbody>
145
+ <% list["items"].each do |item| %>
146
+ <tr>
147
+ <% if columns %>
148
+ <% columns.each do |column| %><td><%= ERB::Util.html_escape(item[column]) %></td><% end %>
149
+ <% else %>
150
+ <td><%= ERB::Util.html_escape(item) %></td>
151
+ <% end %>
152
+ </tr>
153
+ <% end %>
154
+ </tbody>
155
+ </table>
156
+ </div>
157
+ <% end %>
158
+ </details>
159
+ </td>
160
+ </tr>
161
+ <% end %>
92
162
  <% end %>
93
163
  </tbody>
94
164
  </table>
@@ -106,6 +176,7 @@
106
176
  <% end %>
107
177
  </div>
108
178
 
179
+ <% unless task.error? %>
109
180
  <header class="">
110
181
  <div class="">
111
182
  <h2><%= t("run_task") %></h2>
@@ -124,6 +195,18 @@
124
195
  <% end %>
125
196
  </div>
126
197
 
198
+ <div class="st-form-group-full">
199
+ <% if task.dry_run_supported? %>
200
+ <label class="st-checkbox-label">
201
+ <input type="checkbox" id="dryRunInput" name="dry_run" value="1" checked>
202
+ <%= t("dry_run") %>
203
+ </label>
204
+ <small><%= t("dry_run_hint") %></small>
205
+ <% else %>
206
+ <p class="st-warning"><%= t("dry_run_unsupported") %></p>
207
+ <% end %>
208
+ </div>
209
+
127
210
  <div class="st-form-group-full">
128
211
  <label for="envConfirmationInput" class="st-label">
129
212
  <%= t("env_confirmation", current_env: current_env) %>
@@ -143,6 +226,7 @@
143
226
  <%= t("enqueue") %>
144
227
  </button>
145
228
  </form>
229
+ <% end %>
146
230
 
147
231
  <% if Sidekiq::Tasks::Web::SIDEKIQ_GTE_7_3_0 %>
148
232
  <%= script_tag "tasks/js/env_confirmation.js" %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Capsens
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: prism
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.5'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.5'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: rake
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -243,7 +257,20 @@ files:
243
257
  - lib/sidekiq/tasks/config.rb
244
258
  - lib/sidekiq/tasks/errors.rb
245
259
  - lib/sidekiq/tasks/job.rb
260
+ - lib/sidekiq/tasks/magic_comments.rb
261
+ - lib/sidekiq/tasks/magic_comments/comment.rb
262
+ - lib/sidekiq/tasks/magic_comments/comments.rb
263
+ - lib/sidekiq/tasks/magic_comments/handlers/base.rb
264
+ - lib/sidekiq/tasks/magic_comments/handlers/disable.rb
265
+ - lib/sidekiq/tasks/magic_comments/handlers/dry_run.rb
266
+ - lib/sidekiq/tasks/magic_comments/handlers/enable.rb
267
+ - lib/sidekiq/tasks/magic_comments/handlers/sidekiq_options.rb
268
+ - lib/sidekiq/tasks/magic_comments/registration.rb
269
+ - lib/sidekiq/tasks/magic_comments/registry.rb
270
+ - lib/sidekiq/tasks/magic_comments/scanner.rb
271
+ - lib/sidekiq/tasks/run.rb
246
272
  - lib/sidekiq/tasks/set.rb
273
+ - lib/sidekiq/tasks/sidekiq_options_validator.rb
247
274
  - lib/sidekiq/tasks/storage.rb
248
275
  - lib/sidekiq/tasks/storage/base.rb
249
276
  - lib/sidekiq/tasks/storage/redis.rb
@@ -270,9 +297,11 @@ files:
270
297
  - lib/sidekiq/tasks/web/params.rb
271
298
  - lib/sidekiq/tasks/web/search.rb
272
299
  - sig/sidekiq/tasks.rbs
300
+ - web/assets/tasks/css/components/alerts.css
273
301
  - web/assets/tasks/css/components/buttons.css
274
302
  - web/assets/tasks/css/components/forms.css
275
303
  - web/assets/tasks/css/components/pagination.css
304
+ - web/assets/tasks/css/components/report.css
276
305
  - web/assets/tasks/css/components/status_badges.css
277
306
  - web/assets/tasks/css/components/tables.css
278
307
  - web/assets/tasks/css/components/tooltips.css
@@ -293,6 +322,7 @@ metadata:
293
322
  homepage_uri: https://github.com/CapSens/sidekiq-tasks
294
323
  source_code_uri: https://github.com/CapSens/sidekiq-tasks/blob/master
295
324
  changelog_uri: https://github.com/CapSens/sidekiq-tasks/blob/master/CHANGELOG.md
325
+ rubygems_mfa_required: 'true'
296
326
  rdoc_options: []
297
327
  require_paths:
298
328
  - lib