sidekiq-bus 1.1.0 → 2.0.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: 348236e181a0dfa48615334f28f2f9cc866a44fa93d63377c7780190f47f9e82
4
- data.tar.gz: db608296c196894b6e793dc5a6b7a5ad41426307ea2e0cf592b75b9cc580e7f4
3
+ metadata.gz: 31218b263cfcfbc7226f2f8d30ddc2ffb24019fc9a1ee55a45cc324a592d8a60
4
+ data.tar.gz: 4bc6d366f8163ec83b392476d4fb4919b3c16c026c5713e7632c6aacab276097
5
5
  SHA512:
6
- metadata.gz: 865909c8db64b272978af02dcceb551f5f8c5c552ef1cd9e140876bdff8dc4a149385433bebcabe55ecc911a9ef6cd895b31b4d024366b5dee0691ed57bfb6d5
7
- data.tar.gz: cb8ca09af0f508755e71f28f3bc7ec212f5380677de55e8c92ea7d6393cc7526103a9a72cd72f274d46da8a9409a0e7772a4a4eec782150eaaa1428f7ad5cfc0
6
+ metadata.gz: 825f2a4bf78bbfef5e4e02cbd10cbd98833eaa3e29445203877adc238db6aaa0f92aae41c27ddaf11d1ae4a81b49bb63ebf7bfdfe91a13e192d1800a529e08a1
7
+ data.tar.gz: d42466dd3302d78ed7670fdff75b5b80e59d8da9597e581a1f7324b4e9ab0cd40aa0455c397249300cc41dd5bdcb3e4f644d4743fa51fbc2aca6a2efa3239ce5
data/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Changed
10
+
11
+ ## [2.0.0] - 2025-06-17
12
+
13
+ - [BREAKING] Sidekiq major version now targets 7.X
14
+ - [BREAKING] SidekiqScheduler major version now targets 5.X to support Sidekiq 7
15
+ - [BREAKING] SidekiqBus must now be configured with a Redis pool. See the README for more details.
16
+ - [Development] Discontinues use of FakeRedis in favor of real Redis for testing.
17
+
9
18
  ## [1.1.0] - 2025-05-13
10
19
 
11
20
  ### Changed
data/README.mdown CHANGED
@@ -11,6 +11,27 @@ To install, include the 'sidekiq-bus' gem and add the following to your Rakefile
11
11
  require "sidekiq_bus/tasks"
