inst-jobs 2.1.3 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c31ed6d846425c9bf022bb8c744681019cbf0f0192d4e0ee7f0a5d7dc44a65c
4
- data.tar.gz: 4a5b940ba8bd6770209d93e20ccc217d4ab5915bcd1a5791de70b076e7cecf97
3
+ metadata.gz: c062c222e731bd490efe572108a508bf78faabee4479f7fe6927a89688d9ef0b
4
+ data.tar.gz: 3b1678fc017230e990bc7e8d4e652c23ab59413953ce72a312b13adfa7626193
5
5
  SHA512:
6
- metadata.gz: 07377763c26979774add4b3445aa72ebc2cbff6aabe595e1157c883a90dea48407bc8ecb87f5532265178a96b27548caaf5ce13a0789c469272980bc864a2882
7
- data.tar.gz: 7ddd291e18be337ae1d858d016af92cc255c111e5141eafca8cee598fcdae9563a74983ba6b98daeb50c1fe599490dd9c962e1c722d5dcea5083bf16a619641d
6
+ metadata.gz: 8c1a722c17c9abc8f5c8a44cb28f6584dc9fb16c1edcccc8df566ad21a5f81af7a54fb70282e2689aee11947dcd96f44ca01dfe542d71c8d3d6b7f145a572ce7
7
+ data.tar.gz: 9a7a65c71820d4b04f1e1ac2bf498cf030490a597d075d87d4399a392a7da1bbf50cfb3d5eeb1dea9c357d11e00aabf5e469f062c1fe9cc4b02cc8ed08e1a192
@@ -53,18 +53,12 @@ class Periodic
53
53
  end
54
54
 
55
55
  def enqueue_args
56
- # yes, checking for whether it is actually the boolean literal false,
57
- # which means the consuming code really does not want this job to be
58
- # a singleton at all.
59
- non_singleton_periodic_job = @job_args[:singleton] == false
60
56
  inferred_args = {
61
57
  max_attempts: 1,
62
58
  run_at: @cron.next_time(Delayed::Periodic.now).utc.to_time,
63
- singleton: (non_singleton_periodic_job ? nil : tag)
59
+ singleton: tag,
60
+ on_conflict: :patient
64
61
  }
65
- unless non_singleton_periodic_job
66
- inferred_args[:on_conflict] = :patient
67
- end
68
62
  @job_args.merge(inferred_args)
69
63
  end
70
64
 
@@ -39,6 +39,7 @@ class Pool
39
39
  Process.wait unlock_pid
40
40
 
41
41
  spawn_periodic_auditor
42
+ spawn_abandoned_job_cleanup
42
43
  spawn_all_workers
43
44
  say "Workers spawned"
44
45
  join
@@ -111,6 +112,34 @@ class Pool
111
112
  end
112
113
  end
113
114
 
115
+ def spawn_abandoned_job_cleanup
116
+ return if Settings.disable_abandoned_job_cleanup
117
+ cleanup_interval_in_minutes = 60
118
+ @abandoned_cleanup_thread = Thread.new do
119
+ # every hour (staggered by process)
120
+ # check for dead jobs and cull them.
121
+ # Will actually be more often based on the
122
+ # number of worker nodes in the pool. This will actually
123
+ # be a max of N times per hour where N is the number of workers,
124
+ # but they won't overrun each other because the health check
125
+ # takes an advisory lock internally
126
+ sleep(rand(cleanup_interval_in_minutes * 60))
127
+ loop do
128
+ schedule_abandoned_job_cleanup
129
+ sleep(cleanup_interval_in_minutes * 60)
130
+ end
131
+ end
132
+ end
133
+
134
+ def schedule_abandoned_job_cleanup
135
+ pid = fork_with_reconnects do
136
+ # we want to avoid db connections in the main pool process
137
+ $0 = "delayed_abandoned_job_cleanup"
138
+ Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
139
+ end
140
+ workers[pid] = :abandoned_job_cleanup
141
+ end
142
+
114
143
  def spawn_periodic_auditor
115
144
  return if Settings.disable_periodic_jobs
116
145
 
@@ -217,6 +246,8 @@ class Pool
217
246
  case worker
218
247
  when :periodic_audit
219
248
  say "ran auditor: #{worker}"
249
+ when :abandoned_job_cleanup
250
+ say "ran cleanup: #{worker}"
220
251
  when :work_queue
221
252
  say "work queue exited, restarting", :info
222
253
  spawn_work_queue
@@ -8,6 +8,7 @@ module Delayed
8
8
  module Settings
9
9
  SETTINGS = [
10
10
  :default_job_options,
11
+ :disable_abandoned_job_cleanup,
11
12
  :disable_periodic_jobs,
12
13
  :disable_automatic_orphan_unlocking,
13
14
  :fetch_batch_size,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delayed
4
- VERSION = "2.1.3"
4
+ VERSION = "2.2.0"
5
5
  end
@@ -23,12 +23,13 @@ module Delayed
23
23
  def reschedule_abandoned_jobs
24
24
  return if Settings.worker_health_check_type == :none
25
25
  Delayed::Job.transaction do
26
- # this job is a special case, and is not a singleton
26
+ # this action is a special case, and SHOULD NOT be a periodic job
27
27
  # because if it gets wiped out suddenly during execution
28
28
  # it can't go clean up it's abandoned self. Therefore,
29
- # we try to get an advisory lock when it runs. If we succeed,
30
- # no other job is trying to do this right now (and if we abandon the
31
- # job, the transaction will end, releasing the advisory lock).
29
+ # we expect it to get run from it's own process forked from the job pool
30
+ # and we try to get an advisory lock when it runs. If we succeed,
31
+ # no other worker is trying to do this right now (and if we abandon the
32
+ # operation, the transaction will end, releasing the advisory lock).
32
33
  result = attempt_advisory_lock
33
34
  return unless result
34
35
  checker = Worker::HealthCheck.build(
@@ -27,15 +27,5 @@ RSpec.describe Delayed::Periodic do
27
27
  expect(instance).to_not be_nil
28
28
  expect(instance.enqueue_args[:singleton]).to eq("periodic: just a test")
29
29
  end
30
-
31
- it "uses no singleton if told to skip" do
32
- Delayed::Periodic.cron job_name, '*/10 * * * *', {singleton: false} do
33
- # no-op
34
- end
35
- instance = Delayed::Periodic.scheduled[job_name]
36
- expect(instance).to_not be_nil
37
- expect(instance.enqueue_args[:singleton]).to be_nil
38
- Delayed::Periodic.perform_audit!
39
- end
40
30
  end
41
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-12-22 00:00:00.000000000 Z
12
+ date: 2021-01-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord