From 16744040382bbdc12e4498b38dbc31e8f2ac7e0c Mon Sep 17 00:00:00 2001 From: Jian Weihang Date: Thu, 9 Apr 2026 21:14:53 +0800 Subject: [PATCH] feat: support redis v4 In redis v4, the client inside a `Redis` instance is stateful and it will [replace the client](https://github.com/redis/redis-rb/blob/v4.8.1/lib/redis.rb#L225) inside the `Redis#multi` block, which is different from v5. It causes the issue that the `Redis::Future` instance is returned instead of the actual value when calling any command inside the `Redis#multi` block, which is not expected in our case. ```ruby redis.multi do redis.get('foo').class # => Redis::Future in v4 # => NilClass in v5 end ``` --- lib/cover_rage/stores/redis.rb | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/cover_rage/stores/redis.rb b/lib/cover_rage/stores/redis.rb index a3e233b..f7aeacb 100644 --- a/lib/cover_rage/stores/redis.rb +++ b/lib/cover_rage/stores/redis.rb @@ -9,13 +9,10 @@ module CoverRage module Stores class Redis KEY = 'cover_rage_records' + IS_REDIS_BELOW_V5 = Gem::Version.new(::Redis::VERSION) < Gem::Version.new('5') def initialize(url) - @redis = - if url.start_with?('rediss') - ::Redis.new(url:, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }) - else - ::Redis.new(url:) - end + @redis = new_redis(url) + @redis_for_below_v5 = new_redis(url) if IS_REDIS_BELOW_V5 end def transaction(&) @@ -42,7 +39,14 @@ def update(records) end def list - result = @redis.hgetall(KEY) + # For Redis versions below 5, we need to use the separate client to read + # the data while the transaction is in progress. + client = if Thread.current[:redis_multi] && IS_REDIS_BELOW_V5 + @redis_for_below_v5 + else + @redis + end + result = client.hgetall(KEY) return [] if result.empty? result.map { |_, value| Record.new(**JSON.parse(value)) } @@ -51,6 +55,16 @@ def list def clear @redis.del(KEY) end + + private + + def new_redis(url) + if url.start_with?('rediss') + ::Redis.new(url:, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }) + else + ::Redis.new(url:) + end + end end end end