solid_queue 0.3.0 → 0.3.1

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -10
  3. data/app/models/solid_queue/blocked_execution.rb +16 -10
  4. data/app/models/solid_queue/claimed_execution.rb +11 -4
  5. data/app/models/solid_queue/execution/dispatching.rb +2 -3
  6. data/app/models/solid_queue/execution.rb +32 -15
  7. data/app/models/solid_queue/failed_execution.rb +10 -6
  8. data/app/models/solid_queue/job/executable.rb +1 -1
  9. data/app/models/solid_queue/job/schedulable.rb +1 -1
  10. data/app/models/solid_queue/process/prunable.rb +6 -5
  11. data/app/models/solid_queue/process.rb +13 -6
  12. data/app/models/solid_queue/recurring_execution.rb +3 -3
  13. data/app/models/solid_queue/scheduled_execution.rb +3 -1
  14. data/app/models/solid_queue/semaphore.rb +1 -1
  15. data/lib/active_job/queue_adapters/solid_queue_adapter.rb +4 -0
  16. data/lib/generators/solid_queue/install/templates/config.yml +1 -1
  17. data/lib/puma/plugin/solid_queue.rb +1 -0
  18. data/lib/solid_queue/app_executor.rb +1 -1
  19. data/lib/solid_queue/dispatcher/recurring_task.rb +13 -7
  20. data/lib/solid_queue/dispatcher.rb +4 -4
  21. data/lib/solid_queue/engine.rb +4 -2
  22. data/lib/solid_queue/log_subscriber.rb +164 -0
  23. data/lib/solid_queue/processes/base.rb +16 -0
  24. data/lib/solid_queue/processes/interruptible.rb +1 -1
  25. data/lib/solid_queue/processes/poller.rb +7 -5
  26. data/lib/solid_queue/processes/registrable.rb +5 -23
  27. data/lib/solid_queue/processes/runnable.rb +4 -3
  28. data/lib/solid_queue/processes/signals.rb +1 -1
  29. data/lib/solid_queue/supervisor.rb +25 -24
  30. data/lib/solid_queue/version.rb +1 -1
  31. data/lib/solid_queue/worker.rb +6 -6
  32. data/lib/solid_queue.rb +19 -10
  33. metadata +23 -11
  34. data/lib/solid_queue/recurring_tasks/manager.rb +0 -31
  35. data/lib/solid_queue/recurring_tasks/schedule.rb +0 -58
  36. data/lib/solid_queue/recurring_tasks/task.rb +0 -87
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/log_subscriber"
4
+
5
+ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
6
+ def dispatch_scheduled(event)
7
+ debug formatted_event(event, action: "Dispatch scheduled jobs", **event.payload.slice(:batch_size, :size))
8
+ end
9
+
10
+ def release_many_claimed(event)
11
+ debug formatted_event(event, action: "Release claimed jobs", **event.payload.slice(:size))
12
+ end
13
+
14
+ def release_claimed(event)
15
+ debug formatted_event(event, action: "Release claimed job", **event.payload.slice(:job_id, :process_id))
16
+ end
17
+
18
+ def retry_all(event)
19
+ debug formatted_event(event, action: "Retry failed jobs", **event.payload.slice(:jobs_size, :size))
20
+ end
21
+
22
+ def retry(event)
23
+ debug formatted_event(event, action: "Retry failed job", **event.payload.slice(:job_id))
24
+ end
25
+
26
+ def discard_all(event)
27
+ debug formatted_event(event, action: "Discard jobs", **event.payload.slice(:jobs_size, :size, :status))
28
+ end
29
+
30
+ def discard(event)
31
+ debug formatted_event(event, action: "Discard job", **event.payload.slice(:job_id, :status))
32
+ end
33
+
34
+ def release_many_blocked(event)
35
+ debug formatted_event(event, action: "Unblock jobs", **event.payload.slice(:limit, :size))
36
+ end
37
+
38
+ def release_blocked(event)
39
+ debug formatted_event(event, action: "Release blocked job", **event.payload.slice(:job_id, :concurrency_key, :released))
40
+ end
41
+
42
+ def enqueue_recurring_task(event)
43
+ attributes = event.payload.slice(:task, :at, :active_job_id)
44
+
45
+ if event.payload[:other_adapter]
46
+ debug formatted_event(event, action: "Enqueued recurring task outside Solid Queue", **attributes)
47
+ else
48
+ action = attributes[:active_job_id].present? ? "Enqueued recurring task" : "Skipped recurring task – already dispatched"
49
+ info formatted_event(event, action: action, **attributes)
50
+ end
51
+ end
52
+
53
+ def start_process(event)
54
+ process = event.payload[:process]
55
+
56
+ attributes = {
57
+ pid: process.pid,
58
+ hostname: process.hostname
59
+ }.merge(process.metadata)
60
+
61
+ info formatted_event(event, action: "Started #{process.kind}", **attributes)
62
+ end
63
+
64
+ def shutdown_process(event)
65
+ process = event.payload[:process]
66
+
67
+ attributes = {
68
+ pid: process.pid,
69
+ hostname: process.hostname
70
+ }.merge(process.metadata)
71
+
72
+ info formatted_event(event, action: "Shut down #{process.kind}", **attributes)
73
+ end
74
+
75
+ def register_process(event)
76
+ process_kind = event.payload[:kind]
77
+ attributes = event.payload.slice(:pid, :hostname)
78
+
79
+ if error = event.payload[:error]
80
+ warn formatted_event(event, action: "Error registering #{process_kind}", **attributes.merge(error: formatted_error(error)))
81
+ else
82
+ info formatted_event(event, action: "Register #{process_kind}", **attributes)
83
+ end
84
+ end
85
+
86
+ def deregister_process(event)
87
+ process = event.payload[:process]
88
+
89
+ attributes = {
90
+ process_id: process.id,
91
+ pid: process.pid,
92
+ hostname: process.hostname,
93
+ last_heartbeat_at: process.last_heartbeat_at,
94
+ claimed_size: process.claimed_executions.size,
95
+ pruned: event.payload
96
+ }
97
+
98
+ if error = event.payload[:error]
99
+ warn formatted_event(event, action: "Error deregistering #{process.kind}", **attributes.merge(error: formatted_error(error)))
100
+ else
101
+ info formatted_event(event, action: "Deregister #{process.kind}", **attributes)
102
+ end
103
+ end
104
+
105
+ def prune_processes(event)
106
+ debug formatted_event(event, action: "Prune dead processes", **event.payload.slice(:size))
107
+ end
108
+
109
+ def thread_error(event)
110
+ error formatted_event(event, action: "Error in thread", error: formatted_error(event.payload[:error]))
111
+ end
112
+
113
+ def graceful_termination(event)
114
+ attributes = event.payload.slice(:supervisor_pid, :supervised_pids)
115
+
116
+ if event.payload[:shutdown_timeout_exceeded]
117
+ warn formatted_event(event, action: "Supervisor wasn't terminated gracefully - shutdown timeout exceeded", **attributes)
118
+ else
119
+ info formatted_event(event, action: "Supervisor terminated gracefully", **attributes)
120
+ end
121
+ end
122
+
123
+ def immediate_termination(event)
124
+ info formatted_event(event, action: "Supervisor terminated immediately", **event.payload.slice(:supervisor_pid, :supervised_pids))
125
+ end
126
+
127
+ def unhandled_signal_error(event)
128
+ error formatted_event(event, action: "Received unhandled signal", **event.payload.slice(:signal))
129
+ end
130
+
131
+ def replace_fork(event)
132
+ status = event.payload[:status]
133
+ attributes = event.payload.slice(:pid).merge \
134
+ status: (status.exitstatus || "no exit status set"),
135
+ pid_from_status: status.pid,
136
+ signaled: status.signaled?,
137
+ stopsig: status.stopsig,
138
+ termsig: status.termsig
139
+
140
+ if replaced_fork = event.payload[:fork]
141
+ info formatted_event(event, action: "Replaced terminated #{replaced_fork.kind}", **attributes.merge(hostname: replaced_fork.hostname))
142
+ else
143
+ warn formatted_event(event, action: "Tried to replace forked process but it had already died", **attributes)
144
+ end
145
+ end
146
+
147
+ private
148
+ def formatted_event(event, action:, **attributes)
149
+ "SolidQueue-#{SolidQueue::VERSION} #{action} (#{event.duration.round(1)}ms) #{formatted_attributes(**attributes)}"
150
+ end
151
+
152
+ def formatted_attributes(**attributes)
153
+ attributes.map { |attr, value| "#{attr}: #{value.inspect}" }.join(", ")
154
+ end
155
+
156
+ def formatted_error(error)
157
+ [ error.class, error.message ].compact.join(" ")
158
+ end
159
+
160
+ # Use the logger configured for SolidQueue
161
+ def logger
162
+ SolidQueue.logger
163
+ end
164
+ end
@@ -5,6 +5,22 @@ module SolidQueue
5
5
  class Base
6
6
  include Callbacks # Defines callbacks needed by other concerns
7
7
  include AppExecutor, Registrable, Interruptible, Procline
8
+
9
+ def kind
10
+ self.class.name.demodulize
11
+ end
12
+
13
+ def hostname
14
+ @hostname ||= Socket.gethostname.force_encoding(Encoding::UTF_8)
15
+ end
16
+
17
+ def pid
18
+ @pid ||= ::Process.pid
19
+ end
20
+
21
+ def metadata
22
+ {}
23
+ end
8
24
  end
9
25
  end
10
26
  end
@@ -10,7 +10,7 @@ module SolidQueue::Processes
10
10
  SELF_PIPE_BLOCK_SIZE = 11
11
11
 
12
12
  def interrupt
13
- self_pipe[:writer].write_nonblock( "." )
13
+ self_pipe[:writer].write_nonblock(".")
14
14
  rescue Errno::EAGAIN, Errno::EINTR
15
15
  # Ignore writes that would block and retry
16
16
  # if another signal arrived while writing
@@ -10,6 +10,10 @@ module SolidQueue::Processes
10
10
  attr_accessor :polling_interval
11
11
  end
12
12
 
13
+ def metadata
14
+ super.merge(polling_interval: polling_interval)
15
+ end
16
+
13
17
  private
