solid_queue 1.5.1 → 1.7.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/README.md +163 -6
- data/UPGRADING.md +12 -0
- data/app/models/solid_queue/batch/callbacks.rb +50 -0
- data/app/models/solid_queue/batch/clearable.rb +23 -0
- data/app/models/solid_queue/batch/status.rb +64 -0
- data/app/models/solid_queue/batch/sweepable.rb +64 -0
- data/app/models/solid_queue/batch.rb +133 -0
- data/app/models/solid_queue/batch_execution.rb +52 -0
- data/app/models/solid_queue/claimed_execution.rb +1 -0
- data/app/models/solid_queue/failed_execution/batchable.rb +22 -0
- data/app/models/solid_queue/failed_execution.rb +1 -1
- data/app/models/solid_queue/job/batchable.rb +50 -0
- data/app/models/solid_queue/job/executable.rb +5 -1
- data/app/models/solid_queue/job.rb +11 -3
- data/lib/active_job/batch_id.rb +57 -0
- data/lib/generators/solid_queue/install/templates/db/queue_schema.rb +31 -0
- data/lib/generators/solid_queue/update/templates/db/add_batches_to_solid_queue.rb +39 -0
- data/lib/solid_queue/configuration.rb +76 -11
- data/lib/solid_queue/dispatcher/concurrency_maintenance.rb +4 -37
- data/lib/solid_queue/dispatcher/maintenance.rb +79 -0
- data/lib/solid_queue/dispatcher.rb +13 -9
- data/lib/solid_queue/engine.rb +4 -0
- data/lib/solid_queue/fiber_pool.rb +130 -0
- data/lib/solid_queue/fork_supervisor.rb +13 -4
- data/lib/solid_queue/log_subscriber.rb +16 -1
- data/lib/solid_queue/pool.rb +46 -25
- data/lib/solid_queue/processes/runnable.rb +2 -5
- data/lib/solid_queue/processes/supervised.rb +7 -0
- data/lib/solid_queue/supervisor/signals.rb +3 -0
- data/lib/solid_queue/supervisor.rb +29 -16
- data/lib/solid_queue/thread_pool.rb +28 -0
- data/lib/solid_queue/version.rb +1 -1
- data/lib/solid_queue/worker.rb +9 -3
- data/lib/solid_queue.rb +1 -0
- metadata +29 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidQueue
|
|
4
|
+
class FiberPool < Pool
|
|
5
|
+
def initialize(size, on_idle: nil)
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
@state_mutex = Mutex.new
|
|
9
|
+
@shutdown = false
|
|
10
|
+
@fatal_error = nil
|
|
11
|
+
@boot_queue = Thread::Queue.new
|
|
12
|
+
@pending_executions = Thread::Queue.new
|
|
13
|
+
@reactor_thread = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def post(execution)
|
|
17
|
+
raise_if_fatal_error!
|
|
18
|
+
raise RuntimeError, "Execution pool is shutting down" if shutdown?
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def available_capacity
|
|
24
|
+
raise_if_fatal_error!
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def shutdown
|
|
29
|
+
state_mutex.synchronize do
|
|
30
|
+
next false if @shutdown
|
|
31
|
+
|
|
32
|
+
@shutdown = true
|
|
33
|
+
end.tap do |shut_down|
|
|
34
|
+
# Wake the reactor: already-queued executions are drained before the
|
|
35
|
+
# blocked pop in +wait_for_executions+ returns nil
|
|
36
|
+
pending_executions.close if shut_down
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def shutdown?
|
|
41
|
+
state_mutex.synchronize { @shutdown }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def wait_for_termination(timeout)
|
|
45
|
+
reactor_thread&.join(timeout)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
attr_reader :boot_queue, :pending_executions, :reactor_thread, :state_mutex
|
|
50
|
+
|
|
51
|
+
def name
|
|
52
|
+
@name ||= "solid_queue-fiber-pool-#{object_id}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def schedule(execution)
|
|
56
|
+
start_reactor_if_needed
|
|
57
|
+
pending_executions << execution
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The reactor thread is started lazily, when the first execution is posted,
|
|
61
|
+
# so that the pool can be safely built before forking: in the default fork
|
|
62
|
+
# supervisor mode, workers are instantiated in the supervisor process, and
|
|
63
|
+
# a thread started there wouldn't survive the fork. The async gem is also
|
|
64
|
+
# required lazily here, so that setups without fiber workers never load it.
|
|
65
|
+
def start_reactor_if_needed
|
|
66
|
+
@reactor_thread ||= begin
|
|
67
|
+
require "async"
|
|
68
|
+
require "async/semaphore"
|
|
69
|
+
|
|
70
|
+
start_reactor.tap do
|
|
71
|
+
boot_result = boot_queue.pop
|
|
72
|
+
raise boot_result if boot_result.is_a?(Exception)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def start_reactor
|
|
78
|
+
create_thread do
|
|
79
|
+
Async do |task|
|
|
80
|
+
semaphore = Async::Semaphore.new(size, parent: task)
|
|
81
|
+
boot_queue << :ready
|
|
82
|
+
|
|
83
|
+
# The reactor exits when all in-flight execution fibers, children
|
|
84
|
+
# of this task, have finished
|
|
85
|
+
wait_for_executions(semaphore)
|
|
86
|
+
end
|
|
87
|
+
rescue Exception => error
|
|
88
|
+
register_fatal_error(error)
|
|
89
|
+
raise
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def wait_for_executions(semaphore)
|
|
94
|
+
# Thread::Queue#pop is fiber-scheduler-aware: it suspends this fiber, letting
|
|
95
|
+
# execution fibers run, and wakes the reactor when the poller thread pushes new
|
|
96
|
+
# work or closes the queue on shutdown, after which it drains any remaining
|
|
97
|
+
# executions and returns nil
|
|
98
|
+
while execution = pending_executions.pop
|
|
99
|
+
semaphore.async(execution) do |_execution_task, scheduled_execution|
|
|
100
|
+
perform_execution(scheduled_execution)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def perform_execution(execution)
|
|
106
|
+
wrap_in_app_executor { execution.perform }
|
|
107
|
+
rescue Async::Stop => error
|
|
108
|
+
handle_thread_error(error)
|
|
109
|
+
register_fatal_error(error)
|
|
110
|
+
rescue Exception => error
|
|
111
|
+
handle_thread_error(error)
|
|
112
|
+
ensure
|
|
113
|
+
restore_capacity
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def register_fatal_error(error)
|
|
117
|
+
state_mutex.synchronize do
|
|
118
|
+
@fatal_error ||= error
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
boot_queue << error if boot_queue.empty?
|
|
122
|
+
on_idle&.call
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def raise_if_fatal_error!
|
|
126
|
+
error = state_mutex.synchronize { @fatal_error }
|
|
127
|
+
raise error if error
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -57,8 +57,7 @@ module SolidQueue
|
|
|
57
57
|
terminated_fork.mark_as_reaped
|
|
58
58
|
|
|
59
59
|
if !status.exited? || status.exitstatus.to_i > 0
|
|
60
|
-
|
|
61
|
-
release_claimed_jobs_by(terminated_fork, with_error: error)
|
|
60
|
+
attempt_to_release_claimed_jobs_by(terminated_fork, status)
|
|
62
61
|
end
|
|
63
62
|
end
|
|
64
63
|
|
|
@@ -73,14 +72,24 @@ module SolidQueue
|
|
|
73
72
|
if terminated_fork = process_instances.delete(pid)
|
|
74
73
|
terminated_fork.mark_as_reaped
|
|
75
74
|
payload[:fork] = terminated_fork
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
|
|
76
|
+
attempt_to_release_claimed_jobs_by(terminated_fork, status)
|
|
78
77
|
|
|
79
78
|
start_process(configured_processes.delete(pid))
|
|
80
79
|
end
|
|
81
80
|
end
|
|
82
81
|
end
|
|
83
82
|
|
|
83
|
+
# The database may be unreachable — likely the same reason the fork
|
|
84
|
+
# terminated. Neither starting a replacement nor shutting down can depend
|
|
85
|
+
# on it: the jobs claimed by the terminated fork will be failed when its
|
|
86
|
+
# stale registration is pruned once the database is back.
|
|
87
|
+
def attempt_to_release_claimed_jobs_by(terminated_fork, status)
|
|
88
|
+
release_claimed_jobs_by(terminated_fork, with_error: Processes::ProcessExitError.new(status))
|
|
89
|
+
rescue StandardError => error
|
|
90
|
+
handle_thread_error(error)
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
def all_processes_terminated?
|
|
85
94
|
process_instances.empty?
|
|
86
95
|
end
|
|
@@ -16,7 +16,10 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def fail_many_claimed(event)
|
|
19
|
-
|
|
19
|
+
attributes = event.payload.slice(:job_ids, :process_ids)
|
|
20
|
+
attributes[:error] = formatted_error(event.payload[:error]) if event.payload[:error]
|
|
21
|
+
|
|
22
|
+
warn formatted_event(event, action: "Fail claimed jobs", **attributes)
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
def release_claimed(event)
|
|
@@ -39,6 +42,18 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
|
|
|
39
42
|
debug formatted_event(event, action: "Discard job", **event.payload.slice(:job_id, :status))
|
|
40
43
|
end
|
|
41
44
|
|
|
45
|
+
def finish_batch(event)
|
|
46
|
+
info formatted_event(event, action: "Finish batch", **event.payload.slice(:batch_id, :total_jobs, :completed_jobs, :failed_jobs))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sweep_stalled_batches(event)
|
|
50
|
+
debug formatted_event(event, action: "Sweep stalled batches", **event.payload.slice(:stale_executions, :finished_batches, :started_batches))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def batch_progress_error(event)
|
|
54
|
+
error formatted_event(event, action: "Error updating batch progress", **event.payload.slice(:batch_id, :job_id), error: formatted_error(event.payload[:error]))
|
|
55
|
+
end
|
|
56
|
+
|
|
42
57
|
def release_many_blocked(event)
|
|
43
58
|
debug formatted_event(event, action: "Unblock jobs", **event.payload.slice(:limit, :size))
|
|
44
59
|
end
|
data/lib/solid_queue/pool.rb
CHANGED
|
@@ -4,51 +4,72 @@ module SolidQueue
|
|
|
4
4
|
class Pool
|
|
5
5
|
include AppExecutor
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
def self.build(type:, size:, on_idle: nil)
|
|
8
|
+
SolidQueue.const_get("#{type.to_s.camelize}Pool").new(size, on_idle: on_idle)
|
|
9
|
+
end
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
attr_reader :size
|
|
10
12
|
|
|
11
13
|
def initialize(size, on_idle: nil)
|
|
12
14
|
@size = size
|
|
13
15
|
@on_idle = on_idle
|
|
14
|
-
@
|
|
16
|
+
@available_capacity = size
|
|
15
17
|
@mutex = Mutex.new
|
|
16
18
|
end
|
|
17
19
|
|
|
20
|
+
def type
|
|
21
|
+
self.class.name.demodulize.delete_suffix("Pool").underscore.to_sym
|
|
22
|
+
end
|
|
23
|
+
|
|
18
24
|
def post(execution)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mutex.synchronize { on_idle.try(:call) if idle? }
|
|
27
|
-
end
|
|
28
|
-
end.on_rejection! do |e|
|
|
29
|
-
handle_thread_error(e)
|
|
25
|
+
reserve_capacity!
|
|
26
|
+
|
|
27
|
+
begin
|
|
28
|
+
schedule(execution)
|
|
29
|
+
rescue Exception
|
|
30
|
+
restore_capacity
|
|
31
|
+
raise
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
+
def available_capacity
|
|
36
|
+
mutex.synchronize { @available_capacity }
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def idle?
|
|
38
|
-
|
|
40
|
+
available_capacity.positive?
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
private
|
|
42
|
-
attr_reader :
|
|
44
|
+
attr_reader :mutex, :on_idle
|
|
45
|
+
|
|
46
|
+
def schedule(execution)
|
|
47
|
+
raise NotImplementedError
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def perform_execution(execution)
|
|
51
|
+
wrap_in_app_executor { execution.perform }
|
|
52
|
+
rescue Exception => error
|
|
53
|
+
handle_thread_error(error)
|
|
54
|
+
ensure
|
|
55
|
+
restore_capacity
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def reserve_capacity!
|
|
59
|
+
mutex.synchronize do
|
|
60
|
+
raise RuntimeError, "Execution pool is at capacity" if @available_capacity <= 0
|
|
43
61
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
@available_capacity -= 1
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def restore_capacity
|
|
67
|
+
should_notify = mutex.synchronize do
|
|
68
|
+
@available_capacity += 1
|
|
69
|
+
@available_capacity.positive?
|
|
70
|
+
end
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
@executor ||= Concurrent::ThreadPoolExecutor.new DEFAULT_OPTIONS.merge(max_threads: size, max_queue: size)
|
|
72
|
+
on_idle&.call if should_notify
|
|
52
73
|
end
|
|
53
74
|
end
|
|
54
75
|
end
|
|
@@ -50,7 +50,7 @@ module SolidQueue::Processes
|
|
|
50
50
|
case
|
|
51
51
|
when running_as_fork?
|
|
52
52
|
@boot_guard = BootGuards::ForkGuard.new
|
|
53
|
-
|
|
53
|
+
create_fork(&block).tap { @boot_guard.start }
|
|
54
54
|
when running_async?
|
|
55
55
|
@boot_guard = BootGuards::NullGuard.new
|
|
56
56
|
@thread = create_thread(&block)
|
|
@@ -64,10 +64,7 @@ module SolidQueue::Processes
|
|
|
64
64
|
def boot
|
|
65
65
|
SolidQueue.instrument(:start_process, process: self) do
|
|
66
66
|
run_callbacks(:boot) do
|
|
67
|
-
if running_as_fork?
|
|
68
|
-
register_signal_handlers
|
|
69
|
-
set_procline
|
|
70
|
-
end
|
|
67
|
+
set_procline if running_as_fork?
|
|
71
68
|
end
|
|
72
69
|
end
|
|
73
70
|
|
|
@@ -39,9 +39,13 @@ module SolidQueue
|
|
|
39
39
|
run_start_hooks
|
|
40
40
|
|
|
41
41
|
start_processes
|
|
42
|
-
launch_maintenance_task
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
if stopped?
|
|
44
|
+
shutdown
|
|
45
|
+
else
|
|
46
|
+
launch_maintenance_task
|
|
47
|
+
supervise
|
|
48
|
+
end
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
def stop
|
|
@@ -65,27 +69,33 @@ module SolidQueue
|
|
|
65
69
|
end
|
|
66
70
|
|
|
67
71
|
def start_processes
|
|
68
|
-
configuration.configured_processes.each
|
|
72
|
+
configuration.configured_processes.each do |configured_process|
|
|
73
|
+
# Honour signals that arrive during boot or start hooks: a queued TERM
|
|
74
|
+
# stops us here, before starting children, instead of in #supervise,
|
|
75
|
+
# after all of them have been started
|
|
76
|
+
break if time_to_stop?
|
|
77
|
+
|
|
78
|
+
start_process(configured_process)
|
|
79
|
+
end
|
|
69
80
|
end
|
|
70
81
|
|
|
71
82
|
def supervise
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
set_procline
|
|
77
|
-
process_signal_queue
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
unless stopped?
|
|
81
|
-
check_and_replace_terminated_processes
|
|
82
|
-
interruptible_sleep(1.second)
|
|
83
|
-
end
|
|
83
|
+
until time_to_stop?
|
|
84
|
+
set_procline
|
|
85
|
+
check_and_replace_terminated_processes
|
|
86
|
+
interruptible_sleep(1.second)
|
|
84
87
|
end
|
|
85
88
|
ensure
|
|
86
89
|
shutdown
|
|
87
90
|
end
|
|
88
91
|
|
|
92
|
+
# Process any signals queued while we were busy and report whether
|
|
93
|
+
# we've been asked to stop
|
|
94
|
+
def time_to_stop?
|
|
95
|
+
process_signal_queue
|
|
96
|
+
stopped?
|
|
97
|
+
end
|
|
98
|
+
|
|
89
99
|
def start_process(configured_process)
|
|
90
100
|
process_instance = configured_process.instantiate.tap do |instance|
|
|
91
101
|
instance.supervised_by process
|
|
@@ -139,7 +149,10 @@ module SolidQueue
|
|
|
139
149
|
end
|
|
140
150
|
|
|
141
151
|
def set_procline
|
|
142
|
-
|
|
152
|
+
# Embedded supervisors don't own their process's title
|
|
153
|
+
if standalone?
|
|
154
|
+
procline "supervising #{configured_processes.keys.join(", ")}"
|
|
155
|
+
end
|
|
143
156
|
end
|
|
144
157
|
|
|
145
158
|
def sync_std_streams
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidQueue
|
|
4
|
+
class ThreadPool < Pool
|
|
5
|
+
delegate :shutdown, :shutdown?, :wait_for_termination, to: :executor
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
DEFAULT_OPTIONS = {
|
|
9
|
+
min_threads: 0,
|
|
10
|
+
idletime: 60,
|
|
11
|
+
fallback_policy: :abort
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def schedule(execution)
|
|
15
|
+
Concurrent::Promises.future_on(executor, execution) do |thread_execution|
|
|
16
|
+
perform_execution(thread_execution)
|
|
17
|
+
end.on_rejection! do |error|
|
|
18
|
+
# Backstop for errors raised outside perform_execution's own rescue,
|
|
19
|
+
# such as when restoring capacity or waking up the worker
|
|
20
|
+
handle_thread_error(error)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def executor
|
|
25
|
+
@executor ||= Concurrent::ThreadPoolExecutor.new DEFAULT_OPTIONS.merge(max_threads: size, max_queue: size)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/solid_queue/version.rb
CHANGED
data/lib/solid_queue/worker.rb
CHANGED
|
@@ -11,18 +11,24 @@ module SolidQueue
|
|
|
11
11
|
attr_reader :queues, :pool
|
|
12
12
|
|
|
13
13
|
def initialize(**options)
|
|
14
|
+
execution_pool_type = options.key?(:fibers) ? :fiber : :thread
|
|
15
|
+
|
|
14
16
|
options = options.dup.with_defaults(SolidQueue::Configuration::WORKER_DEFAULTS)
|
|
17
|
+
execution_pool_size = execution_pool_type == :fiber ? options[:fibers] : options[:threads]
|
|
15
18
|
|
|
16
19
|
# Ensure that the queues array is deep frozen to prevent accidental modification
|
|
17
20
|
@queues = Array(options[:queues]).map(&:freeze).freeze
|
|
18
21
|
|
|
19
|
-
@pool = Pool.
|
|
22
|
+
@pool = Pool.build \
|
|
23
|
+
type: execution_pool_type,
|
|
24
|
+
size: execution_pool_size,
|
|
25
|
+
on_idle: -> { wake_up }
|
|
20
26
|
|
|
21
27
|
super(**options)
|
|
22
28
|
end
|
|
23
29
|
|
|
24
30
|
def metadata
|
|
25
|
-
super.merge(queues: queues.join(","),
|
|
31
|
+
super.merge(queues: queues.join(","), pool_type: pool.type, pool_size: pool.size)
|
|
26
32
|
end
|
|
27
33
|
|
|
28
34
|
private
|
|
@@ -38,7 +44,7 @@ module SolidQueue
|
|
|
38
44
|
|
|
39
45
|
def claim_executions
|
|
40
46
|
with_polling_volume do
|
|
41
|
-
SolidQueue::ReadyExecution.claim(queues, pool.
|
|
47
|
+
SolidQueue::ReadyExecution.claim(queues, pool.available_capacity, process_id)
|
|
42
48
|
end
|
|
43
49
|
end
|
|
44
50
|
|
data/lib/solid_queue.rb
CHANGED
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: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rosa Gutierrez
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -122,6 +122,20 @@ dependencies:
|
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '1.9'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: async
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '2.24'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '2.24'
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
140
|
name: minitest
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -273,13 +287,21 @@ files:
|
|
|
273
287
|
- README.md
|
|
274
288
|
- UPGRADING.md
|
|
275
289
|
- app/jobs/solid_queue/recurring_job.rb
|
|
290
|
+
- app/models/solid_queue/batch.rb
|
|
291
|
+
- app/models/solid_queue/batch/callbacks.rb
|
|
292
|
+
- app/models/solid_queue/batch/clearable.rb
|
|
293
|
+
- app/models/solid_queue/batch/status.rb
|
|
294
|
+
- app/models/solid_queue/batch/sweepable.rb
|
|
295
|
+
- app/models/solid_queue/batch_execution.rb
|
|
276
296
|
- app/models/solid_queue/blocked_execution.rb
|
|
277
297
|
- app/models/solid_queue/claimed_execution.rb
|
|
278
298
|
- app/models/solid_queue/execution.rb
|
|
279
299
|
- app/models/solid_queue/execution/dispatching.rb
|
|
280
300
|
- app/models/solid_queue/execution/job_attributes.rb
|
|
281
301
|
- app/models/solid_queue/failed_execution.rb
|
|
302
|
+
- app/models/solid_queue/failed_execution/batchable.rb
|
|
282
303
|
- app/models/solid_queue/job.rb
|
|
304
|
+
- app/models/solid_queue/job/batchable.rb
|
|
283
305
|
- app/models/solid_queue/job/clearable.rb
|
|
284
306
|
- app/models/solid_queue/job/concurrency_controls.rb
|
|
285
307
|
- app/models/solid_queue/job/executable.rb
|
|
@@ -301,6 +323,7 @@ files:
|
|
|
301
323
|
- app/models/solid_queue/scheduled_execution.rb
|
|
302
324
|
- app/models/solid_queue/semaphore.rb
|
|
303
325
|
- config/routes.rb
|
|
326
|
+
- lib/active_job/batch_id.rb
|
|
304
327
|
- lib/active_job/concurrency_controls.rb
|
|
305
328
|
- lib/active_job/queue_adapters/solid_queue_adapter.rb
|
|
306
329
|
- lib/generators/solid_queue/install/USAGE
|
|
@@ -309,6 +332,7 @@ files:
|
|
|
309
332
|
- lib/generators/solid_queue/install/templates/config/queue.yml
|
|
310
333
|
- lib/generators/solid_queue/install/templates/config/recurring.yml
|
|
311
334
|
- lib/generators/solid_queue/install/templates/db/queue_schema.rb
|
|
335
|
+
- lib/generators/solid_queue/update/templates/db/add_batches_to_solid_queue.rb
|
|
312
336
|
- lib/generators/solid_queue/update/update_generator.rb
|
|
313
337
|
- lib/puma/plugin/solid_queue.rb
|
|
314
338
|
- lib/solid_queue.rb
|
|
@@ -318,7 +342,9 @@ files:
|
|
|
318
342
|
- lib/solid_queue/configuration.rb
|
|
319
343
|
- lib/solid_queue/dispatcher.rb
|
|
320
344
|
- lib/solid_queue/dispatcher/concurrency_maintenance.rb
|
|
345
|
+
- lib/solid_queue/dispatcher/maintenance.rb
|
|
321
346
|
- lib/solid_queue/engine.rb
|
|
347
|
+
- lib/solid_queue/fiber_pool.rb
|
|
322
348
|
- lib/solid_queue/fork_supervisor.rb
|
|
323
349
|
- lib/solid_queue/lifecycle_hooks.rb
|
|
324
350
|
- lib/solid_queue/log_subscriber.rb
|
|
@@ -343,6 +369,7 @@ files:
|
|
|
343
369
|
- lib/solid_queue/supervisor/pidfiled.rb
|
|
344
370
|
- lib/solid_queue/supervisor/signals.rb
|
|
345
371
|
- lib/solid_queue/tasks.rb
|
|
372
|
+
- lib/solid_queue/thread_pool.rb
|
|
346
373
|
- lib/solid_queue/timer.rb
|
|
347
374
|
- lib/solid_queue/version.rb
|
|
348
375
|
- lib/solid_queue/worker.rb
|