redis 4.8.0 → 5.0.8
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 +64 -1
 - data/README.md +101 -161
 - data/lib/redis/client.rb +82 -625
 - data/lib/redis/commands/bitmaps.rb +4 -1
 - data/lib/redis/commands/cluster.rb +1 -18
 - data/lib/redis/commands/connection.rb +5 -10
 - data/lib/redis/commands/geo.rb +3 -3
 - data/lib/redis/commands/hashes.rb +9 -6
 - data/lib/redis/commands/hyper_log_log.rb +1 -1
 - data/lib/redis/commands/keys.rb +5 -23
 - data/lib/redis/commands/lists.rb +74 -25
 - data/lib/redis/commands/pubsub.rb +28 -25
 - data/lib/redis/commands/server.rb +15 -15
 - data/lib/redis/commands/sets.rb +31 -40
 - data/lib/redis/commands/sorted_sets.rb +84 -12
 - data/lib/redis/commands/streams.rb +39 -19
 - data/lib/redis/commands/strings.rb +18 -17
 - data/lib/redis/commands/transactions.rb +7 -31
 - data/lib/redis/commands.rb +4 -7
 - data/lib/redis/distributed.rb +114 -64
 - data/lib/redis/errors.rb +15 -50
 - data/lib/redis/hash_ring.rb +26 -26
 - data/lib/redis/pipeline.rb +43 -222
 - data/lib/redis/subscribe.rb +50 -14
 - data/lib/redis/version.rb +1 -1
 - data/lib/redis.rb +76 -184
 - metadata +10 -54
 - data/lib/redis/cluster/command.rb +0 -79
 - data/lib/redis/cluster/command_loader.rb +0 -33
 - data/lib/redis/cluster/key_slot_converter.rb +0 -72
 - data/lib/redis/cluster/node.rb +0 -120
 - data/lib/redis/cluster/node_key.rb +0 -31
 - data/lib/redis/cluster/node_loader.rb +0 -34
 - data/lib/redis/cluster/option.rb +0 -100
 - data/lib/redis/cluster/slot.rb +0 -86
 - data/lib/redis/cluster/slot_loader.rb +0 -46
 - data/lib/redis/cluster.rb +0 -315
 - data/lib/redis/connection/command_helper.rb +0 -41
 - data/lib/redis/connection/hiredis.rb +0 -68
 - data/lib/redis/connection/registry.rb +0 -13
 - data/lib/redis/connection/ruby.rb +0 -437
 - data/lib/redis/connection/synchrony.rb +0 -148
 - data/lib/redis/connection.rb +0 -11
 
    
        data/lib/redis/pipeline.rb
    CHANGED
    
    | 
         @@ -4,27 +4,30 @@ require "delegate" 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            class Redis
         
     | 
| 
       6 
6 
     | 
    
         
             
              class PipelinedConnection
         
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :db
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(pipeline, futures = [])
         
     | 
| 
       8 
10 
     | 
    
         
             
                  @pipeline = pipeline
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @futures = futures
         
     | 
| 
       9 
12 
     | 
    
         
             
                end
         
     | 
| 
       10 
13 
     | 
    
         | 
| 
       11 
14 
     | 
    
         
             
                include Commands
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                def db
         
     | 
| 
       14 
     | 
    
         
            -
                  @pipeline.db
         
     | 
| 
       15 
     | 
    
         
            -
                end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                def db=(db)
         
     | 
| 
       18 
     | 
    
         
            -
                  @pipeline.db = db
         
     | 
| 
       19 
     | 
    
         
            -
                end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
16 
     | 
    
         
             
                def pipelined
         
     | 
| 
       22 
17 
     | 
    
         
             
                  yield self
         
     | 
| 
       23 
18 
     | 
    
         
             
                end
         
     | 
| 
       24 
19 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                def  
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
       27 
     | 
    
         
            -
                   
     | 
| 
      
 20 
     | 
    
         
            +
                def multi
         
     | 
| 
      
 21 
     | 
    
         
            +
                  transaction = MultiConnection.new(@pipeline, @futures)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  send_command([:multi])
         
     | 
| 
      
 23 
     | 
    
         
            +
                  size = @futures.size
         
     | 
