solid_queue 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -1
- data/lib/solid_queue/lifecycle_hooks.rb +43 -0
- data/lib/solid_queue/processes/runnable.rb +10 -12
- data/lib/solid_queue/supervisor.rb +3 -0
- data/lib/solid_queue/version.rb +1 -1
- data/lib/solid_queue/worker.rb +5 -0
- data/lib/solid_queue.rb +10 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7234dc4430998648196bf2d3905b66bb85e265c2393121a7c5343fed36b1996
|
4
|
+
data.tar.gz: 216a0918e29194e6d11fe4bf365183228127f8390658a11ace329523ad41468c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a080aedf20f39940d8c25e8a14628811801b8fd4832fbcb926beecd0d1ce4c694ec8d80b608656f9de80cc8cc69b525f62d4fe7bc7258408aa6d6af62292d4fd
|
7
|
+
data.tar.gz: 66d24c1bb1c7cb1b9afbcf8a0b667df624dd3f47cea92887fbcd69d93b1832af3c44afb570d1cfb459c37e2b3c163900e0dd2febb067ee9179b4c49514e4b359
|
data/README.md
CHANGED
@@ -208,17 +208,47 @@ Finally, run the migrations:
|
|
208
208
|
$ bin/rails db:migrate
|
209
209
|
```
|
210
210
|
|
211
|
+
## Lifecycle hooks
|
212
|
+
|
213
|
+
In Solid queue, you can hook into two different points in the supervisor's life:
|
214
|
+
- `start`: after the supervisor has finished booting and right before it forks workers and dispatchers.
|
215
|
+
- `stop`: after receiving a signal (`TERM`, `INT` or `QUIT`) and right before starting graceful or immediate shutdown.
|
216
|
+
|
217
|
+
And into two different points in a worker's life:
|
218
|
+
- `worker_start`: after the worker has finished booting and right before it starts the polling loop.
|
219
|
+
- `worker_stop`: after receiving a signal (`TERM`, `INT` or `QUIT`) and right before starting graceful or immediate shutdown (which is just `exit!`).
|
220
|
+
|
221
|
+
You can use the following methods with a block to do this:
|
222
|
+
```ruby
|
223
|
+
SolidQueue.on_start
|
224
|
+
SolidQueue.on_stop
|
225
|
+
|
226
|
+
SolidQueue.on_worker_start
|
227
|
+
SolidQueue.on_worker_stop
|
228
|
+
```
|
229
|
+
|
230
|
+
For example:
|
231
|
+
```ruby
|
232
|
+
SolidQueue.on_start { start_metrics_server }
|
233
|
+
SolidQueue.on_stop { stop_metrics_server }
|
234
|
+
```
|
235
|
+
|
236
|
+
These can be called several times to add multiple hooks, but it needs to happen before Solid Queue is started. An initializer would be a good place to do this.
|
237
|
+
|
238
|
+
|
211
239
|
### Other configuration settings
|
212
240
|
_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`
|
213
241
|
|
214
242
|
There are several settings that control how Solid Queue works that you can set as well:
|
215
243
|
- `logger`: the logger you want Solid Queue to use. Defaults to the app logger.
|
216
244
|
- `app_executor`: the [Rails executor](https://guides.rubyonrails.org/threading_and_code_execution.html#executor) used to wrap asynchronous operations, defaults to the app executor
|
217
|
-
- `on_thread_error`: custom lambda/Proc to call when there's an error within a thread that takes the exception raised as argument. Defaults to
|
245
|
+
- `on_thread_error`: custom lambda/Proc to call when there's an error within a Solid Queue thread that takes the exception raised as argument. Defaults to
|
218
246
|
|
219
247
|
```ruby
|
220
248
|
-> (exception) { Rails.error.report(exception, handled: false) }
|
221
249
|
```
|
250
|
+
**This is not used for errors raised within a job execution**. Errors happening in jobs are handled by Active Job's `retry_on` or `discard_on`, and ultimately will result in [failed jobs](#failed-jobs-and-retries). This is for errors happening within Solid Queue itself.
|
251
|
+
|
222
252
|
- `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.
|
223
253
|
- `process_heartbeat_interval`: the heartbeat interval that all processes will follow—defaults to 60 seconds.
|
224
254
|
- `process_alive_threshold`: how long to wait until a process is considered dead after its last heartbeat—defaults to 5 minutes.
|
@@ -283,6 +313,8 @@ In this case, if we have a `Box::MovePostingsByContactToDesignatedBoxJob` job en
|
|
283
313
|
|
284
314
|
Note that the `duration` setting depends indirectly on the value for `concurrency_maintenance_interval` that you set for your dispatcher(s), as that'd be the frequency with which blocked jobs are checked and unblocked. In general, you should set `duration` in a way that all your jobs would finish well under that duration and think of the concurrency maintenance task as a failsafe in case something goes wrong.
|
285
315
|
|
316
|
+
Jobs are unblocked in order of priority but queue order is not taken into account for unblocking jobs. That means that if you have a group of jobs that share a concurrency group but are in different queues, or jobs of the same class that you enqueue in different queues, the queue order you set for a worker is not taken into account when unblocking blocked ones. The reason is that a job that runs unblocks the next one, and the job itself doesn't know about a particular worker's queue order (you could even have different workers with different queue orders), it can only know about priority. Once blocked jobs are unblocked and available for polling, they'll be picked up by a worker following its queue order.
|
317
|
+
|
286
318
|
Finally, failed jobs that are automatically or manually retried work in the same way as new jobs that get enqueued: they get in the queue for gaining the lock, and whenever they get it, they'll be run. It doesn't matter if they had gained the lock already in the past.
|
287
319
|
|
288
320
|
## Failed jobs and retries
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidQueue
|
4
|
+
module LifecycleHooks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
mattr_reader :lifecycle_hooks, default: { start: [], stop: [] }
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
def on_start(&block)
|
13
|
+
self.lifecycle_hooks[:start] << block
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_stop(&block)
|
17
|
+
self.lifecycle_hooks[:stop] << block
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_hooks
|
21
|
+
self.lifecycle_hooks[:start] = []
|
22
|
+
self.lifecycle_hooks[:stop] = []
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def run_start_hooks
|
28
|
+
run_hooks_for :start
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_stop_hooks
|
32
|
+
run_hooks_for :stop
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_hooks_for(event)
|
36
|
+
self.class.lifecycle_hooks.fetch(event, []).each do |block|
|
37
|
+
block.call
|
38
|
+
rescue Exception => exception
|
39
|
+
handle_thread_error(exception)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -7,11 +7,7 @@ module SolidQueue::Processes
|
|
7
7
|
attr_writer :mode
|
8
8
|
|
9
9
|
def start
|
10
|
-
|
11
|
-
|
12
|
-
SolidQueue.instrument(:start_process, process: self) do
|
13
|
-
run_callbacks(:boot) { boot }
|
14
|
-
end
|
10
|
+
boot
|
15
11
|
|
16
12
|
if running_async?
|
17
13
|
@thread = create_thread { run }
|
@@ -25,10 +21,6 @@ module SolidQueue::Processes
|
|
25
21
|
@thread&.join
|
26
22
|
end
|
27
23
|
|
28
|
-
def alive?
|
29
|
-
!running_async? || @thread.alive?
|
30
|
-
end
|
31
|
-
|
32
24
|
private
|
33
25
|
DEFAULT_MODE = :async
|
34
26
|
|
@@ -37,9 +29,15 @@ module SolidQueue::Processes
|
|
37
29
|
end
|
38
30
|
|
39
31
|
def boot
|
40
|
-
|
41
|
-
|
42
|
-
|
32
|
+
SolidQueue.instrument(:start_process, process: self) do
|
33
|
+
run_callbacks(:boot) do
|
34
|
+
@stopped = false
|
35
|
+
|
36
|
+
if running_as_fork?
|
37
|
+
register_signal_handlers
|
38
|
+
set_procline
|
39
|
+
end
|
40
|
+
end
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module SolidQueue
|
4
4
|
class Supervisor < Processes::Base
|
5
|
+
include LifecycleHooks
|
5
6
|
include Maintenance, Signals, Pidfiled
|
6
7
|
|
7
8
|
class << self
|
@@ -27,6 +28,7 @@ module SolidQueue
|
|
27
28
|
|
28
29
|
def start
|
29
30
|
boot
|
31
|
+
run_start_hooks
|
30
32
|
|
31
33
|
start_processes
|
32
34
|
launch_maintenance_task
|
@@ -36,6 +38,7 @@ module SolidQueue
|
|
36
38
|
|
37
39
|
def stop
|
38
40
|
@stopped = true
|
41
|
+
run_stop_hooks
|
39
42
|
end
|
40
43
|
|
41
44
|
private
|
data/lib/solid_queue/version.rb
CHANGED
data/lib/solid_queue/worker.rb
CHANGED
data/lib/solid_queue.rb
CHANGED
@@ -43,6 +43,16 @@ module SolidQueue
|
|
43
43
|
mattr_accessor :clear_finished_jobs_after, default: 1.day
|
44
44
|
mattr_accessor :default_concurrency_control_period, default: 3.minutes
|
45
45
|
|
46
|
+
delegate :on_start, :on_stop, to: Supervisor
|
47
|
+
|
48
|
+
def on_worker_start(...)
|
49
|
+
Worker.on_start(...)
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_worker_stop(...)
|
53
|
+
Worker.on_stop(...)
|
54
|
+
end
|
55
|
+
|
46
56
|
def supervisor?
|
47
57
|
supervisor
|
48
58
|
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.7.
|
4
|
+
version: 0.7.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-09-
|
11
|
+
date: 2024-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -253,6 +253,7 @@ files:
|
|
253
253
|
- lib/solid_queue/dispatcher/concurrency_maintenance.rb
|
254
254
|
- lib/solid_queue/dispatcher/recurring_schedule.rb
|
255
255
|
- lib/solid_queue/engine.rb
|
256
|
+
- lib/solid_queue/lifecycle_hooks.rb
|
256
257
|
- lib/solid_queue/log_subscriber.rb
|
257
258
|
- lib/solid_queue/pool.rb
|
258
259
|
- lib/solid_queue/processes/base.rb
|