14
18
  def run
15
19
  if mode.async?
@@ -30,7 +34,9 @@ module SolidQueue::Processes
30
34
  end
31
35
  end
32
36
  ensure
33
- run_callbacks(:shutdown) { shutdown }
37
+ SolidQueue.instrument(:shutdown_process, process: self) do
38
+ run_callbacks(:shutdown) { shutdown }
39
+ end
34
40
  end
35
41
 
36
42
  def poll
@@ -44,9 +50,5 @@ module SolidQueue::Processes
44
50
  yield
45
51
  end
46
52
  end
47
-
48
- def metadata
49
- super.merge(polling_interval: polling_interval)
50
- end
51
53
  end
52
54
  end
@@ -11,18 +11,13 @@ module SolidQueue::Processes
11
11
  after_shutdown :deregister
12
12
  end
13
13
 
14
- def inspect
15
- "#{kind}(pid=#{process_pid}, hostname=#{hostname}, metadata=#{metadata})"
16
- end
17
- alias to_s inspect
18
-
19
14
  private
20
15
  attr_accessor :process
21
16
 
22
17
  def register
23
18
  @process = SolidQueue::Process.register \
24
19
  kind: self.class.name.demodulize,
25
- pid: process_pid,
20
+ pid: pid,
26
21
  hostname: hostname,
27
22
  supervisor: try(:supervisor),
28
23
  metadata: metadata.compact
@@ -37,7 +32,10 @@ module SolidQueue::Processes
37
32
  end
38
33
 
39
34
  def launch_heartbeat
40
- @heartbeat_task = Concurrent::TimerTask.new(execution_interval: SolidQueue.process_heartbeat_interval) { heartbeat }
35
+ @heartbeat_task = Concurrent::TimerTask.new(execution_interval: SolidQueue.process_heartbeat_interval) do
36
+ wrap_in_app_executor { heartbeat }
37
+ end
38
+
41
39
  @heartbeat_task.execute
