sidekiq-rerouting 0.1.0 → 0.3.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/CHANGELOG.md +14 -2
- data/README.md +84 -15
- data/lib/sidekiq/rerouting/batch_api.rb +30 -0
- data/lib/sidekiq/rerouting/router.rb +52 -0
- data/lib/sidekiq/rerouting/server_middleware.rb +17 -11
- data/lib/sidekiq/rerouting/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6b33ce67524b43eeb69f383ac34528f0d31f7d26df43fa5ab1bd84f8b5d5d52
|
|
4
|
+
data.tar.gz: 80f81ed20b959d9cdb00bb32553e482becc753d834e071f9d3de5ec22f4fd692
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa9a5eeb4e93350104159fc2e844fed05d26a28fc558328b4a11243e8759cf615509d2815a5f94ae21e9652ee9c7f84aaf0dc786d7ebe6c663a8d5640ad41fec
|
|
7
|
+
data.tar.gz: bce4f1c97fe84ee5234de594e6b044a30f2d5c0e9ba267d25d8e0980da20bdcda2d4d6dd7b7927fe8dd6b29c82e54a59f4850532909f49b5b39b9e477fcb233e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [Unreleased]:
|
|
4
|
+
|
|
5
|
+
## [0.3.0]: 2025-11-10
|
|
6
|
+
|
|
7
|
+
- Added support for Sidekiq Pro's Batch feature.
|
|
8
|
+
- **Breaking**: the `on_reroute` callback's `job` parameter is now the rerouted job instead of the original job.
|
|
9
|
+
Meaning the `job["queue"]` will be the rerouted queue, not the original queue.
|
|
10
|
+
|
|
11
|
+
## [0.2.0]: 2025-09-22
|
|
12
|
+
|
|
13
|
+
- **Breaking**: Change configuration of middleware to work with `Sidekiq::Middleware::Chain` API
|
|
14
|
+
|
|
15
|
+
## [0.1.0]: 2025-09-22
|
|
4
16
|
|
|
5
17
|
- Initial release
|
data/README.md
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
# Sidekiq::Rerouting
|
|
2
2
|
|
|
3
|
-
[](https://github.com/hibachrach/sidekiq-rerouting/actions)
|
|
4
4
|
|
|
5
5
|
A [Sidekiq][sidekiq] extension to set Sidekiq jobs to be rerouted to a different queue based on the job ID or job class.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
10
|
-
|
|
11
9
|
Install the gem and add to the application's Gemfile by executing:
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
bundle add
|
|
12
|
+
bundle add sidekiq-rerouting
|
|
15
13
|
```
|
|
16
14
|
|
|
17
15
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
18
16
|
|
|
19
17
|
```bash
|
|
20
|
-
gem install
|
|
18
|
+
gem install sidekiq-rerouting
|
|
21
19
|
```
|
|
22
20
|
|
|
23
21
|
## Usage
|
|
@@ -25,7 +23,7 @@ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
|
25
23
|
From a console (Rails console, or the like) you need a `Sidekiq::Rerouting::Client` instance, which is used to `#reroute` a job, or job class to be disposed.
|
|
26
24
|
|
|
27
25
|
```ruby
|
|
28
|
-
client = Sidekiq::
|
|
26
|
+
client = Sidekiq::Rerouting::Client.new
|
|
29
27
|
```
|
|
30
28
|
|
|
31
29
|
### Marking to reroute
|
|
@@ -40,14 +38,19 @@ client.reroute("different_queue", :jid, some_job_id)
|
|
|
40
38
|
client.reroute("different_queue", :class, "SomeJobClass")
|
|
41
39
|
```
|
|
42
40
|
|
|
43
|
-
A job or job class can also be removed from rerouting
|
|
41
|
+
A job or job class can also be removed from rerouting via a corresponding API. This only takes effects for jobs enqueued after the API call.
|
|
42
|
+
Reroute the jobs back to its original queue to affect the previously rerouted jobs still in the queue.
|
|
44
43
|
|
|
45
44
|
```ruby
|
|
46
|
-
# Unmark a specific Job
|
|
47
|
-
client.remove_rerouting(
|
|
45
|
+
# Unmark a specific Job for rerouting by specifying its job ID
|
|
46
|
+
client.remove_rerouting(:jid, some_job_id)
|
|
47
|
+
|
|
48
|
+
# Unmark an entire job class for rerouting
|
|
49
|
+
client.remove_rerouting(:class, "SomeJobClass")
|
|
48
50
|
|
|
49
|
-
#
|
|
50
|
-
client.
|
|
51
|
+
# Force previously rerouted job class/jid to its original queue
|
|
52
|
+
client.reroute("original_queue", :jid, some_job_id)
|
|
53
|
+
client.reroute("original_queue", :class, "SomeJobClass")
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
### Clearing all rerouting
|
|
@@ -58,19 +61,77 @@ Clearing all reroutes marks can be done in one fell swoop as well.
|
|
|
58
61
|
client.remove_rerouting_for_all
|
|
59
62
|
```
|
|
60
63
|
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
With `sidekiq-rerouting` installed, [register its Sidekiq server middleware][sidekiq-register-middleware].
|
|
67
|
+
Typically this is done via `config/initializers/sidekiq.rb` in a Rails app.
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
Sidekiq.configure_server do |config|
|
|
71
|
+
config.server_middleware do |chain|
|
|
72
|
+
chain.add Sidekiq::Rerouting::ServerMiddleware
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This piece of middleware checks each job, after it's been dequeued, but before its `#perform` has been called, to see if it should be rerouted.
|
|
78
|
+
If the job is marked for rerouting (by job ID or job class), a new job (with the same job ID) is enqueued into the intended destination and the current job exits early.
|
|
79
|
+
|
|
80
|
+
### Callback
|
|
81
|
+
|
|
82
|
+
If you'd like to do something when a job is rerouted,
|
|
83
|
+
you can optionally pass in an object that responds to `.call` (like a `Proc`) when adding the middleware:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
Sidekiq.configure_server do |config|
|
|
87
|
+
config.server_middleware do |chain|
|
|
88
|
+
chain.add(Sidekiq::Rerouting::ServerMiddleware, on_reroute: -> { |job:, old_queue:, new_queue:|
|
|
89
|
+
puts "Job with jid=#{job["jid"]} was rerouted from #{old_queue} to #{new_queue}"
|
|
90
|
+
})
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It yields the following keyword arguments:
|
|
96
|
+
|
|
97
|
+
- `job`: the serialized job that is being rerouted; see [Sidekiq's docs][job-format] for more details.
|
|
98
|
+
- `old_queue`: the queue _from which_ the job is being rerouted.
|
|
99
|
+
- `new_queue`: the queue _to which_ the job is being rerouted.
|
|
100
|
+
|
|
101
|
+
### Sidekiq Pro Batches
|
|
102
|
+
|
|
103
|
+
If you're using [Sidekiq Pro's Batch feature][sidekiq-batches] you need to be sure to insert the rerouting middleware _after_ the `Batch` middleware.
|
|
104
|
+
This will ensure the batch can be re-opened, and the rereouted job added to it.
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
Sidekiq.configure_server do |config|
|
|
108
|
+
config.server_middleware do |chain|
|
|
109
|
+
chain.insert_after(Sidekiq::Batch::Server, Sidekiq::Rerouting::ServerMiddleware)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
```
|
|
113
|
+
|
|
61
114
|
### Non-Reroutable Jobs
|
|
62
115
|
|
|
63
116
|
By default all Jobs are reroutable.
|
|
64
|
-
However, checking if a specific
|
|
65
|
-
Therefore, you might want to make some
|
|
117
|
+
However, checking if a specific job should be rerouted is not free; it requires round trip(s) to Redis.
|
|
118
|
+
Therefore, you might want to make some jobs non-reroutable to avoid these extra round trips.
|
|
66
119
|
Or because there are some Jobs that simply should never be rerouted for… _reasons_.
|
|
67
120
|
|
|
121
|
+
This is done via a job's `sidekiq_options`.
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
sidekiq_options reroutable: false
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
With that in place, the server middleware will ignore the Job, and pass it down the middleware Chain.
|
|
128
|
+
No extra Redis calls, no funny business.
|
|
68
129
|
|
|
69
130
|
## Development
|
|
70
131
|
|
|
71
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `
|
|
132
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
72
133
|
|
|
73
|
-
To install this gem onto your local machine, run `
|
|
134
|
+
To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
74
135
|
|
|
75
136
|
## Contributing
|
|
76
137
|
|
|
@@ -84,4 +145,12 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
84
145
|
|
|
85
146
|
Everyone interacting in the Sidekiq::Rerouting project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/hibachrach/sidekiq-rerouting/blob/main/CODE_OF_CONDUCT.md).
|
|
86
147
|
|
|
148
|
+
## See Also
|
|
149
|
+
|
|
150
|
+
- [`sidekiq-disposal`][sidekiq-disposal]
|
|
151
|
+
|
|
87
152
|
[sidekiq]: https://sidekiq.org "Simple, efficient background jobs for Ruby."
|
|
153
|
+
[sidekiq-batches]: https://github.com/sidekiq/sidekiq/wiki/Batches "Sidekiq Pro Batches"
|
|
154
|
+
[sidekiq-disposal]: https://github.com/hibachrach/sidekiq-disposal "A Sidekiq extension to mark Sidekiq jobs to be disposed of."
|
|
155
|
+
[sidekiq-register-middleware]: https://github.com/sidekiq/sidekiq/wiki/Middleware#registering-middleware "Registering Sidekiq Middleware"
|
|
156
|
+
[job-format]: https://github.com/sidekiq/sidekiq/wiki/Job-Format "How Sidekiq jobs are serialized"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rerouting"
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Rerouting
|
|
7
|
+
class BatchAPI
|
|
8
|
+
def jobs_in(batch:)
|
|
9
|
+
batch_api.new(batch).jobs do
|
|
10
|
+
yield
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def batch_api
|
|
17
|
+
@batch_api ||= defined?(::Sidekiq::Batch) ? ::Sidekiq::Batch : NullBatchAPI
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class NullBatchAPI
|
|
21
|
+
def initialize(_batch_id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def jobs
|
|
25
|
+
yield
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rerouting"
|
|
4
|
+
require_relative "batch_api"
|
|
5
|
+
|
|
6
|
+
module Sidekiq
|
|
7
|
+
module Rerouting
|
|
8
|
+
class Router
|
|
9
|
+
def initialize(job_instance:, job_payload:, client: Client.new, batch_api: BatchAPI.new)
|
|
10
|
+
@batch_api = batch_api
|
|
11
|
+
@client = client
|
|
12
|
+
@job_instance = job_instance
|
|
13
|
+
@job_payload = job_payload
|
|
14
|
+
@original_queue = job_payload["queue"]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :original_queue
|
|
18
|
+
|
|
19
|
+
def reroutable?
|
|
20
|
+
job_instance && job_instance.class.get_sidekiq_options.fetch("reroutable", true)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def rerouted_from?(queue:)
|
|
24
|
+
rerouted_queue && rerouted_queue != queue
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def rerouted_playload
|
|
28
|
+
job_payload.merge("queue" => rerouted_queue)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def rerouted_queue
|
|
32
|
+
return @rerouted_queue if defined?(@rerouted_queue)
|
|
33
|
+
|
|
34
|
+
@rerouted_queue = client.rerouting_destination(job_payload)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def within_batch_maybe
|
|
38
|
+
batch_id = job_payload["bid"]
|
|
39
|
+
|
|
40
|
+
return yield unless batch_id
|
|
41
|
+
|
|
42
|
+
batch_api.jobs_in(batch: batch_id) do
|
|
43
|
+
yield
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
attr_reader :batch_api, :client, :job_instance, :job_payload
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
require "sidekiq"
|
|
4
4
|
require_relative "../rerouting"
|
|
5
|
+
require_relative "router"
|
|
5
6
|
|
|
6
7
|
module Sidekiq
|
|
7
8
|
module Rerouting
|
|
8
9
|
class ServerMiddleware
|
|
9
10
|
include ::Sidekiq::ServerMiddleware
|
|
10
11
|
|
|
11
|
-
def initialize(
|
|
12
|
-
@client = client
|
|
13
|
-
@on_reroute =
|
|
12
|
+
def initialize(opts = {})
|
|
13
|
+
@client = opts.fetch(:client, Client.new)
|
|
14
|
+
@on_reroute = opts.fetch(:on_reroute, nil)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
|
-
def call(job_instance,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
on_reroute&.call(job:, old_queue: queue, new_queue: rerouting_destination)
|
|
17
|
+
def call(job_instance, job_payload, queue)
|
|
18
|
+
router = Router.new(job_instance:, job_payload:, client:)
|
|
19
|
+
|
|
20
|
+
if router.reroutable? && router.rerouted_from?(queue:)
|
|
21
|
+
router.within_batch_maybe do
|
|
22
|
+
reroute(sidekiq_client: job_instance.class, router: router)
|
|
23
|
+
end
|
|
24
24
|
else
|
|
25
25
|
yield
|
|
26
26
|
end
|
|
@@ -29,6 +29,12 @@ module Sidekiq
|
|
|
29
29
|
private
|
|
30
30
|
|
|
31
31
|
attr_reader :client, :on_reroute
|
|
32
|
+
|
|
33
|
+
def reroute(sidekiq_client:, router:)
|
|
34
|
+
sidekiq_client.client_push(router.rerouted_playload)
|
|
35
|
+
|
|
36
|
+
on_reroute&.call(job: router.rerouted_playload, old_queue: router.original_queue, new_queue: router.rerouted_queue)
|
|
37
|
+
end
|
|
32
38
|
end
|
|
33
39
|
end
|
|
34
40
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sidekiq-rerouting
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hazel Bachrach
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
12
|
+
date: 2025-11-10 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: sidekiq
|
|
@@ -41,7 +41,9 @@ files:
|
|
|
41
41
|
- README.md
|
|
42
42
|
- Rakefile
|
|
43
43
|
- lib/sidekiq/rerouting.rb
|
|
44
|
+
- lib/sidekiq/rerouting/batch_api.rb
|
|
44
45
|
- lib/sidekiq/rerouting/client.rb
|
|
46
|
+
- lib/sidekiq/rerouting/router.rb
|
|
45
47
|
- lib/sidekiq/rerouting/server_middleware.rb
|
|
46
48
|
- lib/sidekiq/rerouting/version.rb
|
|
47
49
|
- sig/sidekiq/rerouting.rbs
|
|
@@ -68,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
68
70
|
- !ruby/object:Gem::Version
|
|
69
71
|
version: '0'
|
|
70
72
|
requirements: []
|
|
71
|
-
rubygems_version: 3.
|
|
73
|
+
rubygems_version: 3.5.22
|
|
72
74
|
signing_key:
|
|
73
75
|
specification_version: 4
|
|
74
76
|
summary: A mechanism to reroute queued jobs to a different queue on pickup
|