solid_queue 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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 +5 -3
  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 +24 -11
  33. metadata +27 -15
  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.2"
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,7 +18,11 @@ loader.ignore("#{__dir__}/puma")
15
18
  loader.setup
16
19
 
17
20
  module SolidQueue
18
- mattr_accessor :logger, default: ActiveSupport::Logger.new($stdout)
21
+ extend self
22
+
23
+ DEFAULT_LOGGER = ActiveSupport::Logger.new($stdout)
24
+
25
+ mattr_accessor :logger, default: DEFAULT_LOGGER
19
26
  mattr_accessor :app_executor, :on_thread_error, :connects_to
20
27
 
21
28
  mattr_accessor :use_skip_locked, default: true
@@ -25,6 +32,8 @@ module SolidQueue
25
32
 
26
33
  mattr_accessor :shutdown_timeout, default: 5.seconds
27
34
 
35
+ mattr_accessor :enqueue_after_transaction_commit, default: false
36
+
28
37
  mattr_accessor :silence_polling, default: true
29
38
 
30
39
  mattr_accessor :supervisor_pidfile
@@ -34,17 +43,21 @@ module SolidQueue
34
43
  mattr_accessor :clear_finished_jobs_after, default: 1.day
35
44
  mattr_accessor :default_concurrency_control_period, default: 3.minutes
36
45
 
37
- class << self
38
- def supervisor?
39
- supervisor
40
- end
46
+ def supervisor?
47
+ supervisor
48
+ end
41
49
 
42
- def silence_polling?
43
- silence_polling
44
- end
50
+ def silence_polling?
51
+ silence_polling
52
+ end
53
+
54
+ def preserve_finished_jobs?
55
+ preserve_finished_jobs
56
+ end
45
57
 
46
- def preserve_finished_jobs?
47
- preserve_finished_jobs
48
- end
58
+ def instrument(channel, **options, &block)
59
+ ActiveSupport::Notifications.instrument("#{channel}.solid_queue", **options, &block)
49
60
  end
61
+
62
+ ActiveSupport.run_load_hooks(:solid_queue, self)
50
63
  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.2
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-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -56,30 +56,30 @@ dependencies:
56
56
  name: concurrent-ruby
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 1.2.2
61
+ version: 1.3.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 1.2.2
68
+ version: 1.3.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: fugit
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.9.0
75
+ version: 1.11.0
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.11.0
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