| 
      
 24 
     | 
    
         
            +
                  yield transaction
         
     | 
| 
      
 25 
     | 
    
         
            +
                  multi_future = MultiFuture.new(@futures[size..-1])
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @pipeline.call_v([:exec]) do |result|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    multi_future._set(result)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @futures << multi_future
         
     | 
| 
      
 30 
     | 
    
         
            +
                  multi_future
         
     | 
| 
       28 
31 
     | 
    
         
             
                end
         
     | 
| 
       29 
32 
     | 
    
         | 
| 
       30 
33 
     | 
    
         
             
                private
         
     | 
| 
         @@ -34,204 +37,36 @@ class Redis 
     | 
|
| 
       34 
37 
     | 
    
         
             
                end
         
     | 
| 
       35 
38 
     | 
    
         | 
| 
       36 
39 
     | 
    
         
             
                def send_command(command, &block)
         
     | 
| 
       37 
     | 
    
         
            -
                   
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                def send_blocking_command(command, timeout, &block)
         
     | 
| 
       41 
     | 
    
         
            -
                  @pipeline.call_with_timeout(command, timeout, &block)
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
              end
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
              class Pipeline
         
     | 
| 
       46 
     | 
    
         
            -
                REDIS_INTERNAL_PATH = File.expand_path("..", __dir__).freeze
         
     | 
| 
       47 
     | 
    
         
            -
                # Redis use MonitorMixin#synchronize and this class use DelegateClass which we want to filter out.
         
     | 
| 
       48 
     | 
    
         
            -
                # Both are in the stdlib so we can simply filter the entire stdlib out.
         
     | 
| 
       49 
     | 
    
         
            -
                STDLIB_PATH = File.expand_path("..", MonitorMixin.instance_method(:synchronize).source_location.first).freeze
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                class << self
         
     | 
| 
       52 
     | 
    
         
            -
                  def deprecation_warning(method, caller_locations) # :nodoc:
         
     | 
| 
       53 
     | 
    
         
            -
                    callsite = caller_locations.find { |l| !l.path.start_with?(REDIS_INTERNAL_PATH, STDLIB_PATH) }
         
     | 
| 
       54 
     | 
    
         
            -
                    callsite ||= caller_locations.last # The caller_locations should be large enough, but just in case.
         
     | 
| 
       55 
     | 
    
         
            -
                    ::Redis.deprecate! <<~MESSAGE
         
     | 
| 
       56 
     | 
    
         
            -
                      Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                      redis.#{method} do
         
     | 
| 
       59 
     | 
    
         
            -
                        redis.get("key")
         
     | 
| 
       60 
     | 
    
         
            -
                      end
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                      should be replaced by
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                      redis.#{method} do |pipeline|
         
     | 
| 
       65 
     | 
    
         
            -
                        pipeline.get("key")
         
     | 
