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.
- checksums.yaml +4 -4
- data/README.md +14 -10
- data/app/models/solid_queue/blocked_execution.rb +16 -10
- data/app/models/solid_queue/claimed_execution.rb +11 -4
- data/app/models/solid_queue/execution/dispatching.rb +2 -3
- data/app/models/solid_queue/execution.rb +32 -15
- data/app/models/solid_queue/failed_execution.rb +10 -6
- data/app/models/solid_queue/job/executable.rb +1 -1
- data/app/models/solid_queue/job/schedulable.rb +1 -1
- data/app/models/solid_queue/process/prunable.rb +6 -5
- data/app/models/solid_queue/process.rb +13 -6
- data/app/models/solid_queue/recurring_execution.rb +3 -3
- data/app/models/solid_queue/scheduled_execution.rb +3 -1
- data/app/models/solid_queue/semaphore.rb +1 -1
- data/lib/active_job/queue_adapters/solid_queue_adapter.rb +4 -0
- data/lib/generators/solid_queue/install/templates/config.yml +1 -1
- data/lib/puma/plugin/solid_queue.rb +1 -0
- data/lib/solid_queue/app_executor.rb +1 -1
- data/lib/solid_queue/dispatcher/recurring_task.rb +13 -7
- data/lib/solid_queue/dispatcher.rb +4 -4
- data/lib/solid_queue/engine.rb +4 -2
- data/lib/solid_queue/log_subscriber.rb +164 -0
- data/lib/solid_queue/processes/base.rb +16 -0
- data/lib/solid_queue/processes/interruptible.rb +1 -1
- data/lib/solid_queue/processes/poller.rb +7 -5
- data/lib/solid_queue/processes/registrable.rb +5 -23
- data/lib/solid_queue/processes/runnable.rb +4 -3
- data/lib/solid_queue/processes/signals.rb +1 -1
- data/lib/solid_queue/supervisor.rb +25 -24
- data/lib/solid_queue/version.rb +1 -1
- data/lib/solid_queue/worker.rb +6 -6
- data/lib/solid_queue.rb +19 -10
- metadata +23 -11
- data/lib/solid_queue/recurring_tasks/manager.rb +0 -31
- data/lib/solid_queue/recurring_tasks/schedule.rb +0 -58
- 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
|
-
|
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:
|
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)
|
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
|
-
|
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?
|
@@ -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.
|
83
|
-
|
80
|
+
SolidQueue.instrument(:graceful_termination, supervisor_pid: ::Process.pid, supervised_pids: forks.keys) do |payload|
|
81
|
+
term_forks
|
84
82
|
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
wait_until(SolidQueue.shutdown_timeout, -> { all_forks_terminated? }) do
|
84
|
+
reap_terminated_forks
|
85
|
+
end
|
88
86
|
|
89
|
-
|
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.
|
94
|
-
|
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
|
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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
|
data/lib/solid_queue/version.rb
CHANGED
data/lib/solid_queue/worker.rb
CHANGED
@@ -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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
44
|
+
def supervisor?
|
45
|
+
supervisor
|
46
|
+
end
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
def silence_polling?
|
49
|
+
silence_polling
|
50
|
+
end
|
51
|
+
|
52
|
+
def preserve_finished_jobs?
|
53
|
+
preserve_finished_jobs
|
54
|
+
end
|
45
55
|
|
46
|
-
|
47
|
-
|
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.
|
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-
|
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.
|
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.
|
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/
|
247
|
+
homepage: https://github.com/rails/solid_queue
|
236
248
|
licenses:
|
237
249
|
- MIT
|
238
250
|
metadata:
|
239
|
-
homepage_uri: https://github.com/
|
240
|
-
source_code_uri: https://github.com/
|
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.
|
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
|