redis 4.6.0 → 5.0.0.beta3

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -1
  3. data/README.md +77 -146
  4. data/lib/redis/client.rb +78 -615
  5. data/lib/redis/commands/bitmaps.rb +4 -1
  6. data/lib/redis/commands/cluster.rb +1 -18
  7. data/lib/redis/commands/connection.rb +5 -10
  8. data/lib/redis/commands/hashes.rb +6 -3
  9. data/lib/redis/commands/hyper_log_log.rb +1 -1
  10. data/lib/redis/commands/keys.rb +52 -26
  11. data/lib/redis/commands/lists.rb +10 -14
  12. data/lib/redis/commands/pubsub.rb +7 -9
  13. data/lib/redis/commands/server.rb +14 -14
  14. data/lib/redis/commands/sets.rb +42 -35
  15. data/lib/redis/commands/sorted_sets.rb +13 -3
  16. data/lib/redis/commands/streams.rb +12 -10
  17. data/lib/redis/commands/strings.rb +1 -0
  18. data/lib/redis/commands/transactions.rb +26 -3
  19. data/lib/redis/commands.rb +1 -8
  20. data/lib/redis/distributed.rb +99 -66
  21. data/lib/redis/errors.rb +10 -43
  22. data/lib/redis/hash_ring.rb +26 -26
  23. data/lib/redis/pipeline.rb +56 -203
  24. data/lib/redis/subscribe.rb +15 -9
  25. data/lib/redis/version.rb +1 -1
  26. data/lib/redis.rb +69 -175
  27. metadata +13 -57
  28. data/lib/redis/cluster/command.rb +0 -79
  29. data/lib/redis/cluster/command_loader.rb +0 -33
  30. data/lib/redis/cluster/key_slot_converter.rb +0 -72
  31. data/lib/redis/cluster/node.rb +0 -120
  32. data/lib/redis/cluster/node_key.rb +0 -31
  33. data/lib/redis/cluster/node_loader.rb +0 -37
  34. data/lib/redis/cluster/option.rb +0 -93
  35. data/lib/redis/cluster/slot.rb +0 -86
  36. data/lib/redis/cluster/slot_loader.rb +0 -49
  37. data/lib/redis/cluster.rb +0 -315
  38. data/lib/redis/connection/command_helper.rb +0 -41
  39. data/lib/redis/connection/hiredis.rb +0 -68
  40. data/lib/redis/connection/registry.rb +0 -13
  41. data/lib/redis/connection/ruby.rb +0 -431
  42. data/lib/redis/connection/synchrony.rb +0 -148
  43. data/lib/redis/connection.rb +0 -11
data/lib/redis.rb CHANGED
@@ -6,26 +6,11 @@ require "redis/commands"
6
6
 
7
7
  class Redis
8
8
  BASE_PATH = __dir__
9
- @exists_returns_integer = true
10
-
11
9
  Deprecated = Class.new(StandardError)
12
10
 
13
11
  class << self
14
- attr_reader :exists_returns_integer
15
12
  attr_accessor :silence_deprecations, :raise_deprecations
16
13
 
17
- def exists_returns_integer=(value)
18
- unless value
19
- deprecate!(
20
- "`Redis#exists(key)` will return an Integer by default in redis-rb 4.3. The option to explicitly " \
21
- "disable this behaviour via `Redis.exists_returns_integer` will be removed in 5.0. You should use " \
22
- "`exists?` instead."
23
- )
24
- end
25
-
26
- @exists_returns_integer = value
27
- end
28
-
29
14
  def deprecate!(message)
30
15
  unless silence_deprecations
31
16
  if raise_deprecations
@@ -35,20 +20,12 @@ class Redis
35
20
  end
36
21
  end
37
22
  end
38
-
39
- def current
40
- deprecate!("`Redis.current=` is deprecated and will be removed in 5.0. (called from: #{caller(1, 1).first})")
41
- @current ||= Redis.new
42
- end
43
-
44
- def current=(redis)
45
- deprecate!("`Redis.current=` is deprecated and will be removed in 5.0. (called from: #{caller(1, 1).first})")
46
- @current = redis
47
- end
48
23
  end