42
40
  end
43
41
 
@@ -48,21 +46,5 @@ module SolidQueue::Processes
48
46
  def heartbeat
49
47
  process.heartbeat
50
48
  end
51
-
52
- def kind
53
- self.class.name.demodulize
54
- end
55
-
56
- def hostname
57
- @hostname ||= Socket.gethostname.force_encoding(Encoding::UTF_8)
58
- end
59
-
60
- def process_pid
61
- @pid ||= ::Process.pid
62
- end
63
-
64
- def metadata
65
- {}
66
- end
67
49
  end
68
50
  end
@@ -8,7 +8,10 @@ module SolidQueue::Processes
8
8
 
9
9
  def start
10
10
  @stopping = false
11
- run_callbacks(:boot) { boot }
11
+
12
+ SolidQueue.instrument(:start_process, process: self) do
13
+ run_callbacks(:boot) { boot }
14
+ end
12
15
 
13
16
  run
14
17
  end
@@ -30,8 +33,6 @@ module SolidQueue::Processes
30
33
  register_signal_handlers
31
34
  set_procline
32
35
  end
33
-
34
- SolidQueue.logger.info("[SolidQueue] Starting #{self}")
35
36
  end
36
37
 
37
38
  def shutting_down?
@@ -38,7 +38,7 @@ module SolidQueue::Processes
38
38
  when :QUIT
39
39
  request_immediate_termination
40
40
  else
41
- SolidQueue.logger.warn "Received unhandled signal #{signal}"
41
+ SolidQueue.instrument :unhandled_signal_error, signal: signal
42
42
  end
43
43
  end
44
44
 
@@ -4,8 +4,6 @@ module SolidQueue
4
4
  class Supervisor < Processes::Base
5
5
  include Processes::Signals
6
6
 
7
- after_boot :launch_process_prune
8
-
9
7
  class << self
10
8
  def start(mode: :work, load_configuration_from: nil)
11
9
  SolidQueue.supervisor = true
@@ -23,6 +21,8 @@ module SolidQueue
23
21
  def start
24
22
  run_callbacks(:boot) { boot }
25
23
 
24
+ start_forks
25
+ launch_process_prune
26
26
  supervise
27
27
  rescue Processes::GracefulTerminationRequested
28
28
  graceful_termination
@@ -42,8 +42,6 @@ module SolidQueue
42
42
  end
43
43
 
44
44
  def supervise
45
- start_forks
46
-
47
45
  loop do
48
46
  procline "supervising #{forks.keys.join(", ")}"
49
47
 
@@ -63,15 +61,15 @@ module SolidQueue
63
61
  end
64
62
  end
65
63
 
64
+ def start_forks
65
+ configured_processes.each { |configured_process| start_fork(configured_process) }
66
+ end
67
+
66
68
  def launch_process_prune
67
69
  @prune_task = Concurrent::TimerTask.new(run_now: true, execution_interval: SolidQueue.process_alive_threshold) { prune_dead_processes }
68
70
  @prune_task.execute
69
71
  end
70
72
 
71
- def start_forks
72
- configured_processes.each { |configured_process| start_fork(configured_process) }
73
- end
74
-
75
73
  def shutdown
76
74
  stop_process_prune
77
75
  restore_default_signal_handlers
@@ -79,19 +77,24 @@ module SolidQueue
79
77
  end
80
78
 
81
79
  def graceful_termination
82
- SolidQueue.logger.info("[SolidQueue] Terminating gracefully...")
83
- term_forks
80
+ SolidQueue.instrument(:graceful_termination, supervisor_pid: ::Process.pid, supervised_pids: forks.keys) do |payload|
81
+ term_forks
84
82
 
85
- wait_until(SolidQueue.shutdown_timeout, -> { all_forks_terminated? }) do
86
- reap_terminated_forks
87
- end
83
+ wait_until(SolidQueue.shutdown_timeout, -> { all_forks_terminated? }) do
84
+ reap_terminated_forks
85
+ end
88
86
 
