redis-cluster-client 0.7.8 → 0.7.10
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:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b591c92886bf877147317dd04695d2d22354958443f83e386b061b45b0407b28
         | 
| 4 | 
            +
              data.tar.gz: 40a46369e32c60a3c165aff646d3dbd53c3ef427fef6220d4bacc17fc6a97232
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 0e8eda475d22314feb84d16c2d5d75dfe714abecf2c6482a7600c012d02705110c40a0ed7717029a7e8ad154040c6cd44978ffd6b9a2c0350ec33e45d1e1b81e
         | 
| 7 | 
            +
              data.tar.gz: a8fc2bb1febdac9e44c23aaab93ddce567d9ea1fe4ff09f74aa3ebac7eba56efceff44b5f13fea0284d4bec8b2677bd58dfee0eedfebe9cdc4ed9e7d4f6cb6df
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'redis_client'
         | 
| 4 | 
            -
            require 'redis_client/cluster/key_slot_converter'
         | 
| 5 4 | 
             
            require 'redis_client/cluster/transaction'
         | 
| 6 5 |  | 
| 7 6 | 
             
            class RedisClient
         | 
| @@ -12,46 +11,31 @@ class RedisClient | |
| 12 11 | 
             
                  end
         | 
| 13 12 |  | 
| 14 13 | 
             
                  def watch(keys)
         | 
| 15 | 
            -
                     | 
| 16 | 
            -
                     | 
| 17 | 
            -
                    cnt = 0 # We assume redirects occurred when incrementing it.
         | 
| 14 | 
            +
                    slot = find_slot(keys)
         | 
| 15 | 
            +
                    raise ::RedisClient::Cluster::Transaction::ConsistencyError, "unsafe watch: #{keys.join(' ')}" if slot.nil?
         | 
| 18 16 |  | 
| 17 | 
            +
                    node = @router.find_primary_node_by_slot(slot)
         | 
| 19 18 | 
             
                    @router.handle_redirection(node, retry_count: 1) do |nd|
         | 
| 20 | 
            -
                      cnt += 1
         | 
| 21 19 | 
             
                      nd.with do |c|
         | 
| 22 20 | 
             
                        c.call('WATCH', *keys)
         | 
| 23 | 
            -
                         | 
| 21 | 
            +
                        yield(c, slot)
         | 
| 22 | 
            +
                      rescue StandardError
         | 
| 24 23 | 
             
                        c.call('UNWATCH')
         | 
| 25 | 
            -
                         | 
| 24 | 
            +
                        raise
         | 
| 26 25 | 
             
                      end
         | 
| 27 26 | 
             
                    end
         | 
| 28 27 | 
             
                  end
         | 
| 29 28 |  | 
| 30 29 | 
             
                  private
         | 
| 31 30 |  | 
| 32 | 
            -
                  def  | 
| 33 | 
            -
                    return if  | 
| 31 | 
            +
                  def find_slot(keys)
         | 
| 32 | 
            +
                    return if keys.empty?
         | 
| 33 | 
            +
                    return if keys.any? { |k| k.nil? || k.empty? }
         | 
| 34 34 |  | 
| 35 | 
            -
                     | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def safe?(keys)
         | 
| 39 | 
            -
                    return false if keys.empty?
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    slots = keys.map do |k|
         | 
| 42 | 
            -
                      return false if k.nil? || k.empty?
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                      ::RedisClient::Cluster::KeySlotConverter.convert(k)
         | 
| 45 | 
            -
                    end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                    slots.uniq.size == 1
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  def find_node(keys)
         | 
| 51 | 
            -
                    node_key = @router.find_primary_node_key(['WATCH', *keys])
         | 
| 52 | 
            -
                    return @router.find_node(node_key) unless node_key.nil?
         | 
| 35 | 
            +
                    slots = keys.map { |k| @router.find_slot_by_key(k) }
         | 
| 36 | 
            +
                    return if slots.uniq.size != 1
         | 
| 53 37 |  | 
| 54 | 
            -
                     | 
| 38 | 
            +
                    slots.first
         | 
| 55 39 | 
             
                  end
         | 
| 56 40 | 
             
                end
         | 
| 57 41 | 
             
              end
         | 
| @@ -8,6 +8,8 @@ require 'redis_client/cluster/key_slot_converter' | |
| 8 8 | 
             
            require 'redis_client/cluster/node'
         | 
| 9 9 | 
             
            require 'redis_client/cluster/node_key'
         | 
| 10 10 | 
             
            require 'redis_client/cluster/normalized_cmd_name'
         | 
| 11 | 
            +
            require 'redis_client/cluster/transaction'
         | 
| 12 | 
            +
            require 'redis_client/cluster/optimistic_locking'
         | 
| 11 13 |  | 
| 12 14 | 
             
            class RedisClient
         | 
| 13 15 | 
             
              class Cluster
         | 
| @@ -44,6 +46,7 @@ class RedisClient | |
| 44 46 | 
             
                    when 'memory'   then send_memory_command(method, command, args, &block)
         | 
| 45 47 | 
             
                    when 'script'   then send_script_command(method, command, args, &block)
         | 
| 46 48 | 
             
                    when 'pubsub'   then send_pubsub_command(method, command, args, &block)
         | 
| 49 | 
            +
                    when 'watch'    then send_watch_command(command, &block)
         | 
| 47 50 | 
             
                    when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
         | 
| 48 51 | 
             
                      @node.call_all(method, command, args).first.then(&TSF.call(block))
         | 
| 49 52 | 
             
                    when 'flushall', 'flushdb'
         | 
| @@ -179,6 +182,16 @@ class RedisClient | |
| 179 182 | 
             
                    find_node_key_by_key(key, primary: true)
         | 
| 180 183 | 
             
                  end
         | 
| 181 184 |  | 
| 185 | 
            +
                  def find_slot(command)
         | 
| 186 | 
            +
                    find_slot_by_key(@command.extract_first_key(command))
         | 
| 187 | 
            +
                  end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                  def find_slot_by_key(key)
         | 
| 190 | 
            +
                    return if key.empty?
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                    ::RedisClient::Cluster::KeySlotConverter.convert(key)
         | 
| 193 | 
            +
                  end
         | 
| 194 | 
            +
             | 
| 182 195 | 
             
                  def find_node(node_key, retry_count: 3)
         | 
| 183 196 | 
             
                    @node.find_by(node_key)
         | 
| 184 197 | 
             
                  rescue ::RedisClient::Cluster::Node::ReloadNeeded
         | 
| @@ -298,6 +311,17 @@ class RedisClient | |
| 298 311 | 
             
                    end
         | 
| 299 312 | 
             
                  end
         | 
| 300 313 |  | 
| 314 | 
            +
                  # for redis-rb
         | 
| 315 | 
            +
                  def send_watch_command(command)
         | 
| 316 | 
            +
                    ::RedisClient::Cluster::OptimisticLocking.new(self).watch(command[1..]) do |c, slot|
         | 
| 317 | 
            +
                      transaction = ::RedisClient::Cluster::Transaction.new(
         | 
| 318 | 
            +
                        self, @command_builder, node: c, slot: slot
         | 
| 319 | 
            +
                      )
         | 
| 320 | 
            +
                      yield transaction
         | 
| 321 | 
            +
                      transaction.execute
         | 
| 322 | 
            +
                    end
         | 
| 323 | 
            +
                  end
         | 
| 324 | 
            +
             | 
| 301 325 | 
             
                  def update_cluster_info!
         | 
| 302 326 | 
             
                    @node.reload!
         | 
| 303 327 | 
             
                  end
         | 
| @@ -2,7 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'redis_client'
         | 
| 4 4 | 
             
            require 'redis_client/cluster/pipeline'
         | 
| 5 | 
            -
            require 'redis_client/cluster/node_key'
         | 
| 6 5 |  | 
| 7 6 | 
             
            class RedisClient
         | 
| 8 7 | 
             
              class Cluster
         | 
| @@ -10,7 +9,7 @@ class RedisClient | |
| 10 9 | 
             
                  ConsistencyError = Class.new(::RedisClient::Error)
         | 
| 11 10 | 
             
                  MAX_REDIRECTION = 2
         | 