49
24
 
50
25
  include Commands
51
26
 
27
+ SERVER_URL_OPTIONS = %i(url host port path).freeze
28
+
52
29
  # Create a new client instance
53
30
  #
54
31
  # @param [Hash] options
@@ -62,174 +39,66 @@ class Redis
62
39
  # @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
63
40
  # @option options [String] :username Username to authenticate against server
64
41
  # @option options [String] :password Password to authenticate against server
65
- # @option options [Integer] :db (0) Database to select after initial connect
66
- # @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`, `:synchrony`
42
+ # @option options [Integer] :db (0) Database to select after connect and on reconnects
43
+ # @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`
67
44
  # @option options [String] :id ID for the client connection, assigns name to current connection by sending
68
45
  # `CLIENT SETNAME`
69
- # @option options [Hash, Integer] :tcp_keepalive Keepalive values, if Integer `intvl` and `probe` are calculated
70
- # based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Integer
71
- # @option options [Integer] :reconnect_attempts Number of attempts trying to connect
46
+ # @option options [Integer, Array<Integer, Float>] :reconnect_attempts Number of attempts trying to connect,
47
+ # or a list of sleep duration between attempts.
72
48
  # @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
49
+ # @option options [String] :name The name of the server group to connect to.
73
50
  # @option options [Array] :sentinels List of sentinels to contact
74
- # @option options [Symbol] :role (:master) Role to fetch via Sentinel, either `:master` or `:slave`
75
- # @option options [Array<String, Hash{Symbol => String, Integer}>] :cluster List of cluster nodes to contact
76
- # @option options [Boolean] :replica Whether to use readonly replica nodes in Redis Cluster or not
77
- # @option options [Class] :connector Class of custom connector
78
51
  #
79
52
  # @return [Redis] a new client instance
80
53
  def initialize(options = {})
81
- @options = options.dup
82
- @cluster_mode = options.key?(:cluster)
83
- client = @cluster_mode ? Cluster : Client
84
- @original_client = @client = client.new(options)
85
- @queue = Hash.new { |h, k| h[k] = [] }
86
54
  @monitor = Monitor.new
87
- end
88
-
89
- # Run code with the client reconnecting
90
- def with_reconnect(val = true, &blk)
91
- synchronize do |client|
92
- client.with_reconnect(val, &blk)
55
+ @options = options.dup
56
+ @options[:reconnect_attempts] = 1 unless @options.key?(:reconnect_attempts)
57
+ if ENV["REDIS_URL"] && SERVER_URL_OPTIONS.none? { |o| @options.key?(o) }
58
+ @options[:url] = ENV["REDIS_URL"]
93
59
  end
60
+ inherit_socket = @options.delete(:inherit_socket)
61
+ @subscription_client = nil
62
+
63
+ @client = initialize_client(@options)
64
+ @client.inherit_socket! if inherit_socket
94
65
  end
95
66
 
96
67
  # Run code without the client reconnecting
97
- def without_reconnect(&blk)
98
- with_reconnect(false, &blk)
68
+ def without_reconnect(&block)
69
+ @client.disable_reconnection(&block)
99
70
  end
100
71
 
101
72
  # Test whether or not the client is connected
102
73
  def connected?
103
- @original_client.connected?
74
+ @client.connected? || @subscription_client&.connected?
104
75
  end
105
76
 
106
77
  # Disconnect the client as quickly and silently as possible.
107
78
  def close
108
- @original_client.disconnect
79
+ @client.close
80
+ @subscription_client&.close
109
81
  end
110
82
  alias disconnect! close
111
83
 
112
- # @deprecated Queues a command for pipelining.
113
- #
114
- # Commands in the queue are executed with the Redis#commit method.
115
- #
116
- # See http://redis.io/topics/pipelining for more details.
117
- #
118
- def queue(*command)
119
- ::Redis.deprecate!(
120
- "Redis#queue is deprecated and will be removed in Redis 5.0.0. Use Redis#pipelined instead." \
121
- "(called from: #{caller(1, 1).first})"
122
- )
123
-
124
- synchronize do
125
- @queue[Thread.current.object_id] << command
126
- end
127
- end
128
-
129
- # @deprecated Sends all commands in the queue.
130
- #
131
- # See http://redis.io/topics/pipelining for more details.
132
- #
133
- def commit
134
- ::Redis.deprecate!(
135
- "Redis#commit is deprecated and will be removed in Redis 5.0.0. Use Redis#pipelined instead. " \
136
- "(called from: #{Kernel.caller(1, 1).first})"
137
- )
138
-
139
- synchronize do |client|
140
- begin
141
- pipeline = Pipeline.new(client)
142
- @queue[Thread.current.object_id].each do |command|
143
- pipeline.call(command)
144
- end
145
-
146
- client.call_pipelined(pipeline)
147
- ensure
148
- @queue.delete(Thread.current.object_id)
149
- end
150
- end
84
+ def with
85
+ yield self
151
86
  end
152
87
 
153
88
  def _client
154
89
  @client
155
90
  end
156
91
 
157
- def pipelined(&block)
158
- deprecation_displayed = false
159
- if block&.arity == 0
160
- Pipeline.deprecation_warning("pipelined", Kernel.caller_locations(1, 5))
161
- deprecation_displayed = true
162
- end
163
-
164
- synchronize do |prior_client|
165
- begin
166
- pipeline = Pipeline.new(prior_client)
167
- @client = deprecation_displayed ? pipeline : DeprecatedPipeline.new(pipeline)
168
- pipelined_connection = PipelinedConnection.new(pipeline)
169
- yield pipelined_connection
170
- prior_client.call_pipeline(pipeline)
171
- ensure
172
- @client = prior_client
173
- end
174
- end
175
- end
176
-
177
- # Mark the start of a transaction block.
178
- #
179
- # Passing a block is optional.
180
- #
181
- # @example With a block
182
- # redis.multi do |multi|
183
- # multi.set("key", "value")
184
- # multi.incr("counter")
185
- # end # => ["OK", 6]
186
- #
187
- # @example Without a block
188
- # redis.multi
189
- # # => "OK"
190
- # redis.set("key", "value")
191
- # # => "QUEUED"
192
- # redis.incr("counter")
193
- # # => "QUEUED"
194
- # redis.exec
195
- # # => ["OK", 6]
196
- #
197
- # @yield [multi] the commands that are called inside this block are cached
198
- # and written to the server upon returning from it
199
- # @yieldparam [Redis] multi `self`
200
- #
201
- # @return [String, Array<...>]
202
- # - when a block is not given, `OK`
203
- # - when a block is given, an array with replies
204
- #
205
- # @see #watch
206
- # @see #unwatch
207
- def multi(&block)
208
- if block_given?
209
- deprecation_displayed = false
210
- if block&.arity == 0
211
- Pipeline.deprecation_warning("multi", Kernel.caller_locations(1, 5))
212
- deprecation_displayed = true
213
- end
214
-
215
- synchronize do |prior_client|
216
- begin
217
- pipeline = Pipeline::Multi.new(prior_client)
218
- @client = deprecation_displayed ? pipeline : DeprecatedMulti.new(pipeline)
219
- pipelined_connection = PipelinedConnection.new(pipeline)
220
- yield pipelined_connection
221
- prior_client.call_pipeline(pipeline)
222
- ensure
223
- @client = prior_client
224
- end
92
+ def pipelined
93
+ synchronize do |client|
94
+ client.pipelined do |raw_pipeline|
95
+ yield PipelinedConnection.new(raw_pipeline)
225
96
  end
226
- else
227
- send_command([:multi])
228
97
  end
229
98
  end
230
99
 
231
100
  def id
232
- @original_client.id
101
+ @client.id || @client.server_url
233
102
  end