89
- immediate_termination unless all_forks_terminated?
87
+ unless all_forks_terminated?
88
+ payload[:shutdown_timeout_exceeded] = true
89
+ immediate_termination
90
+ end
91
+ end
90
92
  end
91
93
 
92
94
  def immediate_termination
93
- SolidQueue.logger.info("[SolidQueue] Terminating immediately...")
94
- quit_forks
95
+ SolidQueue.instrument(:immediate_termination, supervisor_pid: ::Process.pid, supervised_pids: forks.keys) do
96
+ quit_forks
97
+ end
95
98
  end
96
99
 
97
100
  def term_forks
@@ -111,9 +114,7 @@ module SolidQueue
111
114
  end
112
115
 
113
116
  def prune_dead_processes
114
- wrap_in_app_executor do
115
- SolidQueue::Process.prune
116
- end
117
+ wrap_in_app_executor { SolidQueue::Process.prune }
117
118
  end
118
119
 
119
120
  def start_fork(configured_process)
@@ -147,11 +148,11 @@ module SolidQueue
147
148
  end
148
149
 
149
150
  def replace_fork(pid, status)
150
- if supervised_fork = forks.delete(pid)
151
- SolidQueue.logger.info "[SolidQueue] Restarting fork[#{status.pid}] (status: #{status.exitstatus})"
152
- start_fork(supervised_fork)
153
- else
154
- SolidQueue.logger.info "[SolidQueue] Tried to replace fork[#{pid}] (status: #{status.exitstatus}, fork[#{status.pid}]), but it had already died (status: #{status.exitstatus})"
151
+ SolidQueue.instrument(:replace_fork, supervisor_pid: ::Process.pid, pid: pid, status: status) do |payload|
152
+ if supervised_fork = forks.delete(pid)
153
+ payload[:fork] = supervised_fork
154
+ start_fork(supervised_fork)
155
+ end
155
156
  end
156
157
  end
157
158
 
@@ -1,3 +1,3 @@
1
1
  module SolidQueue
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -14,6 +14,10 @@ module SolidQueue
14
14
  @pool = Pool.new(options[:threads], on_idle: -> { wake_up })
15
15
  end
16
16
 
17
+ def metadata
18
+ super.merge(queues: queues.join(","), thread_pool_size: pool.size)
19
+ end
20
+
17
21
  private
18
22
  def poll
19
23
  claim_executions.then do |executions|
@@ -32,10 +36,10 @@ module SolidQueue
32
36
  end
33
37
 
34
38
  def shutdown
35
- super
36
-
37
39
  pool.shutdown
38
40
  pool.wait_for_termination(SolidQueue.shutdown_timeout)
41
+
42
+ super
39
43
  end
40
44
 
41
45
  def all_work_completed?
@@ -45,9 +49,5 @@ module SolidQueue
45
49
  def set_procline
46
50
  procline "waiting for jobs in #{queues.join(",")}"
47
51
  end
48
-
49
- def metadata
50
- super.merge(queues: queues.join(","), thread_pool_size: pool.size)
51
- end
52
52
  end
53
53
  end
data/lib/solid_queue.rb CHANGED
@@ -6,6 +6,9 @@ require "solid_queue/engine"
6
6
  require "active_job"
7
7
  require "active_job/queue_adapters"
8
8
 
9
+ require "active_support"
10
+ require "active_support/core_ext/numeric/time"
11
+
9
12
  require "zeitwerk"
10
13
 
11
14
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
@@ -15,6 +18,8 @@ loader.ignore("#{__dir__}/puma")
15
18
  loader.setup
16
19
 
17
20
  module SolidQueue
21
+ extend self
22
+
18
23
  mattr_accessor :logger, default: ActiveSupport::Logger.new($stdout)
19
24
  mattr_accessor :app_executor, :on_thread_error, :connects_to
20
25
 
@@ -25,6 +30,8 @@ module SolidQueue
25
30
 
26
31
  mattr_accessor :shutdown_timeout, default: 5.seconds
27
32
 
33
+ mattr_accessor :enqueue_after_transaction_commit, default: false
34
+
28
35
  mattr_accessor :silence_polling, default: true
