good_job 3.18.3 → 3.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/app/controllers/good_job/jobs_controller.rb +7 -0
- data/app/models/concerns/good_job/advisory_lockable.rb +49 -15
- data/app/models/good_job/base_record.rb +2 -2
- data/app/models/good_job/job.rb +36 -23
- data/app/views/good_job/jobs/_table.erb +7 -0
- data/app/views/good_job/shared/icons/_eject.html.erb +4 -0
- data/config/locales/de.yml +7 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/es.yml +5 -0
- data/config/locales/fr.yml +7 -0
- data/config/locales/ja.yml +7 -0
- data/config/locales/nl.yml +7 -0
- data/config/locales/ru.yml +7 -0
- data/config/locales/tr.yml +7 -0
- data/config/locales/uk.yml +7 -0
- data/config/routes.rb +1 -0
- data/lib/good_job/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6c66d226179c2cd55bfc539c943df468fc683f761b89cdc10606f03a6bb26f87
|
|
4
|
+
data.tar.gz: f72404539fb5bf7ef122cf65ed616276dd0457538b1319e253d6078e223ddbbb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 98d03d3abdbcc20956e37e8c498c8fa57c1b2b091c5f50c0654aa75875d9d23ca02aeb78d67f5f2a8c961a9aabfc0ad3899fcf1867c2b4350dfe56584568a4eb
|
|
7
|
+
data.tar.gz: f0044b4c761371391c5aec83500efece2e000a6f9741a504f244208ae403b42fd39e1324fe1e753e3ae4d67c6ae92706f9a960ab5ec2745df547acd4e0927ac7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v3.19.0](https://github.com/bensheldon/good_job/tree/v3.19.0) (2023-09-19)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.3...v3.19.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- "Force" discard jobs that are already running/runaway to prevent retry [\#1073](https://github.com/bensheldon/good_job/pull/1073) ([jgrau](https://github.com/jgrau))
|
|
10
|
+
|
|
11
|
+
**Closed issues:**
|
|
12
|
+
|
|
13
|
+
- Possible Memory Leak [\#1074](https://github.com/bensheldon/good_job/issues/1074)
|
|
14
|
+
- What's the best way to stop and discard a running job? [\#625](https://github.com/bensheldon/good_job/issues/625)
|
|
15
|
+
|
|
16
|
+
**Merged pull requests:**
|
|
17
|
+
|
|
18
|
+
- AdvisoryLockable: Abort record create if with\_advisory\_lock fails to acquire advisory lock [\#1078](https://github.com/bensheldon/good_job/pull/1078) ([bensheldon](https://github.com/bensheldon))
|
|
19
|
+
- Wrap all test background threads in Rails executors; better test logging/debugging [\#1077](https://github.com/bensheldon/good_job/pull/1077) ([bensheldon](https://github.com/bensheldon))
|
|
20
|
+
|
|
3
21
|
## [v3.18.3](https://github.com/bensheldon/good_job/tree/v3.18.3) (2023-09-16)
|
|
4
22
|
|
|
5
23
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.2...v3.18.3)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module GoodJob
|
|
4
4
|
class JobsController < GoodJob::ApplicationController
|
|
5
5
|
DISCARD_MESSAGE = "Discarded through dashboard"
|
|
6
|
+
FORCE_DISCARD_MESSAGE = "Force discarded through dashboard"
|
|
6
7
|
|
|
7
8
|
ACTIONS = {
|
|
8
9
|
discard: "discarded",
|
|
@@ -66,6 +67,12 @@ module GoodJob
|
|
|
66
67
|
redirect_back(fallback_location: jobs_path, notice: t(".notice"))
|
|
67
68
|
end
|
|
68
69
|
|
|
70
|
+
def force_discard
|
|
71
|
+
@job = Job.find(params[:id])
|
|
72
|
+
@job.force_discard_job(FORCE_DISCARD_MESSAGE)
|
|
73
|
+
redirect_back(fallback_location: jobs_path, notice: t(".notice"))
|
|
74
|
+
end
|
|
75
|
+
|
|
69
76
|
def reschedule
|
|
70
77
|
@job = Job.find(params[:id])
|
|
71
78
|
@job.reschedule_job
|
|
@@ -133,7 +133,12 @@ module GoodJob
|
|
|
133
133
|
# @return [Boolean]
|
|
134
134
|
attr_accessor :create_with_advisory_lock
|
|
135
135
|
|
|
136
|
-
after_create
|
|
136
|
+
after_create lambda {
|
|
137
|
+
advisory_lock || begin
|
|
138
|
+
errors.add(self.class.advisory_lockable_column, "Failed to acquire advisory lock: #{lockable_key}")
|
|
139
|
+
raise ActiveRecord::RecordInvalid # do not reference the record because it can cause I18n missing translation error
|
|
140
|
+
end
|
|
141
|
+
}, if: :create_with_advisory_lock
|
|
137
142
|
end
|
|
138
143
|
|
|
139
144
|
class_methods do
|
|
@@ -222,6 +227,47 @@ module GoodJob
|
|
|
222
227
|
connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Unlock', binds).first['unlocked']
|
|
223
228
|
end
|
|
224
229
|
|
|
230
|
+
# Tests whether the provided key has an advisory lock on it.
|
|
231
|
+
# @param key [String, Symbol] Key to test lock against
|
|
232
|
+
# @return [Boolean]
|
|
233
|
+
def advisory_locked_key?(key)
|
|
234
|
+
query = <<~SQL.squish
|
|
235
|
+
SELECT 1 AS one
|
|
236
|
+
FROM pg_locks
|
|
237
|
+
WHERE pg_locks.locktype = 'advisory'
|
|
238
|
+
AND pg_locks.objsubid = 1
|
|
239
|
+
AND pg_locks.classid = ('x' || substr(md5($1::text), 1, 16))::bit(32)::int
|
|
240
|
+
AND pg_locks.objid = (('x' || substr(md5($2::text), 1, 16))::bit(64) << 32)::bit(32)::int
|
|
241
|
+
LIMIT 1
|
|
242
|
+
SQL
|
|
243
|
+
binds = [
|
|
244
|
+
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
245
|
+
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
246
|
+
]
|
|
247
|
+
connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Locked?', binds).any?
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Tests whether this record is locked by the current database session.
|
|
251
|
+
# @param key [String, Symbol] Key to test lock against
|
|
252
|
+
# @return [Boolean]
|
|
253
|
+
def owns_advisory_lock_key?(key)
|
|
254
|
+
query = <<~SQL.squish
|
|
255
|
+
SELECT 1 AS one
|
|
256
|
+
FROM pg_locks
|
|
257
|
+
WHERE pg_locks.locktype = 'advisory'
|
|
258
|
+
AND pg_locks.objsubid = 1
|
|
259
|
+
AND pg_locks.classid = ('x' || substr(md5($1::text), 1, 16))::bit(32)::int
|
|
260
|
+
AND pg_locks.objid = (('x' || substr(md5($2::text), 1, 16))::bit(64) << 32)::bit(32)::int
|
|
261
|
+
AND pg_locks.pid = pg_backend_pid()
|
|
262
|
+
LIMIT 1
|
|
263
|
+
SQL
|
|
264
|
+
binds = [
|
|
265
|
+
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
266
|
+
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
267
|
+
]
|
|
268
|
+
connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Owns Advisory Lock?', binds).any?
|
|
269
|
+
end
|
|
270
|
+
|
|
225
271
|
def _advisory_lockable_column
|
|
226
272
|
advisory_lockable_column || primary_key
|
|
227
273
|
end
|
|
@@ -318,20 +364,7 @@ module GoodJob
|
|
|
318
364
|
# @param key [String, Symbol] Key to test lock against
|
|
319
365
|
# @return [Boolean]
|
|
320
366
|
def advisory_locked?(key: lockable_key)
|
|
321
|
-
|
|
322
|
-
SELECT 1 AS one
|
|
323
|
-
FROM pg_locks
|
|
324
|
-
WHERE pg_locks.locktype = 'advisory'
|
|
325
|
-
AND pg_locks.objsubid = 1
|
|
326
|
-
AND pg_locks.classid = ('x' || substr(md5($1::text), 1, 16))::bit(32)::int
|
|
327
|
-
AND pg_locks.objid = (('x' || substr(md5($2::text), 1, 16))::bit(64) << 32)::bit(32)::int
|
|
328
|
-
LIMIT 1
|
|
329
|
-
SQL
|
|
330
|
-
binds = [
|
|
331
|
-
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
332
|
-
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
333
|
-
]
|
|
334
|
-
self.class.connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Locked?', binds).any?
|
|
367
|
+
self.class.advisory_locked_key?(key)
|
|
335
368
|
end
|
|
336
369
|
|
|
337
370
|
# Tests whether this record does not have an advisory lock on it.
|
|
@@ -345,6 +378,7 @@ module GoodJob
|
|
|
345
378
|
# @param key [String, Symbol] Key to test lock against
|
|
346
379
|
# @return [Boolean]
|
|
347
380
|
def owns_advisory_lock?(key: lockable_key)
|
|
381
|
+
self.class.owns_advisory_lock_key?(key)
|
|
348
382
|
query = <<~SQL.squish
|
|
349
383
|
SELECT 1 AS one
|
|
350
384
|
FROM pg_locks
|
|
@@ -30,10 +30,10 @@ module GoodJob
|
|
|
30
30
|
|
|
31
31
|
# Runs the block with self.logger silenced.
|
|
32
32
|
# If self.logger is nil, simply runs the block.
|
|
33
|
-
def self.with_logger_silenced(&block)
|
|
33
|
+
def self.with_logger_silenced(silent: true, &block)
|
|
34
34
|
# Assign to a local variable, just in case it's modified in another thread concurrently
|
|
35
35
|
logger = self.logger
|
|
36
|
-
if logger.respond_to?
|
|
36
|
+
if silent && logger.respond_to?(:silence)
|
|
37
37
|
logger.silence(&block)
|
|
38
38
|
else
|
|
39
39
|
yield
|
data/app/models/good_job/job.rb
CHANGED
|
@@ -215,32 +215,17 @@ module GoodJob
|
|
|
215
215
|
# @return [void]
|
|
216
216
|
def discard_job(message)
|
|
217
217
|
with_advisory_lock do
|
|
218
|
-
|
|
219
|
-
active_job = execution.active_job(ignore_deserialization_errors: true)
|
|
220
|
-
|
|
221
|
-
raise ActionForStateMismatchError if execution.finished_at.present?
|
|
222
|
-
|
|
223
|
-
job_error = GoodJob::Job::DiscardJobError.new(message)
|
|
224
|
-
|
|
225
|
-
update_execution = proc do
|
|
226
|
-
execution.update(
|
|
227
|
-
{
|
|
228
|
-
finished_at: Time.current,
|
|
229
|
-
error: GoodJob::Execution.format_error(job_error),
|
|
230
|
-
}.tap do |attrs|
|
|
231
|
-
attrs[:error_event] = ERROR_EVENT_DISCARDED if self.class.error_event_migrated?
|
|
232
|
-
end
|
|
233
|
-
)
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
if active_job.respond_to?(:instrument)
|
|
237
|
-
active_job.send :instrument, :discard, error: job_error, &update_execution
|
|
238
|
-
else
|
|
239
|
-
update_execution.call
|
|
240
|
-
end
|
|
218
|
+
_discard_job(message)
|
|
241
219
|
end
|
|
242
220
|
end
|
|
243
221
|
|
|
222
|
+
# Force discard a job so that it will not be executed further. Force discard allows discarding
|
|
223
|
+
# a running job.
|
|
224
|
+
# This action will add a {DiscardJobError} to the job's {Execution} and mark it as finished.
|
|
225
|
+
def force_discard_job(message)
|
|
226
|
+
_discard_job(message)
|
|
227
|
+
end
|
|
228
|
+
|
|
244
229
|
# Reschedule a scheduled job so that it executes immediately (or later) by the next available execution thread.
|
|
245
230
|
# @param scheduled_at [DateTime, Time] When to reschedule the job
|
|
246
231
|
# @return [void]
|
|
@@ -277,5 +262,33 @@ module GoodJob
|
|
|
277
262
|
def _head?
|
|
278
263
|
_execution_id == head_execution(reload: true).id
|
|
279
264
|
end
|
|
265
|
+
|
|
266
|
+
private
|
|
267
|
+
|
|
268
|
+
def _discard_job(message)
|
|
269
|
+
execution = head_execution(reload: true)
|
|
270
|
+
active_job = execution.active_job(ignore_deserialization_errors: true)
|
|
271
|
+
|
|
272
|
+
raise ActionForStateMismatchError if execution.finished_at.present?
|
|
273
|
+
|
|
274
|
+
job_error = GoodJob::Job::DiscardJobError.new(message)
|
|
275
|
+
|
|
276
|
+
update_execution = proc do
|
|
277
|
+
execution.update(
|
|
278
|
+
{
|
|
279
|
+
finished_at: Time.current,
|
|
280
|
+
error: GoodJob::Execution.format_error(job_error),
|
|
281
|
+
}.tap do |attrs|
|
|
282
|
+
attrs[:error_event] = ERROR_EVENT_DISCARDED if self.class.error_event_migrated?
|
|
283
|
+
end
|
|
284
|
+
)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
if active_job.respond_to?(:instrument)
|
|
288
|
+
active_job.send :instrument, :discard, error: job_error, &update_execution
|
|
289
|
+
else
|
|
290
|
+
update_execution.call
|
|
291
|
+
end
|
|
292
|
+
end
|
|
280
293
|
end
|
|
281
294
|
end
|
|
@@ -127,6 +127,13 @@
|
|
|
127
127
|
<%=t "good_job.actions.discard" %>
|
|
128
128
|
<% end %>
|
|
129
129
|
</li>
|
|
130
|
+
<li>
|
|
131
|
+
<% job_force_discardable = job.status.in? [:running] %>
|
|
132
|
+
<%= link_to force_discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_force_discardable}", title: t("good_job.jobs.actions.force_discard"), data: { confirm: t("good_job.jobs.actions.confirm_force_discard"), disable: true } do %>
|
|
133
|
+
<%= render "good_job/shared/icons/eject" %>
|
|
134
|
+
<%=t "good_job.actions.force_discard" %>
|
|
135
|
+
<% end %>
|
|
136
|
+
</li>
|
|
130
137
|
<li>
|
|
131
138
|
<%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { confirm: t("good_job.jobs.actions.confirm_retry"), disable: true } do %>
|
|
132
139
|
<%= render "good_job/shared/icons/arrow_clockwise" %>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- https://icons.getbootstrap.com/icons/eject/ -->
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eject" viewBox="0 0 16 16">
|
|
3
|
+
<path d="M7.27 1.047a1 1 0 0 1 1.46 0l6.345 6.77c.6.638.146 1.683-.73 1.683H1.656C.78 9.5.326 8.455.926 7.816L7.27 1.047zM14.346 8.5 8 1.731 1.654 8.5h12.692zM.5 11.5a1 1 0 0 1 1-1h13a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1v-1zm14 0h-13v1h13v-1z" />
|
|
4
|
+
</svg>
|
data/config/locales/de.yml
CHANGED
|
@@ -4,6 +4,7 @@ de:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Zerstören
|
|
6
6
|
discard: Verwerfen
|
|
7
|
+
force_discard: Verwerfen erzwingen
|
|
7
8
|
inspect: Prüfen
|
|
8
9
|
reschedule: Umplanen
|
|
9
10
|
retry: Wiederholen
|
|
@@ -110,10 +111,14 @@ de:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: Sind Sie sicher, dass Sie den Job zerstören wollen?
|
|
112
113
|
confirm_discard: Sind Sie sicher, dass Sie den Job verwerfen wollen?
|
|
114
|
+
confirm_force_discard: 'Sind Sie sicher, dass Sie das Verwerfen dieses Jobs erzwingen möchten? Der Job wird als verworfen markiert, aber der laufende Job wird nicht gestoppt – er wird jedoch bei Fehlern nicht erneut versucht.
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: Möchten Sie den Auftrag wirklich verschieben?
|
|
114
118
|
confirm_retry: Möchten Sie den Job wirklich wiederholen?
|
|
115
119
|
destroy: Arbeit vernichten
|
|
116
120
|
discard: Auftrag verwerfen
|
|
121
|
+
force_discard: Job verwerfen erzwingen
|
|
117
122
|
reschedule: Auftrag neu planen
|
|
118
123
|
retry: Job wiederholen
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ de:
|
|
|
124
129
|
in_queue: in der Warteschlange
|
|
125
130
|
runtime: Laufzeit
|
|
126
131
|
title: Hinrichtungen
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: Der Job wurde zwangsweise verworfen. Die Ausführung wird fortgesetzt, bei Fehlern wird der Vorgang jedoch nicht wiederholt
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: Job-Paginierung
|
|
129
136
|
older_jobs: Ältere Berufe
|
data/config/locales/en.yml
CHANGED
|
@@ -4,6 +4,7 @@ en:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Destroy
|
|
6
6
|
discard: Discard
|
|
7
|
+
force_discard: Force discard
|
|
7
8
|
inspect: Inspect
|
|
8
9
|
reschedule: Reschedule
|
|
9
10
|
retry: Retry
|
|
@@ -110,10 +111,14 @@ en:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: Are you sure you want to destroy the job?
|
|
112
113
|
confirm_discard: Are you usure you want to discard the job?
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: Are you sure you want to reschedule the job?
|
|
114
118
|
confirm_retry: Are you sure you want to retry the job?
|
|
115
119
|
destroy: Destroy job
|
|
116
120
|
discard: Discard job
|
|
121
|
+
force_discard: Force discard job
|
|
117
122
|
reschedule: Reschedule job
|
|
118
123
|
retry: Retry job
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ en:
|
|
|
124
129
|
in_queue: in queue
|
|
125
130
|
runtime: runtime
|
|
126
131
|
title: Executions
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: Job has been force discarded. It will continue to run but it will not be retried on failures
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: Job pagination
|
|
129
136
|
older_jobs: Older jobs
|
data/config/locales/es.yml
CHANGED
|
@@ -4,6 +4,7 @@ es:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Eliminar
|
|
6
6
|
discard: Descartar
|
|
7
|
+
force_discard: Forzar descarte
|
|
7
8
|
inspect: Inspeccionar
|
|
8
9
|
reschedule: Reprogramar
|
|
9
10
|
retry: Reintentar
|
|
@@ -110,10 +111,12 @@ es:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: "¿Estás seguro que querés eliminar esta tarea?"
|
|
112
113
|
confirm_discard: "¿Estás seguro que querés descartar esta tarea?"
|
|
114
|
+
confirm_force_discard: "¿Está seguro de que desea forzar el descarte de este trabajo? El trabajo se marcará como descartado, pero el trabajo en ejecución no se detendrá; sin embargo, no se volverá a intentar en caso de falla.\n"
|
|
113
115
|
confirm_reschedule: "¿Estás seguro que querés reprogramar esta tarea?"
|
|
114
116
|
confirm_retry: "¿Estás seguro que querés reintentar esta tarea?"
|
|
115
117
|
destroy: Eliminar tarea
|
|
116
118
|
discard: Descartar tarea
|
|
119
|
+
force_discard: Forzar el descarte del trabajo
|
|
117
120
|
reschedule: Reprogramar tarea
|
|
118
121
|
retry: Reiuntentar tarea
|
|
119
122
|
destroy:
|
|
@@ -124,6 +127,8 @@ es:
|
|
|
124
127
|
in_queue: en cola
|
|
125
128
|
runtime: en ejecución
|
|
126
129
|
title: Ejecuciones
|
|
130
|
+
force_discard:
|
|
131
|
+
notice: Job ha sido descartado a la fuerza. Continuará ejecutándose pero no se volverá a intentar en caso de fallas.
|
|
127
132
|
index:
|
|
128
133
|
job_pagination: Paginación de tareas
|
|
129
134
|
older_jobs: Tareas anteriores
|
data/config/locales/fr.yml
CHANGED
|
@@ -4,6 +4,7 @@ fr:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Détruire
|
|
6
6
|
discard: Mettre au rebut
|
|
7
|
+
force_discard: Forcer le rejet
|
|
7
8
|
inspect: Inspecter
|
|
8
9
|
reschedule: Reprogrammer
|
|
9
10
|
retry: Recommencez
|
|
@@ -110,10 +111,14 @@ fr:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: Voulez-vous vraiment détruire le job ?
|
|
112
113
|
confirm_discard: Voulez-vous vraiment mettre au rebut le job ?
|
|
114
|
+
confirm_force_discard: 'Êtes-vous sûr de vouloir forcer l''abandon de cette tâche ? Le travail sera marqué comme abandonné mais le travail en cours d''exécution ne sera pas arrêté - il ne sera cependant pas réessayé en cas d''échec.
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: Voulez-vous vraiment replanifier le job ?
|
|
114
118
|
confirm_retry: Voulez-vous vraiment réessayer le job ?
|
|
115
119
|
destroy: Détruire le job
|
|
116
120
|
discard: Mettre au rebut le job
|
|
121
|
+
force_discard: Forcer l'abandon du travail
|
|
117
122
|
reschedule: Replanifier le job
|
|
118
123
|
retry: Réessayer le job
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ fr:
|
|
|
124
129
|
in_queue: Dans la file d'attente
|
|
125
130
|
runtime: Durée
|
|
126
131
|
title: Exécutions
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: Le travail a été abandonné de force. Il continuera à fonctionner mais il ne sera pas réessayé en cas d'échec
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: Pagination du job
|
|
129
136
|
older_jobs: Jobs plus anciens
|
data/config/locales/ja.yml
CHANGED
|
@@ -4,6 +4,7 @@ ja:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: 削除する
|
|
6
6
|
discard: 破棄する
|
|
7
|
+
force_discard: 強制破棄
|
|
7
8
|
inspect: 調査する
|
|
8
9
|
reschedule: 再スケジュールする
|
|
9
10
|
retry: 再試行する
|
|
@@ -110,10 +111,14 @@ ja:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: ジョブを削除してもよろしいですか?
|
|
112
113
|
confirm_discard: ジョブを破棄してもよろしいですか?
|
|
114
|
+
confirm_force_discard: 'このジョブを強制的に破棄してもよろしいですか?ジョブは破棄済みとしてマークされますが、実行中のジョブは停止されません。ただし、失敗した場合は再試行されません。
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: ジョブを再スケジュールしてもよろしいですか?
|
|
114
118
|
confirm_retry: ジョブを再試行してもよろしいですか?
|
|
115
119
|
destroy: ジョブを削除
|
|
116
120
|
discard: ジョブを破棄
|
|
121
|
+
force_discard: ジョブを強制的に破棄する
|
|
117
122
|
reschedule: ジョブを再スケジュール
|
|
118
123
|
retry: ジョブを再試行
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ ja:
|
|
|
124
129
|
in_queue: 待機中
|
|
125
130
|
runtime: 実行時間
|
|
126
131
|
title: 実行
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: ジョブは強制的に破棄されました。実行は継続されますが、失敗した場合は再試行されません
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: ジョブのページネーション
|
|
129
136
|
older_jobs: 古いジョブ
|
data/config/locales/nl.yml
CHANGED
|
@@ -4,6 +4,7 @@ nl:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Vernietigen
|
|
6
6
|
discard: Weggooien
|
|
7
|
+
force_discard: Forceer weggooien
|
|
7
8
|
inspect: Inspecteren
|
|
8
9
|
reschedule: Opnieuw plannen
|
|
9
10
|
retry: Opnieuw proberen
|
|
@@ -110,10 +111,14 @@ nl:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: Weet je zeker dat je de baan wilt vernietigen?
|
|
112
113
|
confirm_discard: Wilt u de baan afwijzen?
|
|
114
|
+
confirm_force_discard: 'Weet u zeker dat u deze taak geforceerd wilt weggooien? De taak wordt gemarkeerd als verwijderd, maar de lopende taak wordt niet gestopt. Bij fouten wordt deze echter niet opnieuw geprobeerd.
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: Weet u zeker dat u de taak opnieuw wilt inplannen?
|
|
114
118
|
confirm_retry: Weet u zeker dat u de taak opnieuw wilt proberen?
|
|
115
119
|
destroy: Baan vernietigen
|
|
116
120
|
discard: Gooi de baan weg
|
|
121
|
+
force_discard: Forceer taak weggooien
|
|
117
122
|
reschedule: Taak opnieuw plannen
|
|
118
123
|
retry: Taak opnieuw proberen
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ nl:
|
|
|
124
129
|
in_queue: in de wachtrij
|
|
125
130
|
runtime: looptijd
|
|
126
131
|
title: Executies
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: Baan is gedwongen verwijderd. Het blijft actief, maar wordt niet opnieuw geprobeerd als er fouten optreden
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: Taak paginering
|
|
129
136
|
older_jobs: Oudere banen
|
data/config/locales/ru.yml
CHANGED
|
@@ -4,6 +4,7 @@ ru:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Разрушать
|
|
6
6
|
discard: Отказаться
|
|
7
|
+
force_discard: Принудительно отменить
|
|
7
8
|
inspect: Осмотреть
|
|
8
9
|
reschedule: Перенести
|
|
9
10
|
retry: Повторить попытку
|
|
@@ -134,10 +135,14 @@ ru:
|
|
|
134
135
|
actions:
|
|
135
136
|
confirm_destroy: Вы уверены, что хотите уничтожить задание?
|
|
136
137
|
confirm_discard: Вы уверены, что хотите отказаться от задания?
|
|
138
|
+
confirm_force_discard: 'Вы уверены, что хотите принудительно отменить это задание? Задание будет помечено как отброшенное, но выполняемое задание не будет остановлено, однако в случае сбоя оно не будет повторено.
|
|
139
|
+
|
|
140
|
+
'
|
|
137
141
|
confirm_reschedule: Вы уверены, что хотите перенести задание?
|
|
138
142
|
confirm_retry: Вы уверены, что хотите повторить задание?
|
|
139
143
|
destroy: Уничтожить работу
|
|
140
144
|
discard: Отменить задание
|
|
145
|
+
force_discard: Принудительно отменить задание
|
|
141
146
|
reschedule: Перенести задание
|
|
142
147
|
retry: Повторить задание
|
|
143
148
|
destroy:
|
|
@@ -148,6 +153,8 @@ ru:
|
|
|
148
153
|
in_queue: в очереди
|
|
149
154
|
runtime: время выполнения
|
|
150
155
|
title: Казни
|
|
156
|
+
force_discard:
|
|
157
|
+
notice: Иов был принудительно отброшен. Он продолжит работу, но не будет повторяться в случае сбоя.
|
|
151
158
|
index:
|
|
152
159
|
job_pagination: Пагинация вакансий
|
|
153
160
|
older_jobs: Старые рабочие места
|
data/config/locales/tr.yml
CHANGED
|
@@ -4,6 +4,7 @@ tr:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Sil
|
|
6
6
|
discard: İptal Et
|
|
7
|
+
force_discard: Atmaya zorla
|
|
7
8
|
inspect: İncele
|
|
8
9
|
reschedule: Yeniden planla
|
|
9
10
|
retry: Tekrar dene
|
|
@@ -110,10 +111,14 @@ tr:
|
|
|
110
111
|
actions:
|
|
111
112
|
confirm_destroy: Bu işi silmek istediğinizden emin misiniz?
|
|
112
113
|
confirm_discard: Bu işi iptal etmek istediğinizden emin misiniz?
|
|
114
|
+
confirm_force_discard: 'Bu işi zorla iptal etmek istediğinizden emin misiniz? İş atıldı olarak işaretlenecek ancak devam eden iş durdurulmayacak; ancak başarısızlık durumunda yeniden denenmeyecek.
|
|
115
|
+
|
|
116
|
+
'
|
|
113
117
|
confirm_reschedule: Bu işi yeniden planlamak istediğinizden emin misiniz?
|
|
114
118
|
confirm_retry: Bu işi tekrar denemek istediğinizden emin misiniz?
|
|
115
119
|
destroy: İşi Sil
|
|
116
120
|
discard: İşi İptal Et
|
|
121
|
+
force_discard: İşi zorla atmaya zorla
|
|
117
122
|
reschedule: İşi Yeniden Planla
|
|
118
123
|
retry: İşi Tekrar Dene
|
|
119
124
|
destroy:
|
|
@@ -124,6 +129,8 @@ tr:
|
|
|
124
129
|
in_queue: sırada
|
|
125
130
|
runtime: çalışma süresi
|
|
126
131
|
title: İşlemler
|
|
132
|
+
force_discard:
|
|
133
|
+
notice: İş zorla atıldı. Çalışmaya devam edecek ancak arıza durumunda yeniden denenmeyecek
|
|
127
134
|
index:
|
|
128
135
|
job_pagination: İş sayfalandırması
|
|
129
136
|
older_jobs: Daha eski işler
|
data/config/locales/uk.yml
CHANGED
|
@@ -4,6 +4,7 @@ uk:
|
|
|
4
4
|
actions:
|
|
5
5
|
destroy: Видалити
|
|
6
6
|
discard: Відхилити
|
|
7
|
+
force_discard: Примусово скинути
|
|
7
8
|
inspect: Оглянути
|
|
8
9
|
reschedule: Перепланувати
|
|
9
10
|
retry: Повторити
|
|
@@ -134,10 +135,14 @@ uk:
|
|
|
134
135
|
actions:
|
|
135
136
|
confirm_destroy: Ви впевнені, що хочете видалити завдання?
|
|
136
137
|
confirm_discard: Ви впевнені, що хочете відхилити завдання?
|
|
138
|
+
confirm_force_discard: 'Ви впевнені, що хочете примусово скасувати цю роботу? Завдання буде позначено як відхилене, але виконуване завдання не буде зупинено – однак його не буде повторено у випадку помилок.
|
|
139
|
+
|
|
140
|
+
'
|
|
137
141
|
confirm_reschedule: Ви впевнені, що хочете перепланувати завдання?
|
|
138
142
|
confirm_retry: Ви впевнені, що хочете повторити завдання?
|
|
139
143
|
destroy: Видалити завдання
|
|
140
144
|
discard: Відхилити завдання
|
|
145
|
+
force_discard: Примусово скасувати завдання
|
|
141
146
|
reschedule: Перепланувати завдання
|
|
142
147
|
retry: Повторити завдання
|
|
143
148
|
destroy:
|
|
@@ -148,6 +153,8 @@ uk:
|
|
|
148
153
|
in_queue: у черзі
|
|
149
154
|
runtime: час виконання
|
|
150
155
|
title: Виконання
|
|
156
|
+
force_discard:
|
|
157
|
+
notice: Роботу примусово скасовано. Він продовжуватиме працювати, але не буде повторюватися в разі помилок
|
|
151
158
|
index:
|
|
152
159
|
job_pagination: Пагінація робіт
|
|
153
160
|
older_jobs: Старі роботи
|
data/config/routes.rb
CHANGED
data/lib/good_job/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: good_job
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben Sheldon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-09-
|
|
11
|
+
date: 2023-09-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activejob
|
|
@@ -313,6 +313,7 @@ files:
|
|
|
313
313
|
- app/views/good_job/shared/icons/_clock.html.erb
|
|
314
314
|
- app/views/good_job/shared/icons/_dash_circle.html.erb
|
|
315
315
|
- app/views/good_job/shared/icons/_dots.html.erb
|
|
316
|
+
- app/views/good_job/shared/icons/_eject.html.erb
|
|
316
317
|
- app/views/good_job/shared/icons/_exclamation.html.erb
|
|
317
318
|
- app/views/good_job/shared/icons/_info.html.erb
|
|
318
319
|
- app/views/good_job/shared/icons/_moon_stars_fill.html.erb
|