234
103
 
235
104
  def inspect
@@ -241,54 +110,79 @@ class Redis
241
110
  end
242
111
 
243
112
  def connection
244
- return @original_client.connection_info if @cluster_mode
245
-
246
113
  {
247
- host: @original_client.host,
248
- port: @original_client.port,
249
- db: @original_client.db,
250
- id: @original_client.id,
251
- location: @original_client.location
114
+ host: @client.host,
115
+ port: @client.port,
116
+ db: @client.db,
117
+ id: id,
118
+ location: "#{@client.host}:#{@client.port}"
252
119
  }
253
120
  end
254
121
 
255
122
  private
256
123
 
124
+ def initialize_client(options)
125
+ if options.key?(:cluster)
126
+ raise "Redis Cluster support was moved to the `redis_cluster` gem."
127
+ end
128
+
129
+ if options.key?(:sentinels)
130
+ if url = options.delete(:url)
131
+ uri = URI.parse(url)
132
+ if !options.key?(:name) && uri.host
133
+ options[:name] = uri.host
134
+ end
135
+
136
+ if !options.key?(:password) && uri.password && !uri.password.empty?
137
+ options[:password] = uri.password
138
+ end
139
+
140
+ if !options.key?(:username) && uri.user && !uri.user.empty?
141
+ options[:username] = uri.user
142
+ end
143
+ end
144
+
145
+ Client.sentinel(**options).new_client
146
+ else
147
+ Client.config(**options).new_client
148
+ end
149
+ end
150
+
257
151
  def synchronize
258
152
  @monitor.synchronize { yield(@client) }
259
153
  end
260
154
 
261
155
  def send_command(command, &block)
262
156
  @monitor.synchronize do
263
- @client.call(command, &block)
157
+ @client.call_v(command, &block)
264
158
  end
265
159
  end
266
160
 
267
161
  def send_blocking_command(command, timeout, &block)
268
162
  @monitor.synchronize do
269
- @client.call_with_timeout(command, timeout, &block)
163
+ @client.blocking_call_v(timeout, command, &block)
270
164
  end
271
165
  end
272
166
 
273
167
  def _subscription(method, timeout, channels, block)
274
- return @client.call([method] + channels) if subscribed?
168
+ if @subscription_client
169
+ return @subscription_client.call_v([method] + channels)
170
+ end
275
171
 
276
172
  begin
277
- original, @client = @client, SubscribedClient.new(@client)
173
+ @subscription_client = SubscribedClient.new(@client.pubsub)
278
174
  if timeout > 0
279
- @client.send(method, timeout, *channels, &block)
175
+ @subscription_client.send(method, timeout, *channels, &block)
280
176
  else
281
- @client.send(method, *channels, &block)
177
+ @subscription_client.send(method, *channels, &block)
282
178
  end
283
179
  ensure
284
- @client = original
180
+ @subscription_client = nil
285
181
  end
286
182
  end
287
183
  end
288
184
 
289
185
  require "redis/version"
290
- require "redis/connection"
291
186
  require "redis/client"
292
- require "redis/cluster"
293
187
  require "redis/pipeline"
294
188
  require "redis/subscribe"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.0
4
+ version: 5.0.0.beta3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Zygmuntowicz
@@ -16,50 +16,22 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2022-02-02 00:00:00.000000000 Z
19
+ date: 2022-08-18 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: em-synchrony
22
+ name: redis-client
23
23
  requirement: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '0'
28
- type: :development
27
+ version: '0.7'
28
+ type: :runtime
29
29
  prerelease: false
30
30
  version_requirements: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
35
- - !ruby/object:Gem::Dependency
36
- name: hiredis
37
- requirement: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
- type: :development
43
- prerelease: false
44
- version_requirements: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- - !ruby/object:Gem::Dependency
50
- name: mocha
51
- requirement: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
56
- type: :development
57
- prerelease: false
58
- version_requirements: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: '0'
34
+ version: '0.7'
63
35
  description: |2