| 12 11 |  | 
| 13 | 
            -
                  def initialize(router, command_builder, node: nil,  | 
| 12 | 
            +
                  def initialize(router, command_builder, node: nil, slot: nil)
         | 
| 14 13 | 
             
                    @router = router
         | 
| 15 14 | 
             
                    @command_builder = command_builder
         | 
| 16 15 | 
             
                    @retryable = true
         | 
| @@ -18,7 +17,7 @@ class RedisClient | |
| 18 17 | 
             
                    @pending_commands = []
         | 
| 19 18 | 
             
                    @node = node
         | 
| 20 19 | 
             
                    prepare_tx unless @node.nil?
         | 
| 21 | 
            -
                    @ | 
| 20 | 
            +
                    @watching_slot = slot
         | 
| 22 21 | 
             
                  end
         | 
| 23 22 |  | 
| 24 23 | 
             
                  def call(*command, **kwargs, &block)
         | 
| @@ -111,7 +110,7 @@ class RedisClient | |
| 111 110 | 
             
                      client.middlewares.call_pipelined(commands, client.config) do
         | 
| 112 111 | 
             
                        connection.call_pipelined(commands, nil)
         | 
| 113 112 | 
             
                      rescue ::RedisClient::CommandError => e
         | 
| 114 | 
            -
                        return handle_command_error!( | 
| 113 | 
            +
                        return handle_command_error!(commands, e, redirect: redirect) unless redirect.zero?
         | 
| 115 114 |  | 
| 116 115 | 
             
                        raise
         | 
| 117 116 | 
             
                      end
         | 
| @@ -140,15 +139,15 @@ class RedisClient | |
| 140 139 | 
             
                    results
         | 
| 141 140 | 
             
                  end
         | 
| 142 141 |  | 
| 143 | 
            -
                  def handle_command_error!( | 
| 142 | 
            +
                  def handle_command_error!(commands, err, redirect:) # rubocop:disable Metrics/AbcSize
         | 
| 144 143 | 
             
                    if err.message.start_with?('CROSSSLOT')
         | 
| 145 144 | 
             
                      raise ConsistencyError, "#{err.message}: #{err.command}"
         | 
| 146 145 | 
             
                    elsif err.message.start_with?('MOVED')
         | 
| 147 | 
            -
                       | 
| 146 | 
            +
                      ensure_the_same_slot!(commands)
         | 
| 148 147 | 
             
                      node = @router.assign_redirection_node(err.message)
         | 
| 149 148 | 
             
                      send_transaction(node, redirect: redirect - 1)
         | 
| 150 149 | 
             
                    elsif err.message.start_with?('ASK')
         | 
| 151 | 
            -
                       | 
| 150 | 
            +
                      ensure_the_same_slot!(commands)
         | 
| 152 151 | 
             
                      node = @router.assign_asking_node(err.message)
         | 
| 153 152 | 
             
                      try_asking(node) ? send_transaction(node, redirect: redirect - 1) : err
         | 
| 154 153 | 
             
                    else
         | 
| @@ -156,12 +155,10 @@ class RedisClient | |
| 156 155 | 
             
                    end
         | 
| 157 156 | 
             
                  end
         | 
| 158 157 |  | 
| 159 | 
            -
                  def  | 
| 160 | 
            -
                     | 
| 161 | 
            -
                     | 
| 162 | 
            -
             | 
| 163 | 
            -
                    return if !@resharding_state && node_keys.size == 1 && node_keys.first == expected_node_key
         | 
| 164 | 
            -
                    return if @resharding_state && node_keys.size == 1
         | 
| 158 | 
            +
                  def ensure_the_same_slot!(commands)
         | 
| 159 | 
            +
                    slots = commands.map { |command| @router.find_slot(command) }.compact.uniq
         | 
| 160 | 
            +
                    return if slots.size == 1 && @watching_slot.nil?
         | 
| 161 | 
            +
                    return if slots.size == 1 && @watching_slot == slots.first
         | 
| 165 162 |  | 
| 166 163 | 
             
                    raise(ConsistencyError, "the transaction should be executed to a slot in a node: #{commands}")
         | 
| 167 164 | 
             
                  end
         | 
    
        data/lib/redis_client/cluster.rb
    CHANGED
    
    | @@ -98,9 +98,9 @@ class RedisClient | |
| 98 98 | 
             
                    return transaction.execute
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| 101 | 
            -
                  ::RedisClient::Cluster::OptimisticLocking.new(@router).watch(watch) do |c,  | 
| 101 | 
            +
                  ::RedisClient::Cluster::OptimisticLocking.new(@router).watch(watch) do |c, slot|
         | 
| 102 102 | 
             
                    transaction = ::RedisClient::Cluster::Transaction.new(
         | 
| 103 | 
            -
                      @router, @command_builder, node: c,  | 
| 103 | 
            +
                      @router, @command_builder, node: c, slot: slot
         | 
| 104 104 | 
             
                    )
         | 
| 105 105 | 
             
                    yield transaction
         | 
| 106 106 | 
             
                    transaction.execute
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: redis-cluster-client
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.7. | 
| 4 | 
            +
              version: 0.7.10
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Taishi Kasuga
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024-02- | 
| 11 | 
            +
            date: 2024-02-20 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: redis-client
         |