Skip to content

Fix compatibility with redis-rb 4.6.0#192

Merged
byroot merged 1 commit intoresque:masterfrom
casperisfine:redis-rb-4.6-compat
Mar 7, 2022
Merged

Fix compatibility with redis-rb 4.6.0#192
byroot merged 1 commit intoresque:masterfrom
casperisfine:redis-rb-4.6-compat

Conversation

@casperisfine
Copy link
Copy Markdown
Contributor

Fix: #191
Fix: redis/redis-rb#1069
Fix: redis/redis-rb#1088

In redis-rb 4.6.0, the object yielded by multi and pipelined
is an unsynchronized PipelinedConnection object.

This changed opened a thread safety issue in Redis::Namespace:

  • T1: redis.multi do, sets Namespace#redis = PipelinedConnection
  • T2: any command called before T1 exists the multi block is called on the pipelined connection

cc @ArturT, @sergio91pt (extra testing welcome)

@casperisfine casperisfine force-pushed the redis-rb-4.6-compat branch 2 times, most recently from 5dccf88 to b80aefa Compare March 7, 2022 12:28
Fix: resque#191
Fix: redis/redis-rb#1088

In redis-rb 4.6.0, the object yielded by `multi` and `pipelined`
is an unsynchronized `PipelinedConnection` object.

This changed opened a thread safety issue in Redis::Namespace:

  - T1: `redis.multi do`, sets `Namespace#redis = PipelinedConnection`
  - T2: any command called before T1 exists the `multi` block is called on the pipelined connection
@casperisfine casperisfine force-pushed the redis-rb-4.6-compat branch from b80aefa to 7f76249 Compare March 7, 2022 12:32
@ArturT
Copy link
Copy Markdown

ArturT commented Mar 7, 2022

Thank you @casperisfine . I've tested your fix locally and it does solve the problem.

# Gemfile
source 'https://rubygems.org'

gem 'redis', path: './redis-rb'
#gem 'redis', '4.5.1'
gem 'redis-namespace', path: './redis-namespace' # local copy of this PR branch
#gem 'redis-namespace'
# reproduce_bug.rb
require 'bundler/setup'
require 'redis'
require 'redis-namespace'

puts "Redis gem version: #{Redis::VERSION}"

key = 'a_key'
threads = []
redis = Redis.new(timeout: 5)
redis = Redis::Namespace.new('my-namespace', redis: redis)

index = 0

while true do
  100.times do
    threads << Thread.new do
      100.times do
        redis.multi do |transaction|
          transaction.incr(key)
          transaction.expire(key, 360)
        end
      end
    end
  end

  threads.each(&:join)

  puts "It works! Iteration: #{index}"
  index += 1
end

Output:

$ ruby reproduce_bug.rb

Redis gem version: 4.6.0
It works! Iteration: 0
It works! Iteration: 1
It works! Iteration: 2
...
It works! Iteration: 1498

@byroot byroot merged commit 0769ffa into resque:master Mar 7, 2022
nevans added a commit to nevans/resque that referenced this pull request Jun 21, 2022
Re-using the connection is no longer supported.  Instead, the block var
must be used.

See also:
* redis/redis-rb#1059
* resque/redis-namespace#192
iloveitaly pushed a commit to resque/resque that referenced this pull request Jun 22, 2022
Re-using the connection is no longer supported.  Instead, the block var
must be used.

See also:
* redis/redis-rb#1059
* resque/redis-namespace#192
jwoodrow pushed a commit to moonproject/resque that referenced this pull request Aug 5, 2022
Re-using the connection is no longer supported.  Instead, the block var
must be used.

See also:
* redis/redis-rb#1059
* resque/redis-namespace#192
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants