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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82bc960f510cb4d9d214ee89111b292015a5d9c1f6871e27ed5df98c6733b733
4
- data.tar.gz: 6075abebe883247848cfbba437251fd8fc17c0c0005c2ff85ed4889a8df4f526
3
+ metadata.gz: a6b33ce67524b43eeb69f383ac34528f0d31f7d26df43fa5ab1bd84f8b5d5d52
4
+ data.tar.gz: 80f81ed20b959d9cdb00bb32553e482becc753d834e071f9d3de5ec22f4fd692
5
5
  SHA512:
6
- metadata.gz: c7a77cbc8402503850d5083207e8f4789a4ad58b03e894c27fa1a5832f34dd3c2e188cdbb4712041aec7a51e994431c80d26eea7d6b210314a8180127d087576
7
- data.tar.gz: d634d71d8616958ac051312145487d48cd8013d48419a9b89b20bbd817564b39c1ffa0a0d525290c12a8df0e3fd85abfcefd833fb9c360398bef649e086caa8c
6
+ metadata.gz: aa9a5eeb4e93350104159fc2e844fed05d26a28fc558328b4a11243e8759cf615509d2815a5f94ae21e9652ee9c7f84aaf0dc786d7ebe6c663a8d5640ad41fec
7
+ data.tar.gz: bce4f1c97fe84ee5234de594e6b044a30f2d5c0e9ba267d25d8e0980da20bdcda2d4d6dd7b7927fe8dd6b29c82e54a59f4850532909f49b5b39b9e477fcb233e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
- ## [0.1.0] - 2025-09-19
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
- [![CI](https://github.com/hibachrach/sidekiq-disposal/actions/workflows/main.yml/badge.svg)](https://github.com/hibachrach/sidekiq-disposal/actions)
3
+ [![CI](https://github.com/hibachrach/sidekiq-rerouting/actions/workflows/main.yml/badge.svg)](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 UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
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 UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
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::Disposal::Client.new
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 for disposal via a corresponding API.
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 to be rerouted by specifying its job ID
47
- client.remove_rerouting("different_queue", :jid, some_job_id)
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
- # Unmark an entire job class to be rerouted
50
- client.remove_rerouting("different_queue", :class, "SomeJobClass")
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 Job should be rerouted is not free; it requires round trip(s) to Redis.
65
- Therefore, you might want to make some Jobs non-reroutable to avoid these extra round trips.
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 `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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 `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec 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).
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(client = Client.new, &blk)
12
- @client = client
13
- @on_reroute = blk
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, job, queue)
17
- if job_instance && !job_instance.class.get_sidekiq_options.fetch("reroutable", true)
18
- yield
19
- elsif job_instance &&
20
- (rerouting_destination = client.rerouting_destination(job)) &&
21
- rerouting_destination != queue
22
- job_instance.class.client_push(job.merge("queue" => rerouting_destination))
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sidekiq
4
4
  module Rerouting
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  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.1.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-09-22 00:00:00.000000000 Z
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.4.19
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