12
12
  ```
13
13
 
14
+ ### Configure
15
+ Starting from version 7, Sidekiq no longer provides a standard Redis connection pool, instead providing a limited
16
+ wrapper around the low-level RedisClient gem. To maintain compatibility with both QueueBus and later versions of
17
+ Sidekiq, SidekiqBus now requires an explicit Redis handler. To preserve your existing QueueBus data, this handler should
18
+ connect to the same Redis instance and database as your Sidekiq configuration.
19
+
20
+ The handler can be any object that responds to `call` and yields a Redis connection. In an initializer, set it with:
21
+
22
+ ```ruby
23
+ # Naive example
24
+ SidekiqBus.redis_handler = ->(&block) { block.call(Redis.new(my_config) }
25
+
26
+ # More typical example using the Redis-recommended ConnectionPool gem
27
+ pool = ConnectionPool.new(size: pool_size, timeout: pool_timeout) { Redis.new(my_config) }
28
+ SidekiqBus.redis_handler = pool.method(:with).to_proc
29
+ # Or, for clarity:
30
+ SidekiqBus.redis_handler = ->(&block) do
31
+ pool.with { |redis| block.call(redis) }
32
+ end
33
+ ```
34
+
14
35
  ### Example
15
36
 
16
37
  Application A can publish an event
@@ -162,6 +183,22 @@ event to the appropriate code block.
162
183
  You can also say `QueueBus.local_mode = :suppress` to turn off publishing altogether.
163
184
  This can be helpful inside some sort of migration, for example.
164
185
 
186
+ ### Development
187
+
188
+ #### Running Tests
189
+
190
+ The test suite requires a Redis instance. For convenience, we provide Docker Compose configuration to run Redis in a container:
191
+
192
+ ```bash
193
+ docker-compose up -d
194
+
195
+ bundle exec rspec
196
+ ```
197
+
198
+ The test suite uses database 15 by default to avoid conflicts with your development Redis data.
199
+
200
+ You can override the connection string (including the database number) by setting the `REDIS_URL` environment variable.
201
+
165
202
  ### TODO
166
203
 
167
204
  * Replace local modes with adapters
@@ -0,0 +1,18 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ redis:
5
+ image: redis:7-alpine
6
+ ports:
7
+ - "6379:6379"
8
+ command: redis-server --appendonly yes
9
+ volumes:
10
+ - redis_data:/data
11
+ healthcheck:
12
+ test: ["CMD", "redis-cli", "ping"]
13
+ interval: 5s
14
+ timeout: 3s
15
+ retries: 5
16
+
17
+ volumes:
18
+ redis_data:
data/lib/sidekiq-bus.rb CHANGED
@@ -7,6 +7,10 @@ require 'sidekiq_bus/server'
7
7
  require 'sidekiq_bus/middleware/retry'
8
8
 
9
9
  module SidekiqBus
10
+ ConfigurationError = Class.new(StandardError)
11
+ REDIS_HANDLER_ERROR_MESSAGE = 'Please set SidekiqBus.redis_handler to a Callable that accepts a block and yields a '\
12
+ 'Redis instance. See the SidekiqBus README for more details.'
13
+
10
14
  # This method will analyze the current queues and generate an array that
11
15
  # can operate as the sidekiq queues configuration. It should be based on how
12
16
  # The sidekiq CLI builds weighted queues.
@@ -42,6 +46,21 @@ module SidekiqBus
42
46
  # flattened into a single array
43
47
  entries.flat_map { |e| Array.new(e.weight, e.queue) }
44
48
  end
49
+
50
+ def self.redis_handler=(handler)
51
+ unless handler.respond_to?(:call)
52
+ raise ConfigurationError, REDIS_HANDLER_ERROR_MESSAGE
53
+ end
54
+ @redis_handler = handler
55
+ end
56
+
57
+ def self.redis(&block)
58
+ raise ConfigurationError, REDIS_HANDLER_ERROR_MESSAGE unless @redis_handler
59
+ @redis_handler.call(&block)
60
+ end
61
+
62
+ def self.validate_redis_handler
63
+ end
45
64
  end
46
65
 
47
66
  if QueueBus.has_adapter?
@@ -21,7 +21,7 @@ module QueueBus
21
21
  end
22
22
 
23
23
  def redis(&block)
24
- ::Sidekiq.redis(&block)
24
+ ::SidekiqBus.redis(&block)
25
25
  end
26
26
 
27
27
  def enqueue(queue_name, klass, hash)
@@ -66,7 +66,8 @@ module QueueBus
66
66
  description: 'Enqueues a heart beat every minute for the queue-bus'
67
67
  )
68
68
 
69
- ::Sidekiq::Scheduler.instance.update_schedule unless ::Sidekiq::Scheduler.instance.dynamic
69
+ # If dynamic is enabled, this will propagate through a different mechanism
70
+ SidekiqScheduler::Scheduler.instance.reload_schedule! unless ::Sidekiq::Scheduler.instance.dynamic
70
71
  end
71
72
  end
72
73
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SidekiqBus
4
- VERSION = '1.1.0'
4
+ VERSION = '2.0.0'
5
5
  end
data/sidekiq-bus.gemspec CHANGED
@@ -17,13 +17,11 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  s.add_dependency('queue-bus', ['>= 0.7', '< 1'])
20
- s.add_dependency('sidekiq', ['>= 3.0.0', '< 7.0'])
21
- s.add_dependency('rack', "< 3.0") # Sidekiq 6 was sunset before Rack 3.0 and does not support it
22
- s.add_dependency('sidekiq-scheduler', ['>= 3.0', '< 5.0'])
20
+ s.add_dependency('redis', ['>= 4.0', '< 6.0'])
21
+ s.add_dependency('sidekiq', ['>= 7.0.0', '< 8.0'])
22
+ s.add_dependency('sidekiq-scheduler', ['>= 5.0', '< 6.0'])
23
23
 
24
24
  s.add_development_dependency("rspec")
25
- s.add_development_dependency("fakeredis")
26
- s.add_development_dependency("redis-namespace")
27
25
  s.add_development_dependency("pry")
28
26
  s.add_development_dependency("timecop")
29
27
  s.add_development_dependency("json_pure")
@@ -87,17 +87,14 @@ describe 'Sidekiq Integration' do
87
87
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
88
88
  expect(val).to eq(nil) # nothing really added
89
89
 
90
- # NOTE: this is silently invoking a monkey patch in spec_helper
91
- # since the Poller invokes a Lua script that FakeRedis does not
92
- # natively support.
93
- Sidekiq::Scheduled::Poller.new(Sidekiq).enqueue
90
+ Sidekiq::Scheduled::Poller.new(Sidekiq.default_configuration).enqueue
94
91
 
95
92
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
96
93
  expect(val).to eq(nil) # nothing added yet
97
94
 
98
95
  # process scheduler in future
99
96
  Timecop.freeze(worktime) do
100
- Sidekiq::Scheduled::Poller.new(Sidekiq).enqueue
97
+ Sidekiq::Scheduled::Poller.new(Sidekiq.default_configuration).enqueue
101
98
 
102
99
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
103
100
  hash = JSON.parse(val)
data/spec/adapter_spec.rb CHANGED
@@ -19,11 +19,11 @@ describe 'adapter is set' do
19
19
 
20
20
  around do |example|
21
21
  begin
22
- old = Sidekiq.options[:lifecycle_events][:startup]
23
- Sidekiq.options[:lifecycle_events][:startup] = []
22
+ old = Sidekiq.default_configuration[:lifecycle_events][:startup]
23
+ Sidekiq.default_configuration[:lifecycle_events][:startup] = []
24
24
  example.run
25
25
  ensure
26
- Sidekiq.options[:lifecycle_events][:startup] = old
26
+ Sidekiq.default_configuration[:lifecycle_events][:startup] = old
27
27
  end
28
28
  end
29
29
 
@@ -65,7 +65,7 @@ describe 'adapter is set' do
65
65
  allow(Sidekiq::Scheduler.instance).to receive(:dynamic).and_return(true)
66
66
 
67
67
  # Simulate running startup events
68
- Sidekiq.options[:lifecycle_events][:startup].each(&:call)
68
+ Sidekiq.default_configuration[:lifecycle_events][:startup].each(&:call)
69
69
  end
70
70
 
71
71
  it_behaves_like 'a scheduled heartbeat'
@@ -76,7 +76,7 @@ describe 'adapter is set' do
76
76
  allow(Sidekiq::Scheduler.instance).to receive(:dynamic).and_return(false)
77
77
 
78
78
  # Simulate running startup events
79
- Sidekiq.options[:lifecycle_events][:startup].each(&:call)
79
+ Sidekiq.default_configuration[:lifecycle_events][:startup].each(&:call)
80
80
  end
81
81
 
82
82
  it_behaves_like 'a scheduled heartbeat'
data/spec/spec_helper.rb CHANGED
@@ -4,11 +4,40 @@ require 'timecop'
4
4
  require 'queue-bus'
5
5
  require 'adapter/support'
6
6
  require 'pry'
7
+ require 'redis'
8
+
9
+ # Require some private Sidekiq APIs to simulate internal scheduling behavior
10
+ require "sidekiq/capsule"
7
11
 
8
12
  reset_test_adapter
9
13
 
10
- require 'fakeredis'
11
- Sidekiq.redis = ConnectionPool.new { Redis.new(driver: Redis::Connection::Memory) }
14
+ # Use real Redis for testing to ensure compatibility with Sidekiq's Lua scripts
15
+ redis_url = ENV.fetch('REDIS_URL', 'redis://localhost:6379/15')
16
+
17
+ # Check Redis connection before running tests
18
+ begin
19
+ test_redis = Redis.new(url: redis_url)
20
+ test_redis.ping
21
+ test_redis.disconnect!
22
+ rescue Redis::CannotConnectError, Errno::ECONNREFUSED => e
23
+ puts "\n❌ Redis connection failed!"
24
+ puts " URL: #{redis_url}"
25
+ puts " Error: #{e.message}"
26
+ puts "\n💡 To fix this:"
27
+ puts " • Start Redis with Docker: docker-compose up -d redis"
28
+ puts " • Or start Redis locally: redis-server"
29
+ puts " • Or set REDIS_URL environment variable to a running Redis instance"
30
+ puts "\n"
31
+ exit 1
32
+ rescue => e
33
+ puts "\n❌ Unexpected error connecting to Redis:"
34
+ puts " #{e.class}: #{e.message}"
35
+ puts "\n"
36
+ exit 1
37
+ end
38
+
39
+ redis_pool = ConnectionPool.new { Redis.new(url: redis_url) }
40
+ SidekiqBus.redis_handler = redis_pool.method(:with).to_proc
12
41
 
13
42
  require 'fileutils'
14
43
 
@@ -19,9 +48,18 @@ FileUtils.touch(log_file)
19
48
 
20
49
  logger = Logger.new(File.open(log_file, 'a'))
21
50
 
22
- Sidekiq.logger = logger
23
51
  QueueBus.logger = logger
24
52
 
53
+ Sidekiq.configure_server do |config|
54
+ config.redis = { url: redis_url }
55
+ config.logger = logger
56
+ end
57
+
58
+ Sidekiq.configure_client do |config|
59
+ config.redis = { url: redis_url }
60
+ config.logger = logger
61
+ end
62
+
25
63
  require 'sidekiq/testing'
26
64
 
27
65
  module QueueBus
@@ -53,38 +91,6 @@ module QueueBus
53
91
  end
54
92
  end
55
93
 
56
- class Redis
57
- module Connection
58
- class Memory
59
- def script(*args)
60
- case args[1]
61
- when Sidekiq::Scheduled::Enq::LUA_ZPOPBYSCORE
62
- QueueBus.redis do |redis|
63
- now = Time.now.to_f
64
-
65
- # Process both 'schedule' and 'retry' sets
66
- %w[schedule retry].each do |set_name|
67
- # Get jobs that are ready to be processed (score <= now)
68
- jobs = redis.zrangebyscore(set_name, '-inf', now)
69
-
70
- jobs.each do |job_json|
71
- # Remove from scheduled set
72
- redis.zrem(set_name, job_json)
73
-
74
- # Parse and re-enqueue the job
75
- job_data = JSON.parse(job_json)
76
- queue_name = job_data['queue'] || 'default'
77
- redis.lpush("queue:#{queue_name}", job_json)
78
- end
79
- end
80
- end
81
- else
82
- raise "NOSCRIPT - FakeRedis gem does not include Lua support. Please see spec/spec_helper.rb for more information."
83
- end
84
- end
85
- end
86
- end
87
- end
88
94
 
89
95
  def test_sub(event_name, queue = 'default')
90
96
  matcher = { 'bus_event_type' => event_name }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-bus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Leonard
@@ -30,59 +30,65 @@ dependencies:
30
30
  - !ruby/object:Gem::Version
31
31
  version: '1'
32
32
  - !ruby/object:Gem::Dependency
33
- name: sidekiq
33
+ name: redis
34
34
  requirement: !ruby/object:Gem::Requirement
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: 3.0.0
38
+ version: '4.0'
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
- version: '7.0'
41
+ version: '6.0'
42
42
  type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 3.0.0
48
+ version: '4.0'
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
- version: '7.0'
51
+ version: '6.0'
52
52
  - !ruby/object:Gem::Dependency
53
- name: rack
53
+ name: sidekiq
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 7.0.0
56
59
  - - "<"
57
60
  - !ruby/object:Gem::Version
58
- version: '3.0'
61
+ version: '8.0'
59
62
  type: :runtime
60
63
  prerelease: false
61
64
  version_requirements: !ruby/object:Gem::Requirement
62
65
  requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 7.0.0
63
69
  - - "<"
64
70
  - !ruby/object:Gem::Version
65
- version: '3.0'
71
+ version: '8.0'
66
72
  - !ruby/object:Gem::Dependency
67
73
  name: sidekiq-scheduler
68
74
  requirement: !ruby/object:Gem::Requirement
69
75
  requirements:
70
76
  - - ">="
71
77
  - !ruby/object:Gem::Version
72
- version: '3.0'
78
+ version: '5.0'
73
79
  - - "<"
74
80
  - !ruby/object:Gem::Version
75
- version: '5.0'
81
+ version: '6.0'
76
82
  type: :runtime
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - ">="
81
87
  - !ruby/object:Gem::Version
82
- version: '3.0'
88
+ version: '5.0'
83
89
  - - "<"
84
90
  - !ruby/object:Gem::Version
85
- version: '5.0'
91
+ version: '6.0'
86
92
  - !ruby/object:Gem::Dependency
87
93
  name: rspec
88
94
  requirement: !ruby/object:Gem::Requirement
@@ -97,34 +103,6 @@ dependencies:
97
103
  - - ">="
98
104
  - !ruby/object:Gem::Version
99
105
  version: '0'
100
- - !ruby/object:Gem::Dependency
101
- name: fakeredis
102
- requirement: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- version: '0'
107
- type: :development
108
- prerelease: false
109
- version_requirements: !ruby/object:Gem::Requirement
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- version: '0'
114
- - !ruby/object:Gem::Dependency
115
- name: redis-namespace
116
- requirement: !ruby/object:Gem::Requirement
117
- requirements:
118
- - - ">="
119
- - !ruby/object:Gem::Version
120
- version: '0'
121
- type: :development
122
- prerelease: false
123
- version_requirements: !ruby/object:Gem::Requirement
124
- requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- version: '0'
128
106
  - !ruby/object:Gem::Dependency
129
107
  name: pry
130
108
  requirement: !ruby/object:Gem::Requirement
@@ -200,6 +178,7 @@ files:
200
178
  - MIT-LICENSE
201
179
  - README.mdown
202
180
  - Rakefile
181
+ - docker-compose.yml
203
182
  - lib/sidekiq-bus.rb
204
183
  - lib/sidekiq_bus/adapter.rb
205
184
  - lib/sidekiq_bus/middleware/retry.rb