64
36
  A Ruby client that tries to match Redis' API one-to-one, while still
65
37
  providing an idiomatic interface.
@@ -74,16 +46,6 @@ files:
74
46
  - README.md
75
47
  - lib/redis.rb
76
48
  - lib/redis/client.rb
77
- - lib/redis/cluster.rb
78
- - lib/redis/cluster/command.rb
79
- - lib/redis/cluster/command_loader.rb
80
- - lib/redis/cluster/key_slot_converter.rb
81
- - lib/redis/cluster/node.rb
82
- - lib/redis/cluster/node_key.rb
83
- - lib/redis/cluster/node_loader.rb
84
- - lib/redis/cluster/option.rb
85
- - lib/redis/cluster/slot.rb
86
- - lib/redis/cluster/slot_loader.rb
87
49
  - lib/redis/commands.rb
88
50
  - lib/redis/commands/bitmaps.rb
89
51
  - lib/redis/commands/cluster.rb
@@ -101,12 +63,6 @@ files:
101
63
  - lib/redis/commands/streams.rb
102
64
  - lib/redis/commands/strings.rb
103
65
  - lib/redis/commands/transactions.rb
104
- - lib/redis/connection.rb
105
- - lib/redis/connection/command_helper.rb
106
- - lib/redis/connection/hiredis.rb
107
- - lib/redis/connection/registry.rb
108
- - lib/redis/connection/ruby.rb
109
- - lib/redis/connection/synchrony.rb
110
66
  - lib/redis/distributed.rb
111
67
  - lib/redis/errors.rb
112
68
  - lib/redis/hash_ring.rb
@@ -119,9 +75,9 @@ licenses:
119
75
  metadata:
120
76
  bug_tracker_uri: https://github.com/redis/redis-rb/issues
121
77
  changelog_uri: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md
122
- documentation_uri: https://www.rubydoc.info/gems/redis/4.6.0
78
+ documentation_uri: https://www.rubydoc.info/gems/redis/5.0.0.beta3
123
79
  homepage_uri: https://github.com/redis/redis-rb
124
- source_code_uri: https://github.com/redis/redis-rb/tree/v4.6.0
80
+ source_code_uri: https://github.com/redis/redis-rb/tree/v5.0.0.beta3
125
81
  post_install_message:
126
82
  rdoc_options: []
127
83
  require_paths:
@@ -130,12 +86,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
86
  requirements:
131
87
  - - ">="
132
88
  - !ruby/object:Gem::Version
133
- version: 2.4.0
89
+ version: 2.5.0
134
90
  required_rubygems_version: !ruby/object:Gem::Requirement
135
91
  requirements:
136
- - - ">="
92
+ - - ">"
137
93
  - !ruby/object:Gem::Version
138
- version: '0'
94
+ version: 1.3.1
139
95
  requirements: []
140
96
  rubygems_version: 3.1.2