29
36
 
30
37
  mattr_accessor :supervisor_pidfile
@@ -34,17 +41,19 @@ module SolidQueue
34
41
  mattr_accessor :clear_finished_jobs_after, default: 1.day
35
42
  mattr_accessor :default_concurrency_control_period, default: 3.minutes
36
43
 
37
- class << self
38
- def supervisor?
39
- supervisor
40
- end
44
+ def supervisor?
45
+ supervisor
46
+ end
41
47
 
42
- def silence_polling?
43
- silence_polling
44
- end
48
+ def silence_polling?
49
+ silence_polling
50
+ end
51
+
52
+ def preserve_finished_jobs?
53
+ preserve_finished_jobs
54
+ end
45
55
 
46
- def preserve_finished_jobs?
47
- preserve_finished_jobs
48
- end
56
+ def instrument(channel, **options, &block)
57
+ ActiveSupport::Notifications.instrument("#{channel}.solid_queue", **options, &block)
49
58
  end
50
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rosa Gutierrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-20 00:00:00.000000000 Z
11
+ date: 2024-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.9.0
75
+ version: 1.10.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.9.0
82
+ version: 1.10.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: debug
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-rails-omakase
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  description: Database-backed Active Job backend.
168
182
  email:
169
183
  - rosa@37signals.com
@@ -214,6 +228,7 @@ files:
214
228
  - lib/solid_queue/dispatcher/recurring_schedule.rb
215
229
  - lib/solid_queue/dispatcher/recurring_task.rb
216
230
  - lib/solid_queue/engine.rb
231
+ - lib/solid_queue/log_subscriber.rb
217
232
  - lib/solid_queue/pool.rb
218
233
  - lib/solid_queue/processes/base.rb
219
234
  - lib/solid_queue/processes/callbacks.rb
@@ -225,19 +240,16 @@ files:
225
240
  - lib/solid_queue/processes/runnable.rb
226
241
  - lib/solid_queue/processes/signals.rb
227
242
  - lib/solid_queue/processes/supervised.rb
228
- - lib/solid_queue/recurring_tasks/manager.rb
229
- - lib/solid_queue/recurring_tasks/schedule.rb
230
- - lib/solid_queue/recurring_tasks/task.rb
231
243
  - lib/solid_queue/supervisor.rb
232
244
  - lib/solid_queue/tasks.rb
233
245
  - lib/solid_queue/version.rb
234
246
  - lib/solid_queue/worker.rb
235
- homepage: https://github.com/basecamp/solid_queue
247
+ homepage: https://github.com/rails/solid_queue
236
248
  licenses:
237
249
  - MIT
238
250
  metadata:
239
- homepage_uri: https://github.com/basecamp/solid_queue
240
- source_code_uri: https://github.com/basecamp/solid_queue
251
+ homepage_uri: https://github.com/rails/solid_queue
252
+ source_code_uri: https://github.com/rails/solid_queue
241
253
  post_install_message:
242
254
  rdoc_options: []
243
255
  require_paths:
@@ -253,7 +265,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
253
265
  - !ruby/object:Gem::Version
254
266
  version: '0'
255
267
  requirements: []
256
- rubygems_version: 3.4.10
268
+ rubygems_version: 3.5.9
257
269
  signing_key:
258
270
  specification_version: 4
259
271
  summary: Database-backed Active Job backend.
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SolidQueue
4
- module RecurringTasks
5
- class Manager < Processes::Base
6
- include Processes::Runnable
7
-
8
- attr_accessor :schedule
9
-
10
- after_boot :load_schedule
11
- before_shutdown :unload_schedule
12
-
13
- def initialize(tasks)
14
- @schedule = Schedule.new(tasks)
15
- end
16
-
17
- private
18
- def load_schedule
19
- schedule.load_tasks
20
- end
21
-
22
- def unload_schedule
23
- schedule.unload_tasks
24
- end
25
-
26
- def metadata
27
- super.merge(schedule: schedule.tasks)
28
- end
29
- end
30
- end
31
- end