good_job 4.7.0 → 4.8.1

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: 00f71f047b33832b758797f8fb9c7987a13eae1abb1750467dcbbab12c7680b0
4
- data.tar.gz: 4a9f501a236f45781904d2468cef99d05cea42ac5d76568d8b72ae437823e3e6
3
+ metadata.gz: ad6949cd77548ff686d2824d654f609567f110b1e778975f72f13aec0eeda672
4
+ data.tar.gz: bcfa0c1941d237dc5e4a1b8611d1987b1ddef282ac2a4417306f7664032c2c69
5
5
  SHA512:
6
- metadata.gz: 575e7338adaaaa661f4f0d219ddbaac20dff3547f9878098d51ab71a54dce5660467d2f45d492dd6fa79496143f6482e170557a7b8a230e25853297c9811eba6
7
- data.tar.gz: 5bdd469825d81387e4071900576ea664e820c98c74f7d6a710d3d39fc5c750af4db0a63fc4d0e0af9faf5481e73f1b6107b3ff88c77a257c9c49d02dda7667f8
6
+ metadata.gz: 36643826c085b2192a63bc917d9271079e6517762d84f0fbf4310e56be6b10eb5d221e53cd526c88668300a3716b527dcfe94cc7f0cc5ba8163503f65770e4e1
7
+ data.tar.gz: 8fe8418c883034d7e7e008a37b2617b3965582623fd87c034cdc72bd8798c760df3917a3e5b4e2d0cf9d2caa255cfe3924f0e97b4c110f361c61b00d55fa99db
data/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.8.1](https://github.com/bensheldon/good_job/tree/v4.8.1) (2025-01-24)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.8.0...v4.8.1)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - Fix notifier/scheduler handling of integer/epoch serialized scheduled\_at values [\#1583](https://github.com/bensheldon/good_job/pull/1583) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Closed issues:**
12
+
13
+ - Losing "Processes" on the dashboard [\#1582](https://github.com/bensheldon/good_job/issues/1582)
14
+ - Notifier errored: TypeError: ActiveSupport::TimeWithZone can't be coerced into Integer [\#1581](https://github.com/bensheldon/good_job/issues/1581)
15
+ - Ability to pause queues [\#1574](https://github.com/bensheldon/good_job/issues/1574)
16
+
17
+ ## [v4.8.0](https://github.com/bensheldon/good_job/tree/v4.8.0) (2025-01-22)
18
+
19
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.7.0...v4.8.0)
20
+
21
+ **Implemented enhancements:**
22
+
23
+ - Add ability to pause jobs by queue, job class, or label \(experimental\) [\#1575](https://github.com/bensheldon/good_job/pull/1575) ([bensheldon](https://github.com/bensheldon))
24
+
25
+ **Closed issues:**
26
+
27
+ - perform\_now enqueues a job when raising exception [\#1570](https://github.com/bensheldon/good_job/issues/1570)
28
+
29
+ **Merged pull requests:**
30
+
31
+ - Use Ruby 3.4.1 for development [\#1579](https://github.com/bensheldon/good_job/pull/1579) ([bensheldon](https://github.com/bensheldon))
32
+ - Fix generator tests [\#1577](https://github.com/bensheldon/good_job/pull/1577) ([bensheldon](https://github.com/bensheldon))
33
+ - Add the logger gem as a dependency to fix rails head [\#1576](https://github.com/bensheldon/good_job/pull/1576) ([bensheldon](https://github.com/bensheldon))
34
+ - fix: typo in en.yml when discarding jobs [\#1569](https://github.com/bensheldon/good_job/pull/1569) ([nickstanish](https://github.com/nickstanish))
35
+ - Bump the all group with 60 updates [\#1567](https://github.com/bensheldon/good_job/pull/1567) ([dependabot[bot]](https://github.com/apps/dependabot))
36
+
3
37
  ## [v4.7.0](https://github.com/bensheldon/good_job/tree/v4.7.0) (2024-12-31)
4
38
 
5
39
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.6.0...v4.7.0)
data/README.md CHANGED
@@ -73,6 +73,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
73
73
  - [Write tests](#write-tests)
74
74
  - [PgBouncer compatibility](#pgbouncer-compatibility)
75
75
  - [CLI HTTP health check probes](#cli-http-health-check-probes)
76
+ - [Pausing Jobs](#pausing-jobs)
76
77
  - [Doing your best job with GoodJob](#doing-your-best-job-with-goodjob)
77
78
  - [Sizing jobs: mice and elephants](#sizing-jobs-mice-and-elephants)
78
79
  - [Isolating by total latency](#isolating-by-total-latency)
@@ -329,6 +330,8 @@ Available configuration options are:
329
330
  config.good_job.probe_handler = 'webrick'
330
331
  ```
331
332
 
333
+ - `enable_pauses` (boolean) whether job processing can be paused. Defaults to `false`. You can also set this with the environment variable `GOOD_JOB_ENABLE_PAUSES`.
334
+
332
335
  By default, GoodJob configures the following execution modes per environment:
333
336
 
334
337
  ```ruby
@@ -1559,9 +1562,35 @@ gem 'webrick'
1559
1562
 
1560
1563
  If WEBrick is configured to be used, but the dependency is not found, GoodJob will log a warning and fallback to the default probe server.
1561
1564
 
1565
+ ### Pausing Jobs
1566
+
1567
+ GoodJob allows for pausing jobs by queue or job class. This feature is currently opt-in because the performance impact of loading and filtering these attributes is not yet known. To enable this feature, add the following to your configuration:
1568
+
1569
+ > ```ruby
1570
+ > config.good_job.enable_pauses = true
1571
+ > ```
1572
+
1573
+ Pausing can be done via the Dashboard's Performance page, or in Ruby
1574
+
1575
+ ```ruby
1576
+ # To pause:
1577
+ GoodJob.pause(queue: "default")
1578
+ GoodJob.pause(job_class: "MyJob")
1579
+
1580
+ # To check status
1581
+ GoodJob.paused # => { queues: ["default"], job_classes: ["MyJob"] }
1582
+ GoodJob.paused?(queue: "default") # => true
1583
+ GoodJob.paused?(job_class: "MyJob") # => true
1584
+ GoodJob.paused? # => true
1585
+
1586
+ # To unpause
1587
+ GoodJob.unpause(queue: "default")
1588
+ GoodJob.unpause(job_class: "MyJob")
1589
+ ````
1590
+
1562
1591
  ## Doing your best job with GoodJob
1563
1592
 
1564
- _This section explains how to use GoodJob the most efficiently and performantly, according to its maintainers. GoodJob is very flexible and you dont necessarily have to use it this way, but the concepts explained here are part of GoodJobs design intent._
1593
+ _This section explains how to use GoodJob the most efficiently and performantly, according to its maintainers. GoodJob is very flexible and you don't necessarily have to use it this way, but the concepts explained here are part of GoodJob's design intent._
1565
1594
 
1566
1595
  Background jobs are hard. There are two extremes:
1567
1596
 
@@ -6,6 +6,7 @@ module GoodJob
6
6
  jobs_count = GoodJob::Job.count
7
7
  batches_count = GoodJob::BatchRecord.all.size
8
8
  cron_entries_count = GoodJob::CronEntry.all.size
9
+ pauses_count = GoodJob::Setting.paused.values.sum(&:count)
9
10
  processes_count = GoodJob::Process.active.count
10
11
  discarded_count = GoodJob::Job.discarded.count
11
12
 
@@ -13,6 +14,7 @@ module GoodJob
13
14
  jobs_count: helpers.number_to_human(jobs_count),
14
15
  batches_count: helpers.number_to_human(batches_count),
15
16
  cron_entries_count: helpers.number_to_human(cron_entries_count),
17
+ pauses_count: helpers.number_to_human(pauses_count),
16
18
  processes_count: helpers.number_to_human(processes_count),
17
19
  discarded_count: helpers.number_to_human(discarded_count),
18
20
  }
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoodJob
4
+ class PausesController < ApplicationController
5
+ before_action :validate_type, only: [:create, :destroy]
6
+ def index
7
+ @paused = GoodJob::Setting.paused
8
+ end
9
+
10
+ def create
11
+ pause_type = params[:type].to_sym
12
+ pause_value = params[:value].to_s
13
+
14
+ GoodJob::Setting.pause(pause_type => pause_value)
15
+ redirect_to({ action: :index }, notice: "Successfully paused #{params[:type]} '#{params[:value]}'")
16
+ end
17
+
18
+ def destroy
19
+ pause_type = params[:type].to_sym
20
+ pause_value = params[:value].to_s
21
+
22
+ GoodJob::Setting.unpause(pause_type => pause_value)
23
+ redirect_to({ action: :index }, notice: "Successfully unpaused #{params[:type]} '#{params[:value]}'")
24
+ end
25
+
26
+ private
27
+
28
+ def validate_type
29
+ return if params[:type].in?(%w[queue job_class label]) && params[:value].to_s.present?
30
+
31
+ raise ActionController::BadRequest, "Invalid type"
32
+ end
33
+ end
34
+ end
@@ -3,17 +3,21 @@
3
3
  module GoodJob
4
4
  class PerformanceController < ApplicationController
5
5
  def index
6
- @performances = GoodJob::Execution
7
- .where.not(job_class: nil)
8
- .group(:job_class)
9
- .select("
10
- job_class,
11
- COUNT(*) AS executions_count,
12
- AVG(duration) AS avg_duration,
13
- MIN(duration) AS min_duration,
14
- MAX(duration) AS max_duration
15
- ")
16
- .order("job_class")
6
+ @performances = GoodJob::Execution.group(:job_class).select("
7
+ job_class,
8
+ COUNT(*) AS executions_count,
9
+ AVG(duration) AS avg_duration,
10
+ MIN(duration) AS min_duration,
11
+ MAX(duration) AS max_duration
12
+ ").order(:job_class)
13
+
14
+ @queue_performances = GoodJob::Execution.group(:queue_name).select("
15
+ queue_name,
16
+ COUNT(*) AS executions_count,
17
+ AVG(duration) AS avg_duration,
18
+ MIN(duration) AS min_duration,
19
+ MAX(duration) AS max_duration
20
+ ").order(:queue_name)
17
21
  end
18
22
 
19
23
  def show
@@ -96,6 +96,33 @@ module GoodJob
96
96
  # @return [ActiveRecord::Relation]
97
97
  scope :only_scheduled, -> { where(arel_table['scheduled_at'].lteq(bind_value('scheduled_at', DateTime.current, ActiveRecord::Type::DateTime))).or(where(scheduled_at: nil)) }
98
98
 
99
+ # Exclude jobs that are paused via queue_name or job_class.
100
+ # Only applies when enable_pauses configuration is true.
101
+ # @!method exclude_paused
102
+ # @!scope class
103
+ # @return [ActiveRecord::Relation]
104
+ scope :exclude_paused, lambda {
105
+ return all unless GoodJob.configuration.enable_pauses
106
+
107
+ paused_query = GoodJob::Setting.where(key: GoodJob::Setting::PAUSES)
108
+ paused_queues_query = paused_query.select("jsonb_array_elements_text(value->'queues')")
109
+ paused_job_classes_query = paused_query.select("jsonb_array_elements_text(value->'job_classes')")
110
+ paused_labels_query = paused_query.select("jsonb_array_elements_text(value->'labels')")
111
+
112
+ where.not(queue_name: paused_queues_query)
113
+ .where.not(job_class: paused_job_classes_query)
114
+ .where(
115
+ Arel::Nodes::Not.new(
116
+ Arel::Nodes::NamedFunction.new(
117
+ "COALESCE", [
118
+ Arel::Nodes::InfixOperation.new('&&', arel_table['labels'], Arel::Nodes::NamedFunction.new('ARRAY', [paused_labels_query.arel])),
119
+ Arel::Nodes::SqlLiteral.new('FALSE'),
120
+ ]
121
+ )
122
+ )
123
+ )
124
+ }
125
+
99
126
  # Order jobs by priority (highest priority first).
100
127
  # @!method priority_ordered
101
128
  # @!scope class
@@ -290,7 +317,7 @@ module GoodJob
290
317
  job = nil
291
318
  result = nil
292
319
 
293
- unfinished.dequeueing_ordered(parsed_queues).only_scheduled.limit(1).with_advisory_lock(select_limit: queue_select_limit) do |jobs|
320
+ unfinished.dequeueing_ordered(parsed_queues).only_scheduled.exclude_paused.limit(1).with_advisory_lock(select_limit: queue_select_limit) do |jobs|
294
321
  job = jobs.first
295
322
 
296
323
  if job&.executable?
@@ -4,6 +4,7 @@ module GoodJob
4
4
  class Setting < BaseRecord
5
5
  CRON_KEYS_ENABLED = "cron_keys_enabled"
6
6
  CRON_KEYS_DISABLED = "cron_keys_disabled"
7
+ PAUSES = "pauses"
7
8
 
8
9
  self.table_name = 'good_job_settings'
9
10
  self.implicit_order_column = 'created_at'
@@ -47,5 +48,82 @@ module GoodJob
47
48
  disabled_setting.value << key unless disabled_setting.value.include?(key_string)
48
49
  disabled_setting.save!
49
50
  end
51
+
52
+ def self.pause(queue: nil, job_class: nil, label: nil)
53
+ raise ArgumentError, "Must provide exactly one of queue, job_class, or label" unless [queue, job_class, label].count(&:present?) == 1
54
+
55
+ setting = find_or_initialize_by(key: PAUSES) do |record|
56
+ record.value = { "queues" => [], "job_classes" => [], "labels" => [] }
57
+ end
58
+
59
+ if queue
60
+ setting.value["queues"] ||= []
61
+ setting.value["queues"] << queue.to_s unless setting.value["queues"].include?(queue.to_s)
62
+ elsif job_class
63
+ setting.value["job_classes"] ||= []
64
+ setting.value["job_classes"] << job_class.to_s unless setting.value["job_classes"].include?(job_class.to_s)
65
+ else
66
+ setting.value["labels"] ||= []
67
+ setting.value["labels"] << label.to_s unless setting.value["labels"].include?(label.to_s)
68
+ end
69
+ setting.save!
70
+ end
71
+
72
+ def self.unpause(queue: nil, job_class: nil, label: nil)
73
+ raise ArgumentError, "Must provide exactly one of queue, job_class, or label" unless [queue, job_class, label].count(&:present?) == 1
74
+
75
+ setting = find_by(key: PAUSES)
76
+ return unless setting
77
+
78
+ if queue
79
+ return unless setting.value["queues"]&.include?(queue.to_s)
80
+
81
+ setting.value["queues"].delete(queue.to_s)
82
+ elsif job_class
83
+ return unless setting.value["job_classes"]&.include?(job_class.to_s)
84
+
85
+ setting.value["job_classes"].delete(job_class.to_s)
86
+ else
87
+ return unless setting.value["labels"]&.include?(label.to_s)
88
+
89
+ setting.value["labels"].delete(label.to_s)
90
+ end
91
+ setting.save!
92
+ end
93
+
94
+ def self.paused?(queue: nil, job_class: nil, label: nil)
95
+ raise ArgumentError, "Must provide at most one of queue, job_class, or label" if [queue, job_class, label].count(&:present?) > 1
96
+
97
+ if queue
98
+ queue.in? paused(:queues)
99
+ elsif job_class
100
+ job_class.in? paused(:job_classes)
101
+ elsif label
102
+ label.in? paused(:labels)
103
+ else
104
+ paused.values.any?(&:any?)
105
+ end
106
+ end
107
+
108
+ def self.paused(type = nil)
109
+ setting = find_by(key: PAUSES)
110
+ pauses = setting&.value&.deep_dup || { "queues" => [], "job_classes" => [], "labels" => [] }
111
+ pauses = pauses.with_indifferent_access
112
+
113
+ case type
114
+ when :queues
115
+ pauses["queues"]
116
+ when :job_classes
117
+ pauses["job_classes"]
118
+ when :labels
119
+ pauses["labels"]
120
+ else
121
+ {
122
+ queues: pauses["queues"] || [],
123
+ job_classes: pauses["job_classes"] || [],
124
+ labels: pauses["labels"] || [],
125
+ }
126
+ end
127
+ end
50
128
  end
51
129
  end
@@ -0,0 +1,28 @@
1
+ <% group = type.to_s.pluralize.to_sym %>
2
+ <% items = paused.fetch(group) { [] } %>
3
+ <% if items&.any? %>
4
+ <div class="my-3 card">
5
+ <div class="list-group list-group-flush text-nowrap" role="table">
6
+ <header class="list-group-item bg-body-tertiary">
7
+ <div class="row small text-muted text-uppercase align-items-center">
8
+ <div class="col-12"><%= t("good_job.pauses.index.#{type}") %></div>
9
+ </div>
10
+ </header>
11
+
12
+ <% items.each do |value| %>
13
+ <li class="list-group-item d-flex justify-content-between align-items-center">
14
+ <%= value %>
15
+ <%= button_to(
16
+ { action: :destroy, type: type, value: value },
17
+ method: :delete,
18
+ class: 'btn btn-sm btn-outline-primary',
19
+ data: { confirm: t('good_job.pauses.index.confirm_unpause', value: value) }
20
+ ) do %>
21
+ <%= render_icon "play" %>
22
+ <%= t("good_job.pauses.index.unpause") %>
23
+ <% end %>
24
+ </li>
25
+ <% end %>
26
+ </div>
27
+ </div>
28
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <li class="list-group-item d-flex justify-content-between align-items-center">
2
+ <%= value %>
3
+ <%= button_to t('good_job.pauses.index.unpause'),
4
+ { action: :destroy, type: type, value: value },
5
+ method: :delete,
6
+ class: 'btn btn-sm btn-outline-primary',
7
+ data: { confirm: t('good_job.pauses.index.confirm_unpause', value: value) } %>
8
+ </li>
@@ -0,0 +1,46 @@
1
+ <%= content_for :page_title do %>
2
+ <%= t('good_job.pauses.index.title') %>
3
+ <% end %>
4
+
5
+ <div class="border-bottom">
6
+ <h1 class="h2 pt-3 pb-2"><%= t('good_job.pauses.index.title') %></h1>
7
+ </div>
8
+
9
+ <% if GoodJob.configuration.enable_pauses %>
10
+ <div class="card mb-4">
11
+ <div class="card-body">
12
+ <%= form_tag({ action: :create }, method: :post, class: 'row g-3 align-items-end') do %>
13
+ <div class="col-3">
14
+ <%= label_tag :type, t('good_job.pauses.index.type'), class: 'form-label' %>
15
+ <%= select_tag :type,
16
+ options_for_select([
17
+ [t('good_job.pauses.index.queue'), 'queue'],
18
+ [t('good_job.pauses.index.job_class'), 'job_class'],
19
+ [t('good_job.pauses.index.label'), 'label'],
20
+ ]),
21
+ class: 'form-select',
22
+ required: true %>
23
+ </div>
24
+ <div class="col-6">
25
+ <%= label_tag :value, t('good_job.pauses.index.value'), class: 'form-label' %>
26
+ <%= text_field_tag :value, nil, class: 'form-control', autocomplete: "off", required: true %>
27
+ </div>
28
+ <div class="col-3">
29
+ <%= button_tag type: "submit", class: 'btn btn-primary' do %>
30
+ <%= render_icon "pause" %>
31
+ <%= t('good_job.pauses.index.pause', value: '') %>
32
+ <% end %>
33
+ </div>
34
+ <% end %>
35
+ </div>
36
+ </div>
37
+
38
+ <%= render 'group', paused: @paused, type: :queue %>
39
+ <%= render 'group', paused: @paused, type: :job_class %>
40
+ <%= render 'group', paused: @paused, type: :label %>
41
+ <% else %>
42
+ <div class="alert alert-warning" role="alert">
43
+ <p><%= t('good_job.pauses.index.disabled') %>:</p>
44
+ <pre class="mb-0">config.good_job.enable_pauses = true</pre>
45
+ </div>
46
+ <% end %>
@@ -10,7 +10,6 @@
10
10
  <div class="row small text-muted text-uppercase align-items-center">
11
11
  <div class="col-12 col-lg-4"><%= t ".job_class" %></div>
12
12
  <div class="col-lg-2 d-none d-lg-block"><%= t ".executions" %></div>
13
-
14
13
  <div class="col-lg-2 d-none d-lg-block"><%= t ".average_duration" %></div>
15
14
  <div class="col-lg-2 d-none d-lg-block"><%= t ".minimum_duration" %></div>
16
15
  <div class="col-lg-2 d-none d-lg-block"><%= t ".maximum_duration" %></div>
@@ -20,12 +19,57 @@
20
19
  <% @performances.each do |performance| %>
21
20
  <div role="row" class="list-group-item py-3">
22
21
  <div class="row align-items-center">
23
- <div class="col-12 col-lg-4"><%= link_to performance.job_class, performance_path(performance.job_class) %></div>
22
+ <div class="col-12 col-lg-4">
23
+ <div class="d-flex gap-3 justify-content-between">
24
+ <%= link_to performance.job_class, performance_path(performance.job_class) %>
25
+ </div>
26
+ </div>
24
27
  <div class="col-6 col-lg-2 text-wrap">
25
28
  <div class="d-lg-none small text-muted mt-1"><%= t ".executions" %></div>
26
29
  <%= performance.executions_count %>
27
30
  </div>
31
+ <div class="col-6 col-lg-2 text-wrap">
32
+ <div class="d-lg-none small text-muted mt-1"><%= t ".average_duration" %></div>
33
+ <%= format_duration performance.avg_duration %>
34
+ </div>
35
+ <div class="col-6 col-lg-2 text-wrap">
36
+ <div class="d-lg-none small text-muted mt-1"><%= t ".minimum_duration" %></div>
37
+ <%= format_duration performance.min_duration %>
38
+ </div>
39
+ <div class="col-6 col-lg-2 text-wrap">
40
+ <div class="d-lg-none small text-muted mt-1"><%= t ".maximum_duration" %></div>
41
+ <%= format_duration performance.max_duration %>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ <% end %>
46
+ </div>
47
+ </div>
28
48
 
49
+ <div class="my-3 card">
50
+ <div class="list-group list-group-flush text-nowrap" role="table">
51
+ <header class="list-group-item bg-body-tertiary">
52
+ <div class="row small text-muted text-uppercase align-items-center">
53
+ <div class="col-12 col-lg-4"><%= t ".queue_name" %></div>
54
+ <div class="col-lg-2 d-none d-lg-block"><%= t ".executions" %></div>
55
+ <div class="col-lg-2 d-none d-lg-block"><%= t ".average_duration" %></div>
56
+ <div class="col-lg-2 d-none d-lg-block"><%= t ".minimum_duration" %></div>
57
+ <div class="col-lg-2 d-none d-lg-block"><%= t ".maximum_duration" %></div>
58
+ </div>
59
+ </header>
60
+
61
+ <% @queue_performances.each do |performance| %>
62
+ <div role="row" class="list-group-item py-3">
63
+ <div class="row align-items-center">
64
+ <div class="col-12 col-lg-4">
65
+ <div class="d-flex gap-3 justify-content-between">
66
+ <%= performance.queue_name %>
67
+ </div>
68
+ </div>
69
+ <div class="col-6 col-lg-2 text-wrap">
70
+ <div class="d-lg-none small text-muted mt-1"><%= t ".executions" %></div>
71
+ <%= performance.executions_count %>
72
+ </div>
29
73
  <div class="col-6 col-lg-2 text-wrap">
30
74
  <div class="d-lg-none small text-muted mt-1"><%= t ".average_duration" %></div>
31
75
  <%= format_duration performance.avg_duration %>
@@ -44,6 +44,12 @@
44
44
  <%= t(".performance") %>
45
45
  <% end %>
46
46
  </li>
47
+ <li class="nav-item">
48
+ <%= link_to pauses_path, class: ["nav-link", ("active" if controller_name == 'pauses')] do %>
49
+ <%= t(".pauses") %>
50
+ <span data-async-values-target="value" data-async-values-key="pauses_count" data-async-values-zero-class="d-none" class="badge bg-warning rounded-pill d-none"></span>
51
+ <% end %>
52
+ </li>
47
53
  <li class="nav-item">
48
54
  <%= link_to cleaner_index_path, class: ["nav-link", ("active" if controller_name == 'cleaner')] do %>
49
55
  <%= t(".cleaner") %>
@@ -214,14 +214,28 @@ de:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Sind Sie sicher, dass Sie %{value} pausieren möchten?
220
+ confirm_unpause: Sind Sie sicher, dass Sie %{value} fortsetzen möchten?
221
+ disabled: Die experimentelle Pausenfunktion von GoodJob ist standardmäßig deaktiviert, da sie die Leistung beeinträchtigen kann. Konfigurieren Sie sie zur Aktivierung
222
+ job_class: Job-Klasse
223
+ label: Label
224
+ pause: Pausieren
225
+ queue: Warteschlange
226
+ title: Pausen
227
+ type: Pausentyp
228
+ unpause: Fortsetzen
229
+ value: Wert
217
230
  performance:
218
231
  index:
219
232
  average_duration: Durchschnittliche Dauer
220
- chart_title: Gesamtdauer der Jobs in Sekunden
233
+ chart_title: Gesamtausführungszeit in Sekunden
221
234
  executions: Ausführungen
222
235
  job_class: Job-Klasse
223
236
  maximum_duration: Maximale Dauer
224
- minimum_duration: Mindestdauer
237
+ minimum_duration: Minimale Dauer
238
+ queue_name: Warteschlangenname
225
239
  title: Leistung
226
240
  show:
227
241
  slow: Langsam
@@ -256,6 +270,7 @@ de:
256
270
  jobs: Jobs
257
271
  live_poll: Live Poll
258
272
  name: "GoodJob 👍"
273
+ pauses: Pausen
259
274
  performance: Leistung
260
275
  processes: Prozesse
261
276
  theme:
@@ -127,7 +127,7 @@ en:
127
127
  jobs:
128
128
  actions:
129
129
  confirm_destroy: Are you sure you want to destroy the job?
130
- confirm_discard: Are you usure you want to discard the job?
130
+ confirm_discard: Are you sure you want to discard the job?
131
131
  confirm_force_discard: Are you sure you want to force discard this job? The job will be marked as discarded but the running job will not be stopped - it will, however, not be retried on failures.
132
132
  confirm_reschedule: Are you sure you want to reschedule the job?
133
133
  confirm_retry: Are you sure you want to retry the job?
@@ -163,7 +163,7 @@ en:
163
163
  one: Apply to all 1 job.
164
164
  other: Apply to all %{count} jobs.
165
165
  confirm_destroy_all: Are you sure you want to destroy the selected jobs?
166
- confirm_discard_all: Are you usure you want to discard the selected jobs?
166
+ confirm_discard_all: Are you sure you want to discard the selected jobs?
167
167
  confirm_reschedule_all: Are you sure you want to reschedule the selected jobs?
168
168
  confirm_retry_all: Are you sure you want to retry the selected jobs?
169
169
  destroy_all: Destroy all
@@ -214,6 +214,19 @@ en:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Are you sure you want to pause %{value}?
220
+ confirm_unpause: Are you sure you want to resume %{value}?
221
+ disabled: GoodJob's experimental Pauses feature is disabled by default because it may degrade performance. Configure to enable
222
+ job_class: Job Class
223
+ label: Label
224
+ pause: Pause
225
+ queue: Queue
226
+ title: Pauses
227
+ type: Pause Type
228
+ unpause: Resume
229
+ value: Value
217
230
  performance:
218
231
  index:
219
232
  average_duration: Average duration
@@ -222,6 +235,7 @@ en:
222
235
  job_class: Job class
223
236
  maximum_duration: Maximum duration
224
237
  minimum_duration: Minimum duration
238
+ queue_name: Queue name
225
239
  title: Performance
226
240
  show:
227
241
  slow: Slow
@@ -256,6 +270,7 @@ en:
256
270
  jobs: Jobs
257
271
  live_poll: Live Poll
258
272
  name: "GoodJob 👍"
273
+ pauses: Pauses
259
274
  performance: Performance
260
275
  processes: Processes
261
276
  theme:
@@ -214,18 +214,32 @@ es:
214
214
  thousand: k
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: "¿Está seguro de que desea pausar %{value}?"
220
+ confirm_unpause: "¿Está seguro de que desea reanudar %{value}?"
221
+ disabled: La función experimental de Pausas de GoodJob está desactivada por defecto porque puede degradar el rendimiento. Configure para habilitar
222
+ job_class: Clase de trabajo
223
+ label: Etiqueta
224
+ pause: Pausar
225
+ queue: Cola
226
+ title: Pausas
227
+ type: Tipo de Pausa
228
+ unpause: Reanudar
229
+ value: Valor
217
230
  performance:
218
231
  index:
219
232
  average_duration: Duración promedio
220
- chart_title: Tiempo total de ejecución de la tarea en segundos
233
+ chart_title: Tiempo total de ejecución del trabajo en segundos
221
234
  executions: Ejecuciones
222
- job_class: clase de tarea
235
+ job_class: Clase de trabajo
223
236
  maximum_duration: Duración máxima
224
237
  minimum_duration: Duración mínima
238
+ queue_name: Nombre de la cola
225
239
  title: Rendimiento
226
240
  show:
227
241
  slow: Lento
228
- title: Actuación
242
+ title: Rendimiento
229
243
  processes:
230
244
  index:
231
245
  cron_enabled: Cron habilitado
@@ -256,6 +270,7 @@ es:
256
270
  jobs: Tareas
257
271
  live_poll: En vivo
258
272
  name: "GoodJob 👍"
273
+ pauses: Pausas
259
274
  performance: Rendimiento
260
275
  processes: Procesos
261
276
  theme:
@@ -10,17 +10,17 @@ fr:
10
10
  retry: Recommencez
11
11
  batches:
12
12
  actions:
13
- confirm_retry: Voulez-vous vraiment réessayer ce lot ?
13
+ confirm_retry: Voulez-vous vraiment réessayer ce lot ?
14
14
  retry: Réessayer
15
15
  index:
16
16
  older_batches: Lots plus anciens
17
17
  title: Lots
18
18
  jobs:
19
19
  actions:
20
- confirm_destroy: Voulez-vous vraiment détruire ce job ?
21
- confirm_discard: Voulez-vous vraiment mettre au rebut ce job ?
22
- confirm_reschedule: Voulez-vous vraiment replanifier ce job ?
23
- confirm_retry: Voulez-vous vraiment réessayer ce job ?
20
+ confirm_destroy: Voulez-vous vraiment détruire ce job ?
21
+ confirm_discard: Voulez-vous vraiment mettre au rebut ce job ?
22
+ confirm_reschedule: Voulez-vous vraiment replanifier ce job ?
23
+ confirm_retry: Voulez-vous vraiment réessayer ce job ?
24
24
  destroy: Détruire le job
25
25
  discard: Mettre au rebut le job
26
26
  reschedule: Replanifier le job
@@ -51,9 +51,9 @@ fr:
51
51
  total: Total
52
52
  cron_entries:
53
53
  actions:
54
- confirm_disable: Voulez-vous vraiment désactiver cette entrée cron ?
55
- confirm_enable: Voulez-vous vraiment activer cette entrée cron ?
56
- confirm_enqueue: Voulez-vous vraiment mettre en file d'attente cette entrée cron ?
54
+ confirm_disable: Voulez-vous vraiment désactiver cette entrée cron ?
55
+ confirm_enable: Voulez-vous vraiment activer cette entrée cron ?
56
+ confirm_enqueue: Voulez-vous vraiment mettre en file d'attente cette entrée cron ?
57
57
  disable: Désactiver l'entrée cron
58
58
  enable: Activer l'entrée cron
59
59
  enqueue: Mettre en file d'attente l'entrée cron maintenant
@@ -126,11 +126,11 @@ fr:
126
126
  past: il y a %{time}
127
127
  jobs:
128
128
  actions:
129
- confirm_destroy: Voulez-vous vraiment détruire le job ?
130
- confirm_discard: Voulez-vous vraiment mettre au rebut le job ?
129
+ confirm_destroy: Voulez-vous vraiment détruire le job ?
130
+ confirm_discard: Voulez-vous vraiment mettre au rebut le job ?
131
131
  confirm_force_discard: Êtes-vous sûr de vouloir forcer l'abandon du travail? Le travail sera marqué comme abandonné mais le travail en cours ne sera pas arrêté - cependant, il ne sera pas réessayé en cas d'échec.
132
- confirm_reschedule: Voulez-vous vraiment replanifier le job ?
133
- confirm_retry: Voulez-vous vraiment réessayer le job ?
132
+ confirm_reschedule: Voulez-vous vraiment replanifier le job ?
133
+ confirm_retry: Voulez-vous vraiment réessayer le job ?
134
134
  destroy: Détruire le job
135
135
  discard: Mettre au rebut le job
136
136
  force_discard: Forcer l'abandon du travail
@@ -162,10 +162,10 @@ fr:
162
162
  apply_to_all:
163
163
  one: Appliquer à ce job
164
164
  other: Appliquer aux %{count} jobs
165
- confirm_destroy_all: Voulez-vous vraiment détruire les jobs sélectionnés ?
166
- confirm_discard_all: Voulez-vous vraiment mettre au rebut les jobs sélectionnés ?
167
- confirm_reschedule_all: Voulez-vous vraiment replanifier les jobs sélectionnées ?
168
- confirm_retry_all: Voulez-vous vraiment réessayer les jobs sélectionnées ?
165
+ confirm_destroy_all: Voulez-vous vraiment détruire les jobs sélectionnés ?
166
+ confirm_discard_all: Voulez-vous vraiment mettre au rebut les jobs sélectionnés ?
167
+ confirm_reschedule_all: Voulez-vous vraiment replanifier les jobs sélectionnées ?
168
+ confirm_retry_all: Voulez-vous vraiment réessayer les jobs sélectionnées ?
169
169
  destroy_all: Tout détruire
170
170
  discard_all: Tout mettre au rebut
171
171
  reschedule_all: Tout replanifier
@@ -214,17 +214,31 @@ fr:
214
214
  thousand: k
215
215
  trillion: J
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Êtes-vous sûr de vouloir mettre en pause %{value} ?
220
+ confirm_unpause: Êtes-vous sûr de vouloir reprendre %{value} ?
221
+ disabled: La fonction expérimentale de Pauses de GoodJob est désactivée par défaut car elle peut dégrader les performances. Configurez pour activer
222
+ job_class: Classe de tâche
223
+ label: Étiquette
224
+ pause: Pause
225
+ queue: File d'attente
226
+ title: Pauses
227
+ type: Type de Pause
228
+ unpause: Reprendre
229
+ value: Valeur
217
230
  performance:
218
231
  index:
219
232
  average_duration: Durée moyenne
220
- chart_title: Durée totale d'exécution du travail en secondes
233
+ chart_title: Temps total d'exécution des tâches en secondes
221
234
  executions: Exécutions
222
- job_class: Catégorie d'emplois
235
+ job_class: Classe de tâche
223
236
  maximum_duration: Durée maximale
224
237
  minimum_duration: Durée minimale
238
+ queue_name: Nom de la file
225
239
  title: Performance
226
240
  show:
227
- slow: Lenteur
241
+ slow: Lent
228
242
  title: Performance
229
243
  processes:
230
244
  index:
@@ -256,6 +270,7 @@ fr:
256
270
  jobs: Jobs
257
271
  live_poll: En direct
258
272
  name: "GoodJob 👍"
273
+ pauses: Pauses
259
274
  performance: Performance
260
275
  processes: Processus
261
276
  theme:
@@ -265,7 +280,7 @@ fr:
265
280
  theme: Thème
266
281
  pending_migrations: GoodJob a des migrations de bases de données en attente.
267
282
  secondary_navbar:
268
- inspiration: N'oublie pas, toi aussi tu fais du bon boulot !
283
+ inspiration: N'oublie pas, toi aussi tu fais du bon boulot !
269
284
  last_updated: Dernière mise à jour
270
285
  status:
271
286
  discarded: Mis au rebut
@@ -214,18 +214,32 @@ it:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Sei sicuro di voler mettere in pausa %{value}?
220
+ confirm_unpause: Sei sicuro di voler riprendere %{value}?
221
+ disabled: La funzione sperimentale Pause di GoodJob è disabilitata per impostazione predefinita perché potrebbe degradare le prestazioni. Configurare per abilitare
222
+ job_class: Classe del job
223
+ label: Etichetta
224
+ pause: Pausa
225
+ queue: Coda
226
+ title: Pause
227
+ type: Tipo di Pausa
228
+ unpause: Riprendi
229
+ value: Valore
217
230
  performance:
218
231
  index:
219
232
  average_duration: Durata media
220
- chart_title: Tempo totale di esecuzione del lavoro in secondi
233
+ chart_title: Tempo totale di esecuzione in secondi
221
234
  executions: Esecuzioni
222
- job_class: Classe di lavoro
235
+ job_class: Classe del job
223
236
  maximum_duration: Durata massima
224
237
  minimum_duration: Durata minima
225
- title: Prestazione
238
+ queue_name: Nome della coda
239
+ title: Prestazioni
226
240
  show:
227
241
  slow: Lento
228
- title: Prestazione
242
+ title: Prestazioni
229
243
  processes:
230
244
  index:
231
245
  cron_enabled: Cron abilitato
@@ -256,6 +270,7 @@ it:
256
270
  jobs: Job
257
271
  live_poll: Live Poll
258
272
  name: "GoodJob 👍"
273
+ pauses: Pause
259
274
  performance: Prestazione
260
275
  processes: Processi
261
276
  theme:
@@ -214,14 +214,28 @@ ja:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: "%{value}を一時停止してもよろしいですか?"
220
+ confirm_unpause: "%{value}を再開してもよろしいですか?"
221
+ disabled: GoodJobの実験的な一時停止機能は、パフォーマンスが低下する可能性があるため、デフォルトでは無効になっています。有効にするには設定してください
222
+ job_class: ジョブクラス
223
+ label: ラベル
224
+ pause: 一時停止
225
+ queue: キュー
226
+ title: 一時停止
227
+ type: 一時停止タイプ
228
+ unpause: 再開
229
+ value: 値
217
230
  performance:
218
231
  index:
219
232
  average_duration: 平均所要時間
220
- chart_title: ジョブの総実行時間(秒
221
- executions: 実行
233
+ chart_title: 合計実行時間(秒)
234
+ executions: 実行回数
222
235
  job_class: ジョブクラス
223
- maximum_duration: 最大持続時間
224
- minimum_duration: 最小期間
236
+ maximum_duration: 最大所要時間
237
+ minimum_duration: 最小所要時間
238
+ queue_name: キュー名
225
239
  title: パフォーマンス
226
240
  show:
227
241
  slow: 遅い
@@ -256,6 +270,7 @@ ja:
256
270
  jobs: ジョブ
257
271
  live_poll: リアルタイム更新
258
272
  name: "GoodJob 👍"
273
+ pauses: 一時停止
259
274
  performance: パフォーマンス
260
275
  processes: プロセス
261
276
  theme:
@@ -214,14 +214,28 @@ ko:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: "%{value}를 일시 중지하시겠습니까?"
220
+ confirm_unpause: "%{value}를 재개하시겠습니까?"
221
+ disabled: GoodJob의 실험적인 일시 중지 기능은 성능이 저하될 수 있으므로 기본적으로 비활성화되어 있습니다. 활성화하려면 구성하세요
222
+ job_class: 작업 클래스
223
+ label: 라벨
224
+ pause: 일시 중지
225
+ queue: 대기열
226
+ title: 일시 중지
227
+ type: 중지 유형
228
+ unpause: 재개
229
+ value: 값
217
230
  performance:
218
231
  index:
219
- average_duration: 평균 지속 시간
220
- chart_title: 총 작업 실행 시간(초)
221
- executions: 실행
232
+ average_duration: 평균 소요 시간
233
+ chart_title: 총 실행 시간(초)
234
+ executions: 실행 횟수
222
235
  job_class: 작업 클래스
223
- maximum_duration: 최대 기간
224
- minimum_duration: 최소 기간
236
+ maximum_duration: 최대 소요 시간
237
+ minimum_duration: 최소 소요 시간
238
+ queue_name: 큐 이름
225
239
  title: 성능
226
240
  show:
227
241
  slow: 느림
@@ -256,6 +270,7 @@ ko:
256
270
  jobs: 작업
257
271
  live_poll: 실시간 업데이트
258
272
  name: "GoodJob 👍"
273
+ pauses: 일시 중지
259
274
  performance: 성능
260
275
  processes: 프로세스
261
276
  theme:
@@ -214,18 +214,32 @@ nl:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Weet u zeker dat u %{value} wilt pauzeren?
220
+ confirm_unpause: Weet u zeker dat u %{value} wilt hervatten?
221
+ disabled: De experimentele Pauzes-functie van GoodJob is standaard uitgeschakeld omdat het de prestaties kan verminderen. Configureer om in te schakelen
222
+ job_class: Taakklasse
223
+ label: Label
224
+ pause: Pauzeren
225
+ queue: Wachtrij
226
+ title: Pauzes
227
+ type: Pauze Type
228
+ unpause: Hervatten
229
+ value: Waarde
217
230
  performance:
218
231
  index:
219
232
  average_duration: Gemiddelde duur
220
- chart_title: Totale uitvoeringstijd van de taak in seconden
221
- executions: Executies
222
- job_class: Functie klasse
233
+ chart_title: Totale uitvoeringstijd in seconden
234
+ executions: Uitvoeringen
235
+ job_class: Taakklasse
223
236
  maximum_duration: Maximale duur
224
237
  minimum_duration: Minimale duur
225
- title: Prestatie
238
+ queue_name: Wachtrijnaam
239
+ title: Prestaties
226
240
  show:
227
- slow: Langzaam
228
- title: Prestatie
241
+ slow: Traag
242
+ title: Prestaties
229
243
  processes:
230
244
  index:
231
245
  cron_enabled: Cron ingeschakeld
@@ -256,6 +270,7 @@ nl:
256
270
  jobs: Taken
257
271
  live_poll: Live Poll
258
272
  name: "GoodJob 👍"
273
+ pauses: Pauzes
259
274
  performance: Prestatie
260
275
  processes: Processen
261
276
  theme:
@@ -214,14 +214,28 @@ pt-BR:
214
214
  thousand: K
215
215
  trillion: T
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: Tem certeza que deseja pausar %{value}?
220
+ confirm_unpause: Tem certeza que deseja retomar %{value}?
221
+ disabled: O recurso experimental de Pausas do GoodJob está desativado por padrão porque pode degradar o desempenho. Configure para ativar
222
+ job_class: Classe do trabalho
223
+ label: Rótulo
224
+ pause: Pausar
225
+ queue: Fila
226
+ title: Pausas
227
+ type: Tipo de Pausa
228
+ unpause: Retomar
229
+ value: Valor
217
230
  performance:
218
231
  index:
219
232
  average_duration: Duração média
220
- chart_title: Tempo total de execução do trabalho em segundos
233
+ chart_title: Tempo total de execução em segundos
221
234
  executions: Execuções
222
- job_class: Classe de trabalho
235
+ job_class: Classe do trabalho
223
236
  maximum_duration: Duração máxima
224
237
  minimum_duration: Duração mínima
238
+ queue_name: Nome da fila
225
239
  title: Desempenho
226
240
  show:
227
241
  slow: Lento
@@ -256,6 +270,7 @@ pt-BR:
256
270
  jobs: Tarefas
257
271
  live_poll: Acompanhamento ao Vivo
258
272
  name: "GoodJob 👍"
273
+ pauses: Pausas
259
274
  performance: Desempenho
260
275
  processes: Processos
261
276
  theme:
@@ -240,17 +240,31 @@ ru:
240
240
  thousand: К
241
241
  trillion: Т
242
242
  unit: ''
243
+ pauses:
244
+ index:
245
+ confirm_pause: Вы уверены, что хотите приостановить %{value}?
246
+ confirm_unpause: Вы уверены, что хотите возобновить %{value}?
247
+ disabled: Экспериментальная функция Паузы в GoodJob отключена по умолчанию, так как это может снизить производительность. Настройте для включения
248
+ job_class: Класс задачи
249
+ label: Метка
250
+ pause: Приостановить
251
+ queue: Очередь
252
+ title: Паузы
253
+ type: Тип Паузы
254
+ unpause: Возобновить
255
+ value: Значение
243
256
  performance:
244
257
  index:
245
258
  average_duration: Средняя продолжительность
246
- chart_title: Общее время выполнения задания в секундах
247
- executions: Казни
248
- job_class: Класс работы
259
+ chart_title: Общее время выполнения в секундах
260
+ executions: Выполнения
261
+ job_class: Класс задачи
249
262
  maximum_duration: Максимальная продолжительность
250
263
  minimum_duration: Минимальная продолжительность
264
+ queue_name: Название очереди
251
265
  title: Производительность
252
266
  show:
253
- slow: Медленный
267
+ slow: Медленно
254
268
  title: Производительность
255
269
  processes:
256
270
  index:
@@ -276,12 +290,13 @@ ru:
276
290
  queue_name: Название очереди
277
291
  search: Поиск
278
292
  navbar:
279
- batches: Пакетные задания
293
+ batches: Пакеты
280
294
  cleaner: Discard Cleaner
281
295
  cron_schedules: Cron
282
296
  jobs: Задания
283
- live_poll: Обновления в реальном времени
297
+ live_poll: Живой опрос
284
298
  name: "GoodJob 👍"
299
+ pauses: Паузы
285
300
  performance: Производительность
286
301
  processes: Процессы
287
302
  theme:
@@ -214,18 +214,32 @@ tr:
214
214
  thousand: Bin
215
215
  trillion: Trilyon
216
216
  unit: ''
217
+ pauses:
218
+ index:
219
+ confirm_pause: "%{value} duraklatmak istediğinizden emin misiniz?"
220
+ confirm_unpause: "%{value} devam ettirmek istediğinizden emin misiniz?"
221
+ disabled: GoodJob'ın deneysel Duraklatma özelliği, performansı düşürebileceği için varsayılan olarak devre dışıdır. Etkinleştirmek için yapılandırın
222
+ job_class: İş sınıfı
223
+ label: Etiket
224
+ pause: Duraklat
225
+ queue: Kuyruk
226
+ title: Duraklatmalar
227
+ type: Duraklatma Türü
228
+ unpause: Devam Et
229
+ value: Değer
217
230
  performance:
218
231
  index:
219
232
  average_duration: Ortalama süre
220
- chart_title: Saniye cinsinden toplam iş yürütme süresi
221
- executions: İnfazlar
233
+ chart_title: Toplam yürütme süresi (saniye)
234
+ executions: Yürütmeler
222
235
  job_class: İş sınıfı
223
236
  maximum_duration: Maksimum süre
224
237
  minimum_duration: Minimum süre
225
- title: Verim
238
+ queue_name: Kuyruk adı
239
+ title: Performans
226
240
  show:
227
241
  slow: Yavaş
228
- title: Verim
242
+ title: Performans
229
243
  processes:
230
244
  index:
231
245
  cron_enabled: Cron etkin
@@ -256,6 +270,7 @@ tr:
256
270
  jobs: İşler
257
271
  live_poll: Anlık Güncelleme
258
272
  name: "GoodJob 👍"
273
+ pauses: Duraklatmalar
259
274
  performance: Verim
260
275
  processes: Süreçler
261
276
  theme:
@@ -240,14 +240,28 @@ uk:
240
240
  thousand: Тис
241
241
  trillion: Трлн
242
242
  unit: ''
243
+ pauses:
244
+ index:
245
+ confirm_pause: Ви впевнені, що хочете призупинити %{value}?
246
+ confirm_unpause: Ви впевнені, що хочете відновити %{value}?
247
+ disabled: Експериментальна функція Паузи в GoodJob вимкнена за замовчуванням, оскільки це може знизити продуктивність. Налаштуйте для увімкнення
248
+ job_class: Клас завдання
249
+ label: Мітка
250
+ pause: Призупинити
251
+ queue: Черга
252
+ title: Паузи
253
+ type: Тип Паузи
254
+ unpause: Відновити
255
+ value: Значення
243
256
  performance:
244
257
  index:
245
258
  average_duration: Середня тривалість
246
- chart_title: Загальний час виконання завдання в секундах
247
- executions: Страти
248
- job_class: Клас роботи
259
+ chart_title: Загальний час виконання в секундах
260
+ executions: Виконання
261
+ job_class: Клас завдання
249
262
  maximum_duration: Максимальна тривалість
250
263
  minimum_duration: Мінімальна тривалість
264
+ queue_name: Назва черги
251
265
  title: Продуктивність
252
266
  show:
253
267
  slow: Повільно
@@ -279,9 +293,10 @@ uk:
279
293
  batches: Пакети
280
294
  cleaner: Discard Cleaner
281
295
  cron_schedules: Cron
282
- jobs: Задачі
283
- live_poll: Живе Опитування
296
+ jobs: Роботи
297
+ live_poll: Живе опитування
284
298
  name: "GoodJob 👍"
299
+ pauses: Паузи
285
300
  performance: Продуктивність
286
301
  processes: Процеси
287
302
  theme:
data/config/routes.rb CHANGED
@@ -35,6 +35,12 @@ GoodJob::Engine.routes.draw do
35
35
 
36
36
  resources :processes, only: %i[index]
37
37
  resources :performance, only: %i[index show]
38
+ resources :pauses, only: %i[index] do
39
+ collection do
40
+ post :create
41
+ delete :destroy
42
+ end
43
+ end
38
44
  resources :cleaner, only: %i[index]
39
45
 
40
46
  scope :frontend, controller: :frontends, defaults: { version: GoodJob::VERSION.tr(".", "-") } do
@@ -35,6 +35,8 @@ module GoodJob
35
35
  DEFAULT_DASHBOARD_LIVE_POLL_ENABLED = true
36
36
  # Default enqueue_after_transaction_commit
37
37
  DEFAULT_ENQUEUE_AFTER_TRANSACTION_COMMIT = false
38
+ # Default enable_pauses setting
39
+ DEFAULT_ENABLE_PAUSES = false
38
40
 
39
41
  def self.validate_execution_mode(execution_mode)
40
42
  raise ArgumentError, "GoodJob execution mode must be one of #{EXECUTION_MODES.join(', ')}. It was '#{execution_mode}' which is not valid." unless execution_mode.in?(EXECUTION_MODES)
@@ -369,6 +371,16 @@ module GoodJob
369
371
  DEFAULT_ENQUEUE_AFTER_TRANSACTION_COMMIT
370
372
  end
371
373
 
374
+ # Whether the job processing can be paused.
375
+ # @return [Boolean]
376
+ def enable_pauses
377
+ return options[:enable_pauses] unless options[:enable_pauses].nil?
378
+ return rails_config[:enable_pauses] unless rails_config[:enable_pauses].nil?
379
+ return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_ENABLE_PAUSES']) unless env['GOOD_JOB_ENABLE_PAUSE'].nil?
380
+
381
+ DEFAULT_ENABLE_PAUSES
382
+ end
383
+
372
384
  # Whether running in a web server process.
373
385
  # @return [Boolean, nil]
374
386
  def in_webserver?
@@ -162,6 +162,8 @@ module GoodJob # :nodoc:
162
162
  if state[:scheduled_at]
163
163
  scheduled_at = if state[:scheduled_at].is_a? String
164
164
  Time.zone.parse state[:scheduled_at]
165
+ elsif state[:scheduled_at].is_a? Numeric
166
+ Time.zone.at state[:scheduled_at]
165
167
  else
166
168
  state[:scheduled_at]
167
169
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '4.7.0'
5
+ VERSION = '4.8.1'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
data/lib/good_job.rb CHANGED
@@ -292,6 +292,38 @@ module GoodJob
292
292
  def self.migrated?
293
293
  GoodJob::BatchRecord.jobs_finished_at_migrated?
294
294
  end
295
+
296
+ # Pause job execution for a given queue or job class.
297
+ # @param queue [String, nil] Queue name to pause
298
+ # @param job_class [String, nil] Job class name to pause
299
+ # @return [void]
300
+ def self.pause(queue: nil, job_class: nil)
301
+ GoodJob::Setting.pause(queue: queue, job_class: job_class)
302
+ end
303
+
304
+ # Unpause job execution for a given queue or job class.
305
+ # @param queue [String, nil] Queue name to unpause
306
+ # @param job_class [String, nil] Job class name to unpause
307
+ # @param label [String, nil] Label to unpause
308
+ # @return [void]
309
+ def self.unpause(queue: nil, job_class: nil, label: nil)
310
+ GoodJob::Setting.unpause(queue: queue, job_class: job_class, label: label)
311
+ end
312
+
313
+ # Check if job execution is paused for a given queue or job class.
314
+ # @param queue [String, nil] Queue name to check
315
+ # @param job_class [String, nil] Job class name to check
316
+ # @param label [String, nil] Label to check
317
+ # @return [Boolean]
318
+ def self.paused?(queue: nil, job_class: nil, label: nil)
319
+ GoodJob::Setting.paused?(queue: queue, job_class: job_class, label: label)
320
+ end
321
+
322
+ # Get a list of all paused queues and job classes
323
+ # @return [Hash] Hash with :queues, :job_classes, :labels arrays of paused items
324
+ def self.paused(type = nil)
325
+ GoodJob::Setting.paused(type)
326
+ end
295
327
  end
296
328
 
297
329
  ActiveSupport.run_load_hooks(:good_job, GoodJob)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.0
4
+ version: 4.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-12-31 00:00:00.000000000 Z
10
+ date: 2025-01-24 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activejob
@@ -259,6 +258,7 @@ files:
259
258
  - app/controllers/good_job/frontends_controller.rb
260
259
  - app/controllers/good_job/jobs_controller.rb
261
260
  - app/controllers/good_job/metrics_controller.rb
261
+ - app/controllers/good_job/pauses_controller.rb
262
262
  - app/controllers/good_job/performance_controller.rb
263
263
  - app/controllers/good_job/processes_controller.rb
264
264
  - app/filters/good_job/base_filter.rb
@@ -313,6 +313,9 @@ files:
313
313
  - app/views/good_job/jobs/_table.erb
314
314
  - app/views/good_job/jobs/index.html.erb
315
315
  - app/views/good_job/jobs/show.html.erb
316
+ - app/views/good_job/pauses/_group.html.erb
317
+ - app/views/good_job/pauses/_pause.html.erb
318
+ - app/views/good_job/pauses/index.html.erb
316
319
  - app/views/good_job/performance/index.html.erb
317
320
  - app/views/good_job/performance/show.html.erb
318
321
  - app/views/good_job/processes/index.html.erb
@@ -396,7 +399,6 @@ metadata:
396
399
  homepage_uri: https://github.com/bensheldon/good_job
397
400
  source_code_uri: https://github.com/bensheldon/good_job
398
401
  rubygems_mfa_required: 'true'
399
- post_install_message:
400
402
  rdoc_options:
401
403
  - "--title"
402
404
  - GoodJob - a multithreaded, Postgres-based ActiveJob backend for Ruby on Rails
@@ -418,8 +420,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
418
420
  - !ruby/object:Gem::Version
419
421
  version: '0'
420
422
  requirements: []
421
- rubygems_version: 3.5.11
422
- signing_key:
423
+ rubygems_version: 3.6.2
423
424
  specification_version: 4
424
425
  summary: A multithreaded, Postgres-based ActiveJob backend for Ruby on Rails
425
426
  test_files: []