141
97
  signing_key:
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../errors'
4
-
5
- class Redis
6
- class Cluster
7
- # Keep details about Redis commands for Redis Cluster Client.
8
- # @see https://redis.io/commands/command
9
- class Command
10
- def initialize(details)
11
- @details = pick_details(details)
12
- end
13
-
14
- def extract_first_key(command)
15
- i = determine_first_key_position(command)
16
- return '' if i == 0
17
-
18
- key = command[i].to_s
19
- hash_tag = extract_hash_tag(key)
20
- hash_tag.empty? ? key : hash_tag
21
- end
22
-
23
- def should_send_to_master?(command)
24
- dig_details(command, :write)
25
- end
26
-
27
- def should_send_to_slave?(command)
28
- dig_details(command, :readonly)
29
- end
30
-
31
- private
32
-
33
- def pick_details(details)
34
- details.transform_values do |detail|
35
- {
36
- first_key_position: detail[:first],
37
- write: detail[:flags].include?('write'),
38
- readonly: detail[:flags].include?('readonly')
39
- }
40
- end
41
- end
42
-
43
- def dig_details(command, key)
44
- name = command.first.to_s
45
- return unless @details.key?(name)
46
-
47
- @details.fetch(name).fetch(key)
48
- end
49
-
50
- def determine_first_key_position(command)
51
- case command.first.to_s.downcase
52
- when 'eval', 'evalsha', 'migrate', 'zinterstore', 'zunionstore' then 3
53
- when 'object' then 2
54
- when 'memory'
55
- command[1].to_s.casecmp('usage').zero? ? 2 : 0
56
- when 'xread', 'xreadgroup'
57
- determine_optional_key_position(command, 'streams')
58
- else
59
- dig_details(command, :first_key_position).to_i
60
- end
61
- end
62
-
63
- def determine_optional_key_position(command, option_name)
64
- idx = command.map(&:to_s).map(&:downcase).index(option_name)
65
- idx.nil? ? 0 : idx + 1
66
- end
67
-
68
- # @see https://redis.io/topics/cluster-spec#keys-hash-tags Keys hash tags
69
- def extract_hash_tag(key)
70
- s = key.index('{')
71
- e = key.index('}', s.to_i + 1)
72
-
73
- return '' if s.nil? || e.nil?
74
-
75
- key[s + 1..e - 1]
76
- end
77
- end
78
- end
79
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../errors'
4
-
5
- class Redis
6
- class Cluster
7
- # Load details about Redis commands for Redis Cluster Client
8
- # @see https://redis.io/commands/command
9
- module CommandLoader
10
- module_function
11
-
12
- def load(nodes)
13
- nodes.each do |node|
14
- begin
15
- return fetch_command_details(node)
16
- rescue CannotConnectError, ConnectionError, CommandError
17
- next # can retry on another node
18
- end
19
- end
20
-
21
- raise CannotConnectError, 'Redis client could not connect to any cluster nodes'
22
- end
23
-
24
- def fetch_command_details(node)
25
- node.call(%i[command]).map do |reply|
26
- [reply[0], { arity: reply[1], flags: reply[2], first: reply[3], last: reply[4], step: reply[5] }]
27
- end.to_h
28
- end
29
-
30
- private_class_method :fetch_command_details
31
- end
32
- end
33
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Redis
4
- class Cluster
5
- # Key to slot converter for Redis Cluster Client
6
- #
7
- # We can test it by `CLUSTER KEYSLOT` command.
8
- #
9
- # @see https://github.com/antirez/redis-rb-cluster
10
- # Reference implementation in Ruby
11
- # @see https://redis.io/topics/cluster-spec#appendix
12
- # Reference implementation in ANSI C
13
- # @see https://redis.io/commands/cluster-keyslot
14
- # CLUSTER KEYSLOT command reference
15
- #
16
- # Copyright (C) 2013 Salvatore Sanfilippo <antirez@gmail.com>
17
- module KeySlotConverter
18
- XMODEM_CRC16_LOOKUP = [
19
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
20
- 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
21
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
22
- 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
23
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
24
- 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
25
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
26
- 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
27
- 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
28
- 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
29
- 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
30
- 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
31
- 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
32
- 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
33
- 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
34
- 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
35
- 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
36
- 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
37
- 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
38
- 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
39
- 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
40
- 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
41
- 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
42
- 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
43
- 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
44
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
45
- 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
46
- 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
47
- 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
48
- 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
49
- 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
50
- 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
51
- ].freeze
52
-
53
- HASH_SLOTS = 16_384
54
-
55
- module_function
56
-
57
- # Convert key into slot.
58
- #
59
- # @param key [String] the key of the redis command
60
- #
61
- # @return [Integer] slot number
62
- def convert(key)
63
- crc = 0
64
- key.each_byte do |b|
65
- crc = ((crc << 8) & 0xffff) ^ XMODEM_CRC16_LOOKUP[((crc >> 8) ^ b) & 0xff]
66
- end
67
-
68
- crc % HASH_SLOTS
69
- end
70
- end
71
- end
72
- end