solid_queue 0.3.2 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +56 -8
- data/app/models/solid_queue/claimed_execution.rb +2 -0
- data/app/models/solid_queue/failed_execution.rb +38 -1
- data/app/models/solid_queue/job/executable.rb +1 -11
- data/app/models/solid_queue/job/retryable.rb +29 -0
- data/app/models/solid_queue/job.rb +7 -0
- data/app/models/solid_queue/ready_execution.rb +8 -7
- data/app/models/solid_queue/recurring_execution.rb +7 -3
- data/lib/puma/plugin/solid_queue.rb +11 -5
- data/lib/solid_queue/dispatcher/recurring_schedule.rb +4 -0
- data/lib/solid_queue/dispatcher/recurring_task.rb +14 -6
- data/lib/solid_queue/dispatcher.rb +4 -0
- data/lib/solid_queue/log_subscriber.rb +9 -3
- data/lib/solid_queue/processes/poller.rb +1 -1
- data/lib/solid_queue/supervisor.rb +13 -5
- data/lib/solid_queue/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4a85fb424e127543352846ee1b0b4aa958d4c77a7a9e1c26a8082464ae7bebc
|
4
|
+
data.tar.gz: f15b4db5c77c14af4b989fc8abe2670fd49006853ca9bfce0080e8b15df733c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba913d760e6f1ac8bac01f68b3ffeb61811952d13a7862731c517dea0ec3e8938b8fb5194113e356fe8a35a02f4d95b306f327772e21f8f6098349bd1235dc53
|
7
|
+
data.tar.gz: 7418c2db5be34b59e123395ee3edf519d703b6e0488a564a85c24dc22344d67e894ad8bb378f88a3cd6e0b9085602be1850dab60c168816e92b081364b720594
|
data/README.md
CHANGED
@@ -145,6 +145,56 @@ When receiving a `QUIT` signal, if workers still have jobs in-flight, these will
|
|
145
145
|
|
146
146
|
If processes have no chance of cleaning up before exiting (e.g. if someone pulls a cable somewhere), in-flight jobs might remain claimed by the processes executing them. Processes send heartbeats, and the supervisor checks and prunes processes with expired heartbeats, which will release any claimed jobs back to their queues. You can configure both the frequency of heartbeats and the threshold to consider a process dead. See the section below for this.
|
147
147
|
|
148
|
+
|
149
|
+
### Dedicated database configuration
|
150
|
+
|
151
|
+
Solid Queue can be configured to run on a different database than the main application.
|
152
|
+
|
153
|
+
Configure the `connects_to` option in `config/application.rb` or your environment config, with the custom database configuration that will be used in the abstract `SolidQueue::Record` Active Record model.
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# Use a separate DB for Solid Queue
|
157
|
+
config.solid_queue.connects_to = { database: { writing: :solid_queue_primary, reading: :solid_queue_replica } }
|
158
|
+
```
|
159
|
+
|
160
|
+
Add the dedicated database configuration to `config/database.yml`, differentiating between the main app's database and the dedicated `solid_queue` database. Make sure to include the `migrations_paths` for the solid queue database. This is where migration files for Solid Queue tables will reside.
|
161
|
+
|
162
|
+
```yml
|
163
|
+
default: &default
|
164
|
+
adapter: sqlite3
|
165
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
166
|
+
timeout: 5000
|
167
|
+
|
168
|
+
solid_queue: &solid_queue
|
169
|
+
<<: *default
|
170
|
+
migrations_paths: db/solid_queue_migrate
|
171
|
+
|
172
|
+
development:
|
173
|
+
primary:
|
174
|
+
<<: *default
|
175
|
+
# ...
|
176
|
+
solid_queue_primary:
|
177
|
+
<<: *solid_queue
|
178
|
+
# ...
|
179
|
+
solid_queue_replica:
|
180
|
+
<<: *solid_queue
|
181
|
+
# ...
|
182
|
+
```
|
183
|
+
|
184
|
+
Install migrations and specify the dedicated database name with the `DATABASE` option. This will create the Solid Queue migration files in a separate directory, matching the value provided in `migrations_paths` in `config/database.yml`.
|
185
|
+
|
186
|
+
```bash
|
187
|
+
$ bin/rails solid_queue:install:migrations DATABASE=solid_queue
|
188
|
+
```
|
189
|
+
|
190
|
+
Note: If you've already run the solid queue install command (`bin/rails generate solid_queue:install`), the migration files will have already been generated under the primary database's `db/migrate/` directory. You can remove these files and keep the ones generated by the database-specific migration installation above.
|
191
|
+
|
192
|
+
Finally, run the migrations:
|
193
|
+
|
194
|
+
```bash
|
195
|
+
$ bin/rails db:migrate
|
196
|
+
```
|
197
|
+
|
148
198
|
### Other configuration settings
|
149
199
|
_Note_: The settings in this section should be set in your `config/application.rb` or your environment config like this: `config.solid_queue.silence_polling = true`
|
150
200
|
|
@@ -156,12 +206,6 @@ There are several settings that control how Solid Queue works that you can set a
|
|
156
206
|
```ruby
|
157
207
|
-> (exception) { Rails.error.report(exception, handled: false) }
|
158
208
|
```
|
159
|
-
- `connects_to`: a custom database configuration that will be used in the abstract `SolidQueue::Record` Active Record model. This is required to use a different database than the main app. For example:
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
# Use a separate DB for Solid Queue
|
163
|
-
config.solid_queue.connects_to = { database: { writing: :solid_queue_primary, reading: :solid_queue_replica } }
|
164
|
-
```
|
165
209
|
- `use_skip_locked`: whether to use `FOR UPDATE SKIP LOCKED` when performing locking reads. This will be automatically detected in the future, and for now, you'd only need to set this to `false` if your database doesn't support it. For MySQL, that'd be versions < 8, and for PostgreSQL, versions < 9.5. If you use SQLite, this has no effect, as writes are sequential.
|
166
210
|
- `process_heartbeat_interval`: the heartbeat interval that all processes will follow—defaults to 60 seconds.
|
167
211
|
- `process_alive_threshold`: how long to wait until a process is considered dead after its last heartbeat—defaults to 5 minutes.
|
@@ -173,6 +217,10 @@ There are several settings that control how Solid Queue works that you can set a
|
|
173
217
|
- `default_concurrency_control_period`: the value to be used as the default for the `duration` parameter in [concurrency controls](#concurrency-controls). It defaults to 3 minutes.
|
174
218
|
- `enqueue_after_transaction_commit`: whether the job queuing is deferred to after the current Active Record transaction is committed. The default is `false`. [Read more](https://github.com/rails/rails/pull/51426).
|
175
219
|
|
220
|
+
## Errors when enqueuing
|
221
|
+
Solid Queue will raise a `SolidQueue::Job::EnqueueError` for any Active Record errors that happen when enqueuing a job. The reason for not raising `ActiveJob::EnqueueError` is that this one gets handled by Active Job, causing `perform_later` to return `false` and set `job.enqueue_error`, yielding the job to a block that you need to pass to `perform_later`. This works very well for your own jobs, but makes failure very hard to handle for jobs enqueued by Rails or other gems, such as `Turbo::Streams::BroadcastJob` or `ActiveStorage::AnalyzeJob`, because you don't control the call to `perform_later` in that cases.
|
222
|
+
|
223
|
+
In the case of recurring tasks, if such error is raised when enqueuing the job corresponding to the task, it'll be handled and logged but it won't bubble up.
|
176
224
|
|
177
225
|
## Concurrency controls
|
178
226
|
Solid Queue extends Active Job with concurrency controls, that allows you to limit how many jobs of a certain type or with certain arguments can run at the same time. When limited in this way, jobs will be blocked from running, and they'll stay blocked until another job finishes and unblocks them, or after the set expiry time (concurrency limit's _duration_) elapses. Jobs are never discarded or lost, only blocked.
|
@@ -252,7 +300,7 @@ By default, Solid Queue runs in the same DB as your app, and job enqueuing is _n
|
|
252
300
|
If you prefer not to rely on this, or avoid relying on it unintentionally, you should make sure that:
|
253
301
|
- You set [`config.active_job.enqueue_after_transaction_commit`](https://edgeguides.rubyonrails.org/configuring.html#config-active-job-enqueue-after-transaction-commit) to `always`, if you're using Rails 7.2+.
|
254
302
|
- Or, your jobs relying on specific records are always enqueued on [`after_commit` callbacks](https://guides.rubyonrails.org/active_record_callbacks.html#after-commit-and-after-rollback) or otherwise from a place where you're certain that whatever data the job will use has been committed to the database before the job is enqueued.
|
255
|
-
- Or, you configure a database for Solid Queue, even if it's the same as your app, ensuring that a different connection on the thread handling requests or running jobs for your app will be used to enqueue jobs. For example:
|
303
|
+
- Or, you configure a different database for Solid Queue, even if it's the same as your app, ensuring that a different connection on the thread handling requests or running jobs for your app will be used to enqueue jobs. For example:
|
256
304
|
|
257
305
|
```ruby
|
258
306
|
class ApplicationRecord < ActiveRecord::Base
|
@@ -288,7 +336,7 @@ Tasks are enqueued at their corresponding times by the dispatcher that owns them
|
|
288
336
|
|
289
337
|
It's possible to run multiple dispatchers with the same `recurring_tasks` configuration. To avoid enqueuing duplicate tasks at the same time, an entry in a new `solid_queue_recurring_executions` table is created in the same transaction as the job is enqueued. This table has a unique index on `task_key` and `run_at`, ensuring only one entry per task per time will be created. This only works if you have `preserve_finished_jobs` set to `true` (the default), and the guarantee applies as long as you keep the jobs around.
|
290
338
|
|
291
|
-
Finally, it's possible to configure jobs that aren't handled by Solid Queue. That
|
339
|
+
Finally, it's possible to configure jobs that aren't handled by Solid Queue. That is, you can have a job like this in your app:
|
292
340
|
```ruby
|
293
341
|
class MyResqueJob < ApplicationJob
|
294
342
|
self.queue_adapter = :resque
|
@@ -21,6 +21,7 @@ module SolidQueue
|
|
21
21
|
def retry
|
22
22
|
SolidQueue.instrument(:retry, job_id: job.id) do
|
23
23
|
with_lock do
|
24
|
+
job.reset_execution_counters
|
24
25
|
job.prepare_for_execution
|
25
26
|
destroy!
|
26
27
|
end
|
@@ -32,9 +33,45 @@ module SolidQueue
|
|
32
33
|
end
|
33
34
|
|
34
35
|
private
|
36
|
+
JSON_OVERHEAD = 256
|
37
|
+
|
35
38
|
def expand_error_details_from_exception
|
36
39
|
if exception
|
37
|
-
self.error = { exception_class:
|
40
|
+
self.error = { exception_class: exception_class_name, message: exception_message, backtrace: exception_backtrace }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def exception_class_name
|
45
|
+
exception.class.name
|
46
|
+
end
|
47
|
+
|
48
|
+
def exception_message
|
49
|
+
exception.message
|
50
|
+
end
|
51
|
+
|
52
|
+
def exception_backtrace
|
53
|
+
if (limit = determine_backtrace_size_limit) && exception.backtrace.to_json.bytesize > limit
|
54
|
+
truncate_backtrace(exception.backtrace, limit)
|
55
|
+
else
|
56
|
+
exception.backtrace
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def determine_backtrace_size_limit
|
61
|
+
column = self.class.connection.schema_cache.columns_hash(self.class.table_name)["error"]
|
62
|
+
if column.limit.present?
|
63
|
+
column.limit - exception_class_name.bytesize - exception_message.bytesize - JSON_OVERHEAD
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def truncate_backtrace(lines, limit)
|
68
|
+
[].tap do |truncated_backtrace|
|
69
|
+
lines.each do |line|
|
70
|
+
if (truncated_backtrace << line).to_json.bytesize > limit
|
71
|
+
truncated_backtrace.pop
|
72
|
+
break
|
73
|
+
end
|
74
|
+
end
|
38
75
|
end
|
39
76
|
end
|
40
77
|
end
|
@@ -6,16 +6,14 @@ module SolidQueue
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
include ConcurrencyControls, Schedulable
|
9
|
+
include ConcurrencyControls, Schedulable, Retryable
|
10
10
|
|
11
11
|
has_one :ready_execution
|
12
12
|
has_one :claimed_execution
|
13
|
-
has_one :failed_execution
|
14
13
|
|
15
14
|
after_create :prepare_for_execution
|
16
15
|
|
17
16
|
scope :finished, -> { where.not(finished_at: nil) }
|
18
|
-
scope :failed, -> { includes(:failed_execution).where.not(failed_execution: { id: nil }) }
|
19
17
|
end
|
20
18
|
|
21
19
|
class_methods do
|
@@ -97,18 +95,10 @@ module SolidQueue
|
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
|
-
def retry
|
101
|
-
failed_execution&.retry
|
102
|
-
end
|
103
|
-
|
104
98
|
def discard
|
105
99
|
execution&.discard
|
106
100
|
end
|
107
101
|
|
108
|
-
def failed_with(exception)
|
109
|
-
FailedExecution.create_or_find_by!(job_id: id, exception: exception)
|
110
|
-
end
|
111
|
-
|
112
102
|
private
|
113
103
|
def ready
|
114
104
|
ReadyExecution.create_or_find_by!(job_id: id)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidQueue
|
4
|
+
class Job
|
5
|
+
module Retryable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_one :failed_execution
|
10
|
+
|
11
|
+
scope :failed, -> { includes(:failed_execution).where.not(failed_execution: { id: nil }) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def retry
|
15
|
+
failed_execution&.retry
|
16
|
+
end
|
17
|
+
|
18
|
+
def failed_with(exception)
|
19
|
+
FailedExecution.create_or_find_by!(job_id: id, exception: exception)
|
20
|
+
end
|
21
|
+
|
22
|
+
def reset_execution_counters
|
23
|
+
arguments["executions"] = 0
|
24
|
+
arguments["exception_executions"] = {}
|
25
|
+
save!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module SolidQueue
|
4
4
|
class Job < Record
|
5
|
+
class EnqueueError < StandardError; end
|
6
|
+
|
5
7
|
include Executable, Clearable, Recurrable
|
6
8
|
|
7
9
|
serialize :arguments, coder: JSON
|
@@ -37,6 +39,11 @@ module SolidQueue
|
|
37
39
|
|
38
40
|
def create_from_active_job(active_job)
|
39
41
|
create!(**attributes_from_active_job(active_job))
|
42
|
+
rescue ActiveRecord::ActiveRecordError => e
|
43
|
+
enqueue_error = EnqueueError.new("#{e.class.name}: #{e.message}").tap do |error|
|
44
|
+
error.set_backtrace e.backtrace
|
45
|
+
end
|
46
|
+
raise enqueue_error
|
40
47
|
end
|
41
48
|
|
42
49
|
def create_all_from_active_jobs(active_jobs)
|
@@ -24,20 +24,21 @@ module SolidQueue
|
|
24
24
|
return [] if limit <= 0
|
25
25
|
|
26
26
|
transaction do
|
27
|
-
|
28
|
-
lock_candidates(
|
27
|
+
candidates = select_candidates(queue_relation, limit)
|
28
|
+
lock_candidates(candidates, process_id)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def select_candidates(queue_relation, limit)
|
33
|
-
queue_relation.ordered.limit(limit).non_blocking_lock.
|
33
|
+
queue_relation.ordered.limit(limit).non_blocking_lock.select(:id, :job_id)
|
34
34
|
end
|
35
35
|
|
36
|
-
def lock_candidates(
|
37
|
-
return [] if
|
36
|
+
def lock_candidates(executions, process_id)
|
37
|
+
return [] if executions.none?
|
38
38
|
|
39
|
-
SolidQueue::ClaimedExecution.claiming(
|
40
|
-
|
39
|
+
SolidQueue::ClaimedExecution.claiming(executions.map(&:job_id), process_id) do |claimed|
|
40
|
+
ids_to_delete = executions.index_by(&:job_id).values_at(*claimed.map(&:job_id)).map(&:id)
|
41
|
+
where(id: ids_to_delete).delete_all
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
@@ -2,17 +2,21 @@
|
|
2
2
|
|
3
3
|
module SolidQueue
|
4
4
|
class RecurringExecution < Execution
|
5
|
+
class AlreadyRecorded < StandardError; end
|
6
|
+
|
5
7
|
scope :clearable, -> { where.missing(:job) }
|
6
8
|
|
7
9
|
class << self
|
8
10
|
def record(task_key, run_at, &block)
|
9
11
|
transaction do
|
10
12
|
block.call.tap do |active_job|
|
11
|
-
|
13
|
+
if active_job
|
14
|
+
create!(job_id: active_job.provider_job_id, task_key: task_key, run_at: run_at)
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
|
-
rescue ActiveRecord::RecordNotUnique
|
15
|
-
|
18
|
+
rescue ActiveRecord::RecordNotUnique => e
|
19
|
+
raise AlreadyRecorded
|
16
20
|
end
|
17
21
|
|
18
22
|
def clear_in_batches(batch_size: 500)
|
@@ -7,15 +7,15 @@ Puma::Plugin.create do
|
|
7
7
|
@log_writer = launcher.log_writer
|
8
8
|
@puma_pid = $$
|
9
9
|
|
10
|
+
in_background do
|
11
|
+
monitor_solid_queue
|
12
|
+
end
|
13
|
+
|
10
14
|
launcher.events.on_booted do
|
11
15
|
@solid_queue_pid = fork do
|
12
16
|
Thread.new { monitor_puma }
|
13
17
|
SolidQueue::Supervisor.start(mode: :all)
|
14
18
|
end
|
15
|
-
|
16
|
-
in_background do
|
17
|
-
monitor_solid_queue
|
18
|
-
end
|
19
19
|
end
|
20
20
|
|
21
21
|
launcher.events.on_stopped { stop_solid_queue }
|
@@ -51,12 +51,18 @@ Puma::Plugin.create do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def solid_queue_dead?
|
54
|
-
|
54
|
+
if solid_queue_started?
|
55
|
+
Process.waitpid(solid_queue_pid, Process::WNOHANG)
|
56
|
+
end
|
55
57
|
false
|
56
58
|
rescue Errno::ECHILD, Errno::ESRCH
|
57
59
|
true
|
58
60
|
end
|
59
61
|
|
62
|
+
def solid_queue_started?
|
63
|
+
solid_queue_pid.present?
|
64
|
+
end
|
65
|
+
|
60
66
|
def puma_dead?
|
61
67
|
Process.ppid != puma_pid
|
62
68
|
end
|
@@ -31,15 +31,23 @@ module SolidQueue
|
|
31
31
|
|
32
32
|
def enqueue(at:)
|
33
33
|
SolidQueue.instrument(:enqueue_recurring_task, task: key, at: at) do |payload|
|
34
|
-
if using_solid_queue_adapter?
|
34
|
+
active_job = if using_solid_queue_adapter?
|
35
35
|
perform_later_and_record(run_at: at)
|
36
36
|
else
|
37
37
|
payload[:other_adapter] = true
|
38
38
|
|
39
|
-
perform_later
|
40
|
-
|
41
|
-
|
39
|
+
perform_later do |job|
|
40
|
+
unless job.successfully_enqueued?
|
41
|
+
payload[:enqueue_error] = job.enqueue_error&.message
|
42
|
+
end
|
43
|
+
end
|
42
44
|
end
|
45
|
+
|
46
|
+
payload[:active_job_id] = active_job.job_id if active_job
|
47
|
+
rescue RecurringExecution::AlreadyRecorded
|
48
|
+
payload[:skipped] = true
|
49
|
+
rescue Job::EnqueueError => error
|
50
|
+
payload[:enqueue_error] = error.message
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
@@ -68,8 +76,8 @@ module SolidQueue
|
|
68
76
|
RecurringExecution.record(key, run_at) { perform_later }
|
69
77
|
end
|
70
78
|
|
71
|
-
def perform_later
|
72
|
-
job_class.perform_later(*arguments_with_kwargs)
|
79
|
+
def perform_later(&block)
|
80
|
+
job_class.perform_later(*arguments_with_kwargs, &block)
|
73
81
|
end
|
74
82
|
|
75
83
|
def arguments_with_kwargs
|
@@ -40,12 +40,18 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def enqueue_recurring_task(event)
|
43
|
-
attributes = event.payload.slice(:task, :
|
43
|
+
attributes = event.payload.slice(:task, :active_job_id, :enqueue_error, :at)
|
44
44
|
|
45
45
|
if event.payload[:other_adapter]
|
46
|
-
|
46
|
+
action = attributes[:active_job_id].present? ? "Enqueued recurring task outside Solid Queue" : "Error enqueuing recurring task"
|
47
|
+
info formatted_event(event, action: action, **attributes)
|
47
48
|
else
|
48
|
-
action =
|
49
|
+
action = case
|
50
|
+
when event.payload[:skipped].present? then "Skipped recurring task – already dispatched"
|
51
|
+
when attributes[:active_job_id].nil? then "Error enqueuing recurring task"
|
52
|
+
else "Enqueued recurring task"
|
53
|
+
end
|
54
|
+
|
49
55
|
info formatted_event(event, action: action, **attributes)
|
50
56
|
end
|
51
57
|
end
|
@@ -22,7 +22,8 @@ module SolidQueue
|
|
22
22
|
run_callbacks(:boot) { boot }
|
23
23
|
|
24
24
|
start_forks
|
25
|
-
|
25
|
+
launch_maintenance_task
|
26
|
+
|
26
27
|
supervise
|
27
28
|
rescue Processes::GracefulTerminationRequested
|
28
29
|
graceful_termination
|
@@ -65,9 +66,12 @@ module SolidQueue
|
|
65
66
|
configured_processes.each { |configured_process| start_fork(configured_process) }
|
66
67
|
end
|
67
68
|
|
68
|
-
def
|
69
|
-
@
|
70
|
-
|
69
|
+
def launch_maintenance_task
|
70
|
+
@maintenance_task = Concurrent::TimerTask.new(run_now: true, execution_interval: SolidQueue.process_alive_threshold) do
|
71
|
+
prune_dead_processes
|
72
|
+
release_orphaned_executions
|
73
|
+
end
|
74
|
+
@maintenance_task.execute
|
71
75
|
end
|
72
76
|
|
73
77
|
def shutdown
|
@@ -106,7 +110,7 @@ module SolidQueue
|
|
106
110
|
end
|
107
111
|
|
108
112
|
def stop_process_prune
|
109
|
-
@
|
113
|
+
@maintenance_task&.shutdown
|
110
114
|
end
|
111
115
|
|
112
116
|
def delete_pidfile
|
@@ -117,6 +121,10 @@ module SolidQueue
|
|
117
121
|
wrap_in_app_executor { SolidQueue::Process.prune }
|
118
122
|
end
|
119
123
|
|
124
|
+
def release_orphaned_executions
|
125
|
+
wrap_in_app_executor { SolidQueue::ClaimedExecution.orphaned.release_all }
|
126
|
+
end
|
127
|
+
|
120
128
|
def start_fork(configured_process)
|
121
129
|
configured_process.supervised_by process
|
122
130
|
|
data/lib/solid_queue/version.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: 0.3.
|
4
|
+
version: 0.3.4
|
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-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -199,6 +199,7 @@ files:
|
|
199
199
|
- app/models/solid_queue/job/concurrency_controls.rb
|
200
200
|
- app/models/solid_queue/job/executable.rb
|
201
201
|
- app/models/solid_queue/job/recurrable.rb
|
202
|
+
- app/models/solid_queue/job/retryable.rb
|
202
203
|
- app/models/solid_queue/job/schedulable.rb
|
203
204
|
- app/models/solid_queue/pause.rb
|
204
205
|
- app/models/solid_queue/process.rb
|
@@ -265,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
265
266
|
- !ruby/object:Gem::Version
|
266
267
|
version: '0'
|
267
268
|
requirements: []
|
268
|
-
rubygems_version: 3.5.
|
269
|
+
rubygems_version: 3.5.16
|
269
270
|
signing_key:
|
270
271
|
specification_version: 4
|
271
272
|
summary: Database-backed Active Job backend.
|