| 
       66 
     | 
    
         
            -
                      end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                      (called from #{callsite}}
         
     | 
| 
       69 
     | 
    
         
            -
                    MESSAGE
         
     | 
| 
      
 40 
     | 
    
         
            +
                  future = Future.new(command, block)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @pipeline.call_v(command) do |result|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    future._set(result)
         
     | 
| 
       70 
43 
     | 
    
         
             
                  end
         
     | 
| 
       71 
     | 
    
         
            -
                end
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                attr_accessor :db
         
     | 
| 
       74 
     | 
    
         
            -
                attr_reader :client
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                attr :futures
         
     | 
| 
       77 
     | 
    
         
            -
                alias materialized_futures futures
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                def initialize(client)
         
     | 
| 
       80 
     | 
    
         
            -
                  @client = client.is_a?(Pipeline) ? client.client : client
         
     | 
| 
       81 
     | 
    
         
            -
                  @with_reconnect = true
         
     | 
| 
       82 
     | 
    
         
            -
                  @shutdown = false
         
     | 
| 
       83 
     | 
    
         
            -
                  @futures = []
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def timeout
         
     | 
| 
       87 
     | 
    
         
            -
                  client.timeout
         
     | 
| 
       88 
     | 
    
         
            -
                end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                def with_reconnect?
         
     | 
| 
       91 
     | 
    
         
            -
                  @with_reconnect
         
     | 
| 
       92 
     | 
    
         
            -
                end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                def without_reconnect?
         
     | 
| 
       95 
     | 
    
         
            -
                  !@with_reconnect
         
     | 
| 
       96 
     | 
    
         
            -
                end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                def shutdown?
         
     | 
| 
       99 
     | 
    
         
            -
                  @shutdown
         
     | 
| 
       100 
     | 
    
         
            -
                end
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                def empty?
         
     | 
| 
       103 
     | 
    
         
            -
                  @futures.empty?
         
     | 
| 
       104 
     | 
    
         
            -
                end
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                def call(command, timeout: nil, &block)
         
     | 
| 
       107 
     | 
    
         
            -
                  # A pipeline that contains a shutdown should not raise ECONNRESET when
         
     | 
| 
       108 
     | 
    
         
            -
                  # the connection is gone.
         
     | 
| 
       109 
     | 
    
         
            -
                  @shutdown = true if command.first == :shutdown
         
     | 
| 
       110 
     | 
    
         
            -
                  future = Future.new(command, block, timeout)
         
     | 
| 
       111 
44 
     | 
    
         
             
                  @futures << future
         
     | 
| 
       112 
45 
     | 
    
         
             
                  future
         
     | 
| 
       113 
46 
     | 
    
         
             
                end
         
     | 
| 
       114 
47 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                def  
     | 
| 
       116 
     | 
    
         
            -
                   
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                def call_pipeline(pipeline)
         
     | 
| 
       120 
     | 
    
         
            -
                  @shutdown = true if pipeline.shutdown?
         
     | 
| 
       121 
     | 
    
         
            -
                  @futures.concat(pipeline.materialized_futures)
         
     | 
| 
       122 
     | 
    
         
            -
                  @db = pipeline.db
         
     | 
| 
       123 
     | 
    
         
            -
                  nil
         
     | 
| 
       124 
     | 
    
         
            -
                end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                def commands
         
     | 
| 
       127 
     | 
    
         
            -
                  @futures.map(&:_command)
         
     | 
| 
       128 
     | 
    
         
            -
                end
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                def timeouts
         
     | 
| 
       131 
     | 
    
         
            -
                  @futures.map(&:timeout)
         
     | 
| 
       132 
     | 
    
         
            -
                end
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                def with_reconnect(val = true)
         
     | 
| 
       135 
     | 
    
         
            -
                  @with_reconnect = false unless val
         
     | 
| 
       136 
     | 
    
         
            -
                  yield
         
     | 
| 
       137 
     | 
    
         
            -
                end
         
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
                def without_reconnect(&blk)
         
     | 
| 
       140 
     | 
    
         
            -
                  with_reconnect(false, &blk)
         
     | 
| 
       141 
     | 
    
         
            -
                end
         
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                def finish(replies, &blk)
         
     | 
| 
       144 
     | 
    
         
            -
                  if blk
         
     | 
| 
       145 
     | 
    
         
            -
                    futures.each_with_index.map do |future, i|
         
     | 
| 
       146 
     | 
    
         
            -
                      future._set(blk.call(replies[i]))
         
     | 
| 
       147 
     | 
    
         
            -
                    end
         
     | 
| 
       148 
     | 
    
         
            -
                  else
         
     | 
| 
       149 
     | 
    
         
            -
                    futures.each_with_index.map do |future, i|
         
     | 
| 
       150 
     | 
    
         
            -
                      future._set(replies[i])
         
     | 
| 
       151 
     | 
    
         
            -
                    end
         
     | 
| 
       152 
     | 
    
         
            -
                  end
         
     | 
| 
       153 
     | 
    
         
            -
                end
         
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
                class Multi < self
         
     | 
| 
       156 
     | 
    
         
            -
                  def finish(replies)
         
     | 
| 
       157 
     | 
    
         
            -
                    exec = replies.last
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
                    return if exec.nil? # The transaction failed because of WATCH.
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                    # EXEC command failed.
         
     | 
| 
       162 
     | 
    
         
            -
                    raise exec if exec.is_a?(CommandError)
         
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
                    if exec.size < futures.size
         
     | 
| 
       165 
     | 
    
         
            -
                      # Some command wasn't recognized by Redis.
         
     | 
| 
       166 
     | 
    
         
            -
                      command_error = replies.detect { |r| r.is_a?(CommandError) }
         
     | 
| 
       167 
     | 
    
         
            -
                      raise command_error
         
     | 
| 
       168 
     | 
    
         
            -
                    end
         
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
                    super(exec) do |reply|
         
     | 
| 
       171 
     | 
    
         
            -
                      # Because an EXEC returns nested replies, hiredis won't be able to
         
     | 
| 
       172 
     | 
    
         
            -
                      # convert an error reply to a CommandError instance itself. This is
         
     | 
| 
       173 
     | 
    
         
            -
                      # specific to MULTI/EXEC, so we solve this here.
         
     | 
| 
       174 
     | 
    
         
            -
                      reply.is_a?(::RuntimeError) ? CommandError.new(reply.message) : reply
         
     | 
| 
       175 
     | 
    
         
            -
                    end
         
     | 
| 
       176 
     | 
    
         
            -
                  end
         
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                  def materialized_futures
         
     | 
| 
       179 
     | 
    
         
            -
                    if empty?
         
     | 
| 
       180 
     | 
    
         
            -
                      []
         
     | 
| 
       181 
     | 
    
         
            -
                    else
         
     | 
| 
       182 
     | 
    
         
            -
                      [
         
     | 
| 
       183 
     | 
    
         
            -
                        Future.new([:multi], nil, 0),
         
     | 
| 
       184 
     | 
    
         
            -
                        *futures,
         
     | 
| 
       185 
     | 
    
         
            -
                        MultiFuture.new(futures)
         
     | 
| 
       186 
     | 
    
         
            -
                      ]
         
     | 
| 
       187 
     | 
    
         
            -
                    end
         
     | 
| 
       188 
     | 
    
         
            -
                  end
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
                  def timeouts
         
     | 
| 
       191 
     | 
    
         
            -
                    if empty?
         
     | 
| 
       192 
     | 
    
         
            -
                      []
         
     | 
| 
       193 
     | 
    
         
            -
                    else
         
     | 
| 
       194 
     | 
    
         
            -
                      [nil, *super, nil]
         
     | 
| 
       195 
     | 
    
         
            -
                    end
         
     | 
| 
       196 
     | 
    
         
            -
                  end
         
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
                  def commands
         
     | 
| 
       199 
     | 
    
         
            -
                    if empty?
         
     | 
| 
       200 
     | 
    
         
            -
                      []
         
     | 
| 
       201 
     | 
    
         
            -
                    else
         
     | 
| 
       202 
     | 
    
         
            -
                      [[:multi]] + super + [[:exec]]
         
     | 
| 
       203 
     | 
    
         
            -
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                def send_blocking_command(command, timeout, &block)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  future = Future.new(command, block)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @pipeline.blocking_call_v(timeout, command) do |result|
         
     | 
| 
      
 51 
     | 
    
         
            +
                    future._set(result)
         
     | 
| 
       204 
52 
     | 
    
         
             
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @futures << future
         
     | 
| 
      
 54 
     | 
    
         
            +
                  future
         
     | 
| 
       205 
55 
     | 
    
         
             
                end
         
     | 
| 
       206 
56 
     | 
    
         
             
              end
         
     | 
| 
       207 
57 
     | 
    
         | 
| 
       208 
     | 
    
         
            -
              class  
     | 
| 
       209 
     | 
    
         
            -
                def  
     | 
| 
       210 
     | 
    
         
            -
                   
     | 
| 
       211 
     | 
    
         
            -
                  @deprecation_displayed = false
         
     | 
| 
      
 58 
     | 
    
         
            +
              class MultiConnection < PipelinedConnection
         
     | 
| 
      
 59 
     | 
    
         
            +
                def multi
         
     | 
| 
      
 60 
     | 
    
         
            +
                  raise Redis::Error, "Can't nest multi transaction"
         
     | 
| 
       212 
61 
     | 
    
         
             
                end
         
     | 
| 
       213 
62 
     | 
    
         | 
| 
       214 
     | 
    
         
            -
                 
     | 
| 
       215 
     | 
    
         
            -
                  unless @deprecation_displayed
         
     | 
| 
       216 
     | 
    
         
            -
                    Pipeline.deprecation_warning("pipelined", Kernel.caller_locations(1, 10))
         
     | 
| 
       217 
     | 
    
         
            -
                    @deprecation_displayed = true
         
     | 
| 
       218 
     | 
    
         
            -
                  end
         
     | 
| 
       219 
     | 
    
         
            -
                  @delegate_dc_obj
         
     | 
| 
       220 
     | 
    
         
            -
                end
         
     | 
| 
       221 
     | 
    
         
            -
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
                private
         
     | 
| 
       222 
64 
     | 
    
         | 
| 
       223 
     | 
    
         
            -
             
     | 
| 
       224 
     | 
    
         
            -
                 
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
       226 
     | 
    
         
            -
             
     | 
| 
       227 
     | 
    
         
            -
             
     | 
| 
       228 
     | 
    
         
            -
             
     | 
| 
       229 
     | 
    
         
            -
                def __getobj__
         
     | 
| 
       230 
     | 
    
         
            -
                  unless @deprecation_displayed
         
     | 
| 
       231 
     | 
    
         
            -
                    Pipeline.deprecation_warning("multi", Kernel.caller_locations(1, 10))
         
     | 
| 
       232 
     | 
    
         
            -
                    @deprecation_displayed = true
         
     | 
| 
       233 
     | 
    
         
            -
                  end
         
     | 
| 
       234 
     | 
    
         
            -
                  @delegate_dc_obj
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Blocking commands inside transaction behave like non-blocking.
         
     | 
| 
      
 66 
     | 
    
         
            +
                # It shouldn't be done though.
         
     | 
| 
      
 67 
     | 
    
         
            +
                # https://redis.io/commands/blpop/#blpop-inside-a-multi--exec-transaction
         
     | 
| 
      
 68 
     | 
    
         
            +
                def send_blocking_command(command, _timeout, &block)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  send_command(command, &block)
         
     | 
| 
       235 
70 
     | 
    
         
             
                end
         
     | 
| 
       236 
71 
     | 
    
         
             
              end
         
     | 
| 
       237 
72 
     | 
    
         | 
| 
         @@ -244,23 +79,10 @@ class Redis 
     | 
|
| 
       244 
79 
     | 
    
         
             
              class Future < BasicObject
         
     | 
| 
       245 
80 
     | 
    
         
             
                FutureNotReady = ::Redis::FutureNotReady.new
         
     | 
| 
       246 
81 
     | 
    
         | 
| 
       247 
     | 
    
         
            -
                 
     | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
       249 
     | 
    
         
            -
                def initialize(command, transformation, timeout)
         
     | 
| 
      
 82 
     | 
    
         
            +
                def initialize(command, coerce)
         
     | 
| 
       250 
83 
     | 
    
         
             
                  @command = command
         
     | 
| 
       251 
     | 
    
         
            -
                  @transformation = transformation
         
     | 
| 
       252 
     | 
    
         
            -
                  @timeout = timeout
         
     | 
| 
       253 
84 
     | 
    
         
             
                  @object = FutureNotReady
         
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
       255 
     | 
    
         
            -
             
     | 
| 
       256 
     | 
    
         
            -
                def ==(_other)
         
     | 
| 
       257 
     | 
    
         
            -
                  message = +"The methods == and != are deprecated for Redis::Future and will be removed in 5.0.0"
         
     | 
| 
       258 
     | 
    
         
            -
                  message << " - You probably meant to call .value == or .value !="
         
     | 
| 
       259 
     | 
    
         
            -
                  message << " (#{::Kernel.caller(1, 1).first})\n"
         
     | 
| 
       260 
     | 
    
         
            -
             
     | 
| 
       261 
     | 
    
         
            -
                  ::Redis.deprecate!(message)
         
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
     | 
    
         
            -
                  super
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @coerce = coerce
         
     | 
| 
       264 
86 
     | 
    
         
             
                end
         
     | 
| 
       265 
87 
     | 
    
         | 
| 
       266 
88 
     | 
    
         
             
                def inspect
         
     | 
| 
         @@ -268,16 +90,12 @@ class Redis 
     | 
|
| 
       268 
90 
     | 
    
         
             
                end
         
     | 
| 
       269 
91 
     | 
    
         | 
| 
       270 
92 
     | 
    
         
             
                def _set(object)
         
     | 
| 
       271 
     | 
    
         
            -
                  @object = @ 
     | 
| 
      
 93 
     | 
    
         
            +
                  @object = @coerce ? @coerce.call(object) : object
         
     | 
| 
       272 
94 
     | 
    
         
             
                  value
         
     | 
| 
       273 
95 
     | 
    
         
             
                end
         
     | 
| 
       274 
96 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
                def _command
         
     | 
| 
       276 
     | 
    
         
            -
                  @command
         
     | 
| 
       277 
     | 
    
         
            -
                end
         
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
97 
     | 
    
         
             
                def value
         
     | 
| 
       280 
     | 
    
         
            -
                  ::Kernel.raise(@object) if @object.is_a?(:: 
     | 
| 
      
 98 
     | 
    
         
            +
                  ::Kernel.raise(@object) if @object.is_a?(::StandardError)
         
     | 
| 
       281 
99 
     | 
    
         
             
                  @object
         
     | 
| 
       282 
100 
     | 
    
         
             
                end
         
     | 
| 
       283 
101 
     | 
    
         | 
| 
         @@ -294,13 +112,16 @@ class Redis 
     | 
|
| 
       294 
112 
     | 
    
         
             
                def initialize(futures)
         
     | 
| 
       295 
113 
     | 
    
         
             
                  @futures = futures
         
     | 
| 
       296 
114 
     | 
    
         
             
                  @command = [:exec]
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @object = FutureNotReady
         
     | 
| 
       297 
116 
     | 
    
         
             
                end
         
     | 
| 
       298 
117 
     | 
    
         | 
| 
       299 
118 
     | 
    
         
             
                def _set(replies)
         
     | 
| 
       300 
     | 
    
         
            -
                   
     | 
| 
       301 
     | 
    
         
            -
                    future 
     | 
| 
      
 119 
     | 
    
         
            +
                  if replies
         
     | 
| 
      
 120 
     | 
    
         
            +
                    @futures.each_with_index do |future, index|
         
     | 
| 
      
 121 
     | 
    
         
            +
                      future._set(replies[index])
         
     | 
| 
      
 122 
     | 
    
         
            +
                    end
         
     | 
| 
       302 
123 
     | 
    
         
             
                  end
         
     | 
| 
       303 
     | 
    
         
            -
                  replies
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @object = replies
         
     | 
| 
       304 
125 
     | 
    
         
             
                end
         
     | 
| 
       305 
126 
     | 
    
         
             
              end
         
     | 
| 
       306 
127 
     | 
    
         
             
            end
         
     | 
    
        data/lib/redis/subscribe.rb
    CHANGED
    
    | 
         @@ -4,10 +4,13 @@ class Redis 
     | 
|
| 
       4 
4 
     | 
    
         
             
              class SubscribedClient
         
     | 
| 
       5 
5 
     | 
    
         
             
                def initialize(client)
         
     | 
| 
       6 
6 
     | 
    
         
             
                  @client = client
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @write_monitor = Monitor.new
         
     | 
| 
       7 
8 
     | 
    
         
             
                end
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                def  
     | 
| 
       10 
     | 
    
         
            -
                  @ 
     | 
| 
      
 10 
     | 
    
         
            +
                def call_v(command)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @write_monitor.synchronize do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @client.call_v(command)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
       11 
14 
     | 
    
         
             
                end
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
16 
     | 
    
         
             
                def subscribe(*channels, &block)
         
     | 
| 
         @@ -26,12 +29,28 @@ class Redis 
     | 
|
| 
       26 
29 
     | 
    
         
             
                  subscription("psubscribe", "punsubscribe", channels, block, timeout)
         
     | 
| 
       27 
30 
     | 
    
         
             
                end
         
     | 
| 
       28 
31 
     | 
    
         | 
| 
      
 32 
     | 
    
         
            +
                def ssubscribe(*channels, &block)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  subscription("ssubscribe", "sunsubscribe", channels, block)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def ssubscribe_with_timeout(timeout, *channels, &block)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  subscription("ssubscribe", "sunsubscribe", channels, block, timeout)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       29 
40 
     | 
    
         
             
                def unsubscribe(*channels)
         
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
      
 41 
     | 
    
         
            +
                  call_v([:unsubscribe, *channels])
         
     | 
| 
       31 
42 
     | 
    
         
             
                end
         
     | 
| 
       32 
43 
     | 
    
         | 
| 
       33 
44 
     | 
    
         
             
                def punsubscribe(*channels)
         
     | 
| 
       34 
     | 
    
         
            -
                   
     | 
| 
      
 45 
     | 
    
         
            +
                  call_v([:punsubscribe, *channels])
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def sunsubscribe(*channels)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  call_v([:sunsubscribe, *channels])
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def close
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @client.close
         
     | 
| 
       35 
54 
     | 
    
         
             
                end
         
     | 
| 
       36 
55 
     | 
    
         | 
| 
       37 
56 
     | 
    
         
             
                protected
         
     | 
| 
         @@ -39,13 +58,21 @@ class Redis 
     | 
|
| 
       39 
58 
     | 
    
         
             
                def subscription(start, stop, channels, block, timeout = 0)
         
     | 
| 
       40 
59 
     | 
    
         
             
                  sub = Subscription.new(&block)
         
     | 
| 
       41 
60 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                   
     | 
| 
      
 61 
     | 
    
         
            +
                  case start
         
     | 
| 
      
 62 
     | 
    
         
            +
                  when "ssubscribe" then channels.each { |c| call_v([start, c]) } # avoid cross-slot keys
         
     | 
| 
      
 63 
     | 
    
         
            +
                  else call_v([start, *channels])
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
       43 
65 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                  @client. 
     | 
| 
       45 
     | 
    
         
            -
                     
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                     
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                  while event = @client.next_event(timeout)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    if event.is_a?(::RedisClient::CommandError)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      raise Client::ERROR_MAPPING.fetch(event.class), event.message
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    type, *rest = event
         
     | 
| 
      
 72 
     | 
    
         
            +
                    if callback = sub.callbacks[type]
         
     | 
| 
      
 73 
     | 
    
         
            +
                      callback.call(*rest)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    break if type == stop && rest.last == 0
         
     | 
| 
       49 
76 
     | 
    
         
             
                  end
         
     | 
| 
       50 
77 
     | 
    
         
             
                  # No need to unsubscribe here. The real client closes the connection
         
     | 
| 
       51 
78 
     | 
    
         
             
                  # whenever an exception is raised (see #ensure_connected).
         
     | 
| 
         @@ -56,10 +83,7 @@ class Redis 
     | 
|
| 
       56 
83 
     | 
    
         
             
                attr :callbacks
         
     | 
| 
       57 
84 
     | 
    
         | 
| 
       58 
85 
     | 
    
         
             
                def initialize
         
     | 
| 
       59 
     | 
    
         
            -
                  @callbacks =  
     | 
| 
       60 
     | 
    
         
            -
                    hash[key] = ->(*_) {}
         
     | 
| 
       61 
     | 
    
         
            -
                  end
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
      
 86 
     | 
    
         
            +
                  @callbacks = {}
         
     | 
| 
       63 
87 
     | 
    
         
             
                  yield(self)
         
     | 
| 
       64 
88 
     | 
    
         
             
                end
         
     | 
| 
       65 
89 
     | 
    
         | 
| 
         @@ -86,5 +110,17 @@ class Redis 
     | 
|
| 
       86 
110 
     | 
    
         
             
                def pmessage(&block)
         
     | 
| 
       87 
111 
     | 
    
         
             
                  @callbacks["pmessage"] = block
         
     | 
| 
       88 
112 
     | 
    
         
             
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                def ssubscribe(&block)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @callbacks["ssubscribe"] = block
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def sunsubscribe(&block)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @callbacks["sunsubscribe"] = block
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                def smessage(&block)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  @callbacks["smessage"] = block
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
       89 
125 
     | 
    
         
             
              end
         
     | 
| 
       90 
126 
     | 
    
         
             
            end
         
     | 
    
        data/lib/redis/version.rb
    CHANGED