redis 3.3.5 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +32 -50
  3. data/CHANGELOG.md +7 -9
  4. data/Gemfile +0 -1
  5. data/README.md +31 -75
  6. data/benchmarking/logging.rb +1 -1
  7. data/lib/redis.rb +31 -35
  8. data/lib/redis/client.rb +13 -8
  9. data/lib/redis/connection.rb +2 -2
  10. data/lib/redis/connection/command_helper.rb +2 -8
  11. data/lib/redis/connection/hiredis.rb +2 -2
  12. data/lib/redis/connection/ruby.rb +7 -27
  13. data/lib/redis/connection/synchrony.rb +3 -3
  14. data/lib/redis/pipeline.rb +0 -6
  15. data/lib/redis/version.rb +1 -1
  16. data/makefile +42 -0
  17. data/redis.gemspec +4 -8
  18. data/test/bitpos_test.rb +13 -19
  19. data/test/blocking_commands_test.rb +147 -6
  20. data/test/client_test.rb +1 -1
  21. data/test/command_map_test.rb +3 -5
  22. data/test/commands_on_hashes_test.rb +158 -5
  23. data/test/commands_on_hyper_log_log_test.rb +55 -6
  24. data/test/commands_on_lists_test.rb +139 -5
  25. data/test/commands_on_sets_test.rb +136 -5
  26. data/test/commands_on_sorted_sets_test.rb +312 -5
  27. data/test/commands_on_strings_test.rb +243 -6
  28. data/test/commands_on_value_types_test.rb +120 -7
  29. data/test/connection_handling_test.rb +5 -7
  30. data/test/encoding_test.rb +4 -8
  31. data/test/error_replies_test.rb +2 -4
  32. data/test/fork_safety_test.rb +1 -6
  33. data/test/helper.rb +9 -62
  34. data/test/helper_test.rb +1 -3
  35. data/test/internals_test.rb +67 -49
  36. data/test/persistence_control_commands_test.rb +1 -3
  37. data/test/pipelining_commands_test.rb +4 -8
  38. data/test/publish_subscribe_test.rb +1 -3
  39. data/test/remote_server_control_commands_test.rb +61 -4
  40. data/test/scanning_test.rb +1 -7
  41. data/test/scripting_test.rb +1 -3
  42. data/test/sentinel_command_test.rb +1 -3
  43. data/test/sentinel_test.rb +1 -3
  44. data/test/sorting_test.rb +1 -3
  45. data/test/ssl_test.rb +45 -49
  46. data/test/support/connection/hiredis.rb +1 -1
  47. data/test/support/connection/ruby.rb +1 -1
  48. data/test/support/connection/synchrony.rb +1 -1
  49. data/test/synchrony_driver.rb +6 -9
  50. data/test/thread_safety_test.rb +1 -3
  51. data/test/transactions_test.rb +1 -3
  52. data/test/unknown_commands_test.rb +1 -3
  53. data/test/url_param_test.rb +44 -46
  54. metadata +31 -77
  55. data/Rakefile +0 -87
  56. data/examples/dist_redis.rb +0 -43
  57. data/lib/redis/distributed.rb +0 -873
  58. data/lib/redis/hash_ring.rb +0 -132
  59. data/test/connection_test.rb +0 -57
  60. data/test/distributed_blocking_commands_test.rb +0 -46
  61. data/test/distributed_commands_on_hashes_test.rb +0 -10
  62. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
  63. data/test/distributed_commands_on_lists_test.rb +0 -22
  64. data/test/distributed_commands_on_sets_test.rb +0 -83
  65. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  66. data/test/distributed_commands_on_strings_test.rb +0 -59
  67. data/test/distributed_commands_on_value_types_test.rb +0 -95
  68. data/test/distributed_commands_requiring_clustering_test.rb +0 -164
  69. data/test/distributed_connection_handling_test.rb +0 -23
  70. data/test/distributed_internals_test.rb +0 -79
  71. data/test/distributed_key_tags_test.rb +0 -52
  72. data/test/distributed_persistence_control_commands_test.rb +0 -26
  73. data/test/distributed_publish_subscribe_test.rb +0 -92
  74. data/test/distributed_remote_server_control_commands_test.rb +0 -66
  75. data/test/distributed_scripting_test.rb +0 -102
  76. data/test/distributed_sorting_test.rb +0 -20
  77. data/test/distributed_test.rb +0 -58
  78. data/test/distributed_transactions_test.rb +0 -32
  79. data/test/lint/blocking_commands.rb +0 -150
  80. data/test/lint/hashes.rb +0 -162
  81. data/test/lint/hyper_log_log.rb +0 -60
  82. data/test/lint/lists.rb +0 -143
  83. data/test/lint/sets.rb +0 -140
  84. data/test/lint/sorted_sets.rb +0 -316
  85. data/test/lint/strings.rb +0 -260
  86. data/test/lint/value_types.rb +0 -122
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: 3.3.5
4
+ version: 4.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Zygmuntowicz
@@ -16,40 +16,53 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2017-09-28 00:00:00.000000000 Z
19
+ date: 2016-11-24 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rake
22
+ name: test-unit
23
23
  requirement: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "<"
25
+ - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 11.0.0
27
+ version: 3.1.5
28
28
  type: :development
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: 11.0.0
34
+ version: 3.1.5
35
35
  - !ruby/object:Gem::Dependency
36
- name: test-unit
36
+ name: hiredis
37
37
  requirement: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 3.1.5
41
+ version: '0'
42
42
  type: :development
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 3.1.5
48
+ version: '0'
49
+ - !ruby/object:Gem::Dependency
50
+ name: em-synchrony
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'
49
63
  description: |2
50
64
  A Ruby client that tries to match Redis' API one-to-one, while still
51
- providing an idiomatic interface. It features thread-safety,
52
- client-side sharding, pipelining, and an obsession for performance.
65
+ providing an idiomatic interface.
53
66
  email:
54
67
  - redis-db@googlegroups.com
55
68
  executables: []
@@ -64,7 +77,6 @@ files:
64
77
  - Gemfile
65
78
  - LICENSE
66
79
  - README.md
67
- - Rakefile
68
80
  - benchmarking/logging.rb
69
81
  - benchmarking/pipeline.rb
70
82
  - benchmarking/speed.rb
@@ -72,7 +84,6 @@ files:
72
84
  - benchmarking/worker.rb
73
85
  - examples/basic.rb
74
86
  - examples/consistency.rb
75
- - examples/dist_redis.rb
76
87
  - examples/incr-decr.rb
77
88
  - examples/list.rb
78
89
  - examples/pubsub.rb
@@ -90,12 +101,11 @@ files:
90
101
  - lib/redis/connection/registry.rb
91
102
  - lib/redis/connection/ruby.rb
92
103
  - lib/redis/connection/synchrony.rb
93
- - lib/redis/distributed.rb
94
104
  - lib/redis/errors.rb
95
- - lib/redis/hash_ring.rb
96
105
  - lib/redis/pipeline.rb
97
106
  - lib/redis/subscribe.rb
98
107
  - lib/redis/version.rb
108
+ - makefile
99
109
  - redis.gemspec
100
110
  - test/bitpos_test.rb
101
111
  - test/blocking_commands_test.rb
@@ -109,41 +119,13 @@ files:
109
119
  - test/commands_on_strings_test.rb
110
120
  - test/commands_on_value_types_test.rb
111
121
  - test/connection_handling_test.rb
112
- - test/connection_test.rb
113
122
  - test/db/.gitkeep
114
- - test/distributed_blocking_commands_test.rb
115
- - test/distributed_commands_on_hashes_test.rb
116
- - test/distributed_commands_on_hyper_log_log_test.rb
117
- - test/distributed_commands_on_lists_test.rb
118
- - test/distributed_commands_on_sets_test.rb
119
- - test/distributed_commands_on_sorted_sets_test.rb
120
- - test/distributed_commands_on_strings_test.rb
121
- - test/distributed_commands_on_value_types_test.rb
122
- - test/distributed_commands_requiring_clustering_test.rb
123
- - test/distributed_connection_handling_test.rb
124
- - test/distributed_internals_test.rb
125
- - test/distributed_key_tags_test.rb
126
- - test/distributed_persistence_control_commands_test.rb
127
- - test/distributed_publish_subscribe_test.rb
128
- - test/distributed_remote_server_control_commands_test.rb
129
- - test/distributed_scripting_test.rb
130
- - test/distributed_sorting_test.rb
131
- - test/distributed_test.rb
132
- - test/distributed_transactions_test.rb
133
123
  - test/encoding_test.rb
134
124
  - test/error_replies_test.rb
135
125
  - test/fork_safety_test.rb
136
126
  - test/helper.rb
137
127
  - test/helper_test.rb
138
128
  - test/internals_test.rb
139
- - test/lint/blocking_commands.rb
140
- - test/lint/hashes.rb
141
- - test/lint/hyper_log_log.rb
142
- - test/lint/lists.rb
143
- - test/lint/sets.rb
144
- - test/lint/sorted_sets.rb
145
- - test/lint/strings.rb
146
- - test/lint/value_types.rb
147
129
  - test/persistence_control_commands_test.rb
148
130
  - test/pipelining_commands_test.rb
149
131
  - test/publish_subscribe_test.rb
@@ -190,12 +172,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
190
172
  version: '0'
191
173
  required_rubygems_version: !ruby/object:Gem::Requirement
192
174
  requirements:
193
- - - ">="
175
+ - - ">"
194
176
  - !ruby/object:Gem::Version
195
- version: '0'
177
+ version: 1.3.1
196
178
  requirements: []
197
179
  rubyforge_project:
198
- rubygems_version: 2.5.1
180
+ rubygems_version: 2.4.5.1
199
181
  signing_key:
200
182
  specification_version: 4
201
183
  summary: A Ruby client library for Redis
@@ -212,41 +194,13 @@ test_files:
212
194
  - test/commands_on_strings_test.rb
213
195
  - test/commands_on_value_types_test.rb
214
196
  - test/connection_handling_test.rb
215
- - test/connection_test.rb
216
197
  - test/db/.gitkeep
217
- - test/distributed_blocking_commands_test.rb
218
- - test/distributed_commands_on_hashes_test.rb
219
- - test/distributed_commands_on_hyper_log_log_test.rb
220
- - test/distributed_commands_on_lists_test.rb
221
- - test/distributed_commands_on_sets_test.rb
222
- - test/distributed_commands_on_sorted_sets_test.rb
223
- - test/distributed_commands_on_strings_test.rb
224
- - test/distributed_commands_on_value_types_test.rb
225
- - test/distributed_commands_requiring_clustering_test.rb
226
- - test/distributed_connection_handling_test.rb
227
- - test/distributed_internals_test.rb
228
- - test/distributed_key_tags_test.rb
229
- - test/distributed_persistence_control_commands_test.rb
230
- - test/distributed_publish_subscribe_test.rb
231
- - test/distributed_remote_server_control_commands_test.rb
232
- - test/distributed_scripting_test.rb
233
- - test/distributed_sorting_test.rb
234
- - test/distributed_test.rb
235
- - test/distributed_transactions_test.rb
236
198
  - test/encoding_test.rb
237
199
  - test/error_replies_test.rb
238
200
  - test/fork_safety_test.rb
239
201
  - test/helper.rb
240
202
  - test/helper_test.rb
241
203
  - test/internals_test.rb
242
- - test/lint/blocking_commands.rb
243
- - test/lint/hashes.rb
244
- - test/lint/hyper_log_log.rb
245
- - test/lint/lists.rb
246
- - test/lint/sets.rb
247
- - test/lint/sorted_sets.rb
248
- - test/lint/strings.rb
249
- - test/lint/value_types.rb
250
204
  - test/persistence_control_commands_test.rb
251
205
  - test/pipelining_commands_test.rb
252
206
  - test/publish_subscribe_test.rb
data/Rakefile DELETED
@@ -1,87 +0,0 @@
1
- require "rake/testtask"
2
-
3
- ENV["REDIS_BRANCH"] ||= "unstable"
4
-
5
- REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
6
- REDIS_CNF = File.join(REDIS_DIR, "test.conf")
7
- REDIS_CNF_TEMPLATE = File.join(REDIS_DIR, "test.conf.erb")
8
- REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
9
- REDIS_LOG = File.join(REDIS_DIR, "db", "redis.log")
10
- REDIS_SOCKET = File.join(REDIS_DIR, "db", "redis.sock")
11
- BINARY = "tmp/redis-#{ENV["REDIS_BRANCH"]}/src/redis-server"
12
-
13
- task :default => :run
14
-
15
- desc "Run tests and manage server start/stop"
16
- task :run => [:start, :test, :stop]
17
-
18
- desc "Start the Redis server"
19
- task :start => [BINARY, REDIS_CNF] do
20
- sh "#{BINARY} --version"
21
-
22
- redis_running = \
23
- begin
24
- File.exists?(REDIS_PID) && Process.kill(0, File.read(REDIS_PID).to_i)
25
- rescue Errno::ESRCH
26
- FileUtils.rm REDIS_PID
27
- false
28
- end
29
-
30
- unless redis_running
31
- unless system("#{BINARY} #{REDIS_CNF}")
32
- abort "could not start redis-server"
33
- end
34
- end
35
-
36
- at_exit do
37
- Rake::Task["stop"].invoke
38
- end
39
- end
40
-
41
- desc "Stop the Redis server"
42
- task :stop do
43
- if File.exists?(REDIS_PID)
44
- Process.kill "INT", File.read(REDIS_PID).to_i
45
- FileUtils.rm REDIS_PID
46
- end
47
- end
48
-
49
- desc "Clean up testing artifacts"
50
- task :clean do
51
- FileUtils.rm_f(BINARY)
52
- FileUtils.rm_f(REDIS_CNF)
53
- end
54
-
55
- file BINARY do
56
- branch = ENV.fetch("REDIS_BRANCH")
57
-
58
- sh <<-SH
59
- mkdir -p tmp;
60
- cd tmp;
61
- rm -rf redis-#{branch};
62
- wget https://github.com/antirez/redis/archive/#{branch}.tar.gz -O #{branch}.tar.gz;
63
- tar xf #{branch}.tar.gz;
64
- cd redis-#{branch};
65
- make
66
- SH
67
- end
68
-
69
- file REDIS_CNF => [REDIS_CNF_TEMPLATE, __FILE__] do |t|
70
- require 'erb'
71
-
72
- erb = t.prerequisites[0]
73
- template = File.read(erb)
74
-
75
- File.open(REDIS_CNF, 'w') do |file|
76
- file.puts "\# This file was auto-generated at #{Time.now}",
77
- "\# from (#{erb})",
78
- "\#"
79
- conf = ERB.new(template).result
80
- file << conf
81
- end
82
- end
83
-
84
- Rake::TestTask.new do |t|
85
- t.options = "-v" if $VERBOSE
86
- t.test_files = FileList["test/*_test.rb"]
87
- end
@@ -1,43 +0,0 @@
1
- require "redis"
2
- require "redis/distributed"
3
-
4
- r = Redis::Distributed.new %w[redis://localhost:6379 redis://localhost:6380 redis://localhost:6381 redis://localhost:6382]
5
-
6
- r.flushdb
7
-
8
- r['urmom'] = 'urmom'
9
- r['urdad'] = 'urdad'
10
- r['urmom1'] = 'urmom1'
11
- r['urdad1'] = 'urdad1'
12
- r['urmom2'] = 'urmom2'
13
- r['urdad2'] = 'urdad2'
14
- r['urmom3'] = 'urmom3'
15
- r['urdad3'] = 'urdad3'
16
- p r['urmom']
17
- p r['urdad']
18
- p r['urmom1']
19
- p r['urdad1']
20
- p r['urmom2']
21
- p r['urdad2']
22
- p r['urmom3']
23
- p r['urdad3']
24
-
25
- r.rpush 'listor', 'foo1'
26
- r.rpush 'listor', 'foo2'
27
- r.rpush 'listor', 'foo3'
28
- r.rpush 'listor', 'foo4'
29
- r.rpush 'listor', 'foo5'
30
-
31
- p r.rpop('listor')
32
- p r.rpop('listor')
33
- p r.rpop('listor')
34
- p r.rpop('listor')
35
- p r.rpop('listor')
36
-
37
- puts "key distribution:"
38
-
39
- r.ring.nodes.each do |node|
40
- p [node.client, node.keys("*")]
41
- end
42
- r.flushdb
43
- p r.keys('*')
@@ -1,873 +0,0 @@
1
- require "redis/hash_ring"
2
-
3
- class Redis
4
- class Distributed
5
-
6
- class CannotDistribute < RuntimeError
7
- def initialize(command)
8
- @command = command
9
- end
10
-
11
- def message
12
- "#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic."
13
- end
14
- end
15
-
16
- attr_reader :ring
17
-
18
- def initialize(node_configs, options = {})
19
- @tag = options[:tag] || /^\{(.+?)\}/
20
- @ring = options[:ring] || HashRing.new
21
- @node_configs = node_configs.dup
22
- @default_options = options.dup
23
- node_configs.each { |node_config| add_node(node_config) }
24
- @subscribed_node = nil
25
- end
26
-
27
- def node_for(key)
28
- @ring.get_node(key_tag(key.to_s) || key.to_s)
29
- end
30
-
31
- def nodes
32
- @ring.nodes
33
- end
34
-
35
- def add_node(options)
36
- options = { :url => options } if options.is_a?(String)
37
- options = @default_options.merge(options)
38
- @ring.add_node Redis.new( options )
39
- end
40
-
41
- # Change the selected database for the current connection.
42
- def select(db)
43
- on_each_node :select, db
44
- end
45
-
46
- # Ping the server.
47
- def ping
48
- on_each_node :ping
49
- end
50
-
51
- # Echo the given string.
52
- def echo(value)
53
- on_each_node :echo, value
54
- end
55
-
56
- # Close the connection.
57
- def quit
58
- on_each_node :quit
59
- end
60
-
61
- # Asynchronously save the dataset to disk.
62
- def bgsave
63
- on_each_node :bgsave
64
- end
65
-
66
- # Return the number of keys in the selected database.
67
- def dbsize
68
- on_each_node :dbsize
69
- end
70
-
71
- # Remove all keys from all databases.
72
- def flushall
73
- on_each_node :flushall
74
- end
75
-
76
- # Remove all keys from the current database.
77
- def flushdb
78
- on_each_node :flushdb
79
- end
80
-
81
- # Get information and statistics about the server.
82
- def info(cmd = nil)
83
- on_each_node :info, cmd
84
- end
85
-
86
- # Get the UNIX time stamp of the last successful save to disk.
87
- def lastsave
88
- on_each_node :lastsave
89
- end
90
-
91
- # Listen for all requests received by the server in real time.
92
- def monitor
93
- raise NotImplementedError
94
- end
95
-
96
- # Synchronously save the dataset to disk.
97
- def save
98
- on_each_node :save
99
- end
100
-
101
- # Get server time: an UNIX timestamp and the elapsed microseconds in the current second.
102
- def time
103
- on_each_node :time
104
- end
105
-
106
- # Remove the expiration from a key.
107
- def persist(key)
108
- node_for(key).persist(key)
109
- end
110
-
111
- # Set a key's time to live in seconds.
112
- def expire(key, seconds)
113
- node_for(key).expire(key, seconds)
114
- end
115
-
116
- # Set the expiration for a key as a UNIX timestamp.
117
- def expireat(key, unix_time)
118
- node_for(key).expireat(key, unix_time)
119
- end
120
-
121
- # Get the time to live (in seconds) for a key.
122
- def ttl(key)
123
- node_for(key).ttl(key)
124
- end
125
-
126
- # Set a key's time to live in milliseconds.
127
- def pexpire(key, milliseconds)
128
- node_for(key).pexpire(key, milliseconds)
129
- end
130
-
131
- # Set the expiration for a key as number of milliseconds from UNIX Epoch.
132
- def pexpireat(key, ms_unix_time)
133
- node_for(key).pexpireat(key, ms_unix_time)
134
- end
135
-
136
- # Get the time to live (in milliseconds) for a key.
137
- def pttl(key)
138
- node_for(key).pttl(key)
139
- end
140
-
141
- # Return a serialized version of the value stored at a key.
142
- def dump(key)
143
- node_for(key).dump(key)
144
- end
145
-
146
- # Create a key using the serialized value, previously obtained using DUMP.
147
- def restore(key, ttl, serialized_value)
148
- node_for(key).restore(key, ttl, serialized_value)
149
- end
150
-
151
- # Transfer a key from the connected instance to another instance.
152
- def migrate(key, options)
153
- raise CannotDistribute, :migrate
154
- end
155
-
156
- # Delete a key.
157
- def del(*args)
158
- keys_per_node = args.group_by { |key| node_for(key) }
159
- keys_per_node.inject(0) do |sum, (node, keys)|
160
- sum + node.del(*keys)
161
- end
162
- end
163
-
164
- # Determine if a key exists.
165
- def exists(key)
166
- node_for(key).exists(key)
167
- end
168
-
169
- # Find all keys matching the given pattern.
170
- def keys(glob = "*")
171
- on_each_node(:keys, glob).flatten
172
- end
173
-
174
- # Move a key to another database.
175
- def move(key, db)
176
- node_for(key).move(key, db)
177
- end
178
-
179
- # Return a random key from the keyspace.
180
- def randomkey
181
- raise CannotDistribute, :randomkey
182
- end
183
-
184
- # Rename a key.
185
- def rename(old_name, new_name)
186
- ensure_same_node(:rename, [old_name, new_name]) do |node|
187
- node.rename(old_name, new_name)
188
- end
189
- end
190
-
191
- # Rename a key, only if the new key does not exist.
192
- def renamenx(old_name, new_name)
193
- ensure_same_node(:renamenx, [old_name, new_name]) do |node|
194
- node.renamenx(old_name, new_name)
195
- end
196
- end
197
-
198
- # Sort the elements in a list, set or sorted set.
199
- def sort(key, options = {})
200
- keys = [key, options[:by], options[:store], *Array(options[:get])].compact
201
-
202
- ensure_same_node(:sort, keys) do |node|
203
- node.sort(key, options)
204
- end
205
- end
206
-
207
- # Determine the type stored at key.
208
- def type(key)
209
- node_for(key).type(key)
210
- end
211
-
212
- # Decrement the integer value of a key by one.
213
- def decr(key)
214
- node_for(key).decr(key)
215
- end
216
-
217
- # Decrement the integer value of a key by the given number.
218
- def decrby(key, decrement)
219
- node_for(key).decrby(key, decrement)
220
- end
221
-
222
- # Increment the integer value of a key by one.
223
- def incr(key)
224
- node_for(key).incr(key)
225
- end
226
-
227
- # Increment the integer value of a key by the given integer number.
228
- def incrby(key, increment)
229
- node_for(key).incrby(key, increment)
230
- end
231
-
232
- # Increment the numeric value of a key by the given float number.
233
- def incrbyfloat(key, increment)
234
- node_for(key).incrbyfloat(key, increment)
235
- end
236
-
237
- # Set the string value of a key.
238
- def set(key, value, options = {})
239
- node_for(key).set(key, value, options)
240
- end
241
-
242
- # Set the time to live in seconds of a key.
243
- def setex(key, ttl, value)
244
- node_for(key).setex(key, ttl, value)
245
- end
246
-
247
- # Set the time to live in milliseconds of a key.
248
- def psetex(key, ttl, value)
249
- node_for(key).psetex(key, ttl, value)
250
- end
251
-
252
- # Set the value of a key, only if the key does not exist.
253
- def setnx(key, value)
254
- node_for(key).setnx(key, value)
255
- end
256
-
257
- # Set multiple keys to multiple values.
258
- def mset(*args)
259
- raise CannotDistribute, :mset
260
- end
261
-
262
- def mapped_mset(hash)
263
- raise CannotDistribute, :mapped_mset
264
- end
265
-
266
- # Set multiple keys to multiple values, only if none of the keys exist.
267
- def msetnx(*args)
268
- raise CannotDistribute, :msetnx
269
- end
270
-
271
- def mapped_msetnx(hash)
272
- raise CannotDistribute, :mapped_msetnx
273
- end
274
-
275
- # Get the value of a key.
276
- def get(key)
277
- node_for(key).get(key)
278
- end
279
-
280
- # Get the values of all the given keys.
281
- def mget(*keys)
282
- raise CannotDistribute, :mget
283
- end
284
-
285
- def mapped_mget(*keys)
286
- raise CannotDistribute, :mapped_mget
287
- end
288
-
289
- # Overwrite part of a string at key starting at the specified offset.
290
- def setrange(key, offset, value)
291
- node_for(key).setrange(key, offset, value)
292
- end
293
-
294
- # Get a substring of the string stored at a key.
295
- def getrange(key, start, stop)
296
- node_for(key).getrange(key, start, stop)
297
- end
298
-
299
- # Sets or clears the bit at offset in the string value stored at key.
300
- def setbit(key, offset, value)
301
- node_for(key).setbit(key, offset, value)
302
- end
303
-
304
- # Returns the bit value at offset in the string value stored at key.
305
- def getbit(key, offset)
306
- node_for(key).getbit(key, offset)
307
- end
308
-
309
- # Append a value to a key.
310
- def append(key, value)
311
- node_for(key).append(key, value)
312
- end
313
-
314
- # Count the number of set bits in a range of the string value stored at key.
315
- def bitcount(key, start = 0, stop = -1)
316
- node_for(key).bitcount(key, start, stop)
317
- end
318
-
319
- # Perform a bitwise operation between strings and store the resulting string in a key.
320
- def bitop(operation, destkey, *keys)
321
- ensure_same_node(:bitop, [destkey] + keys) do |node|
322
- node.bitop(operation, destkey, *keys)
323
- end
324
- end
325
-
326
- # Return the position of the first bit set to 1 or 0 in a string.
327
- def bitpos(key, bit, start=nil, stop=nil)
328
- node_for(key).bitpos(key, bit, start, stop)
329
- end
330
-
331
- # Set the string value of a key and return its old value.
332
- def getset(key, value)
333
- node_for(key).getset(key, value)
334
- end
335
-
336
- # Get the length of the value stored in a key.
337
- def strlen(key)
338
- node_for(key).strlen(key)
339
- end
340
-
341
- def [](key)
342
- get(key)
343
- end
344
-
345
- def []=(key,value)
346
- set(key, value)
347
- end
348
-
349
- # Get the length of a list.
350
- def llen(key)
351
- node_for(key).llen(key)
352
- end
353
-
354
- # Prepend one or more values to a list.
355
- def lpush(key, value)
356
- node_for(key).lpush(key, value)
357
- end
358
-
359
- # Prepend a value to a list, only if the list exists.
360
- def lpushx(key, value)
361
- node_for(key).lpushx(key, value)
362
- end
363
-
364
- # Append one or more values to a list.
365
- def rpush(key, value)
366
- node_for(key).rpush(key, value)
367
- end
368
-
369
- # Append a value to a list, only if the list exists.
370
- def rpushx(key, value)
371
- node_for(key).rpushx(key, value)
372
- end
373
-
374
- # Remove and get the first element in a list.
375
- def lpop(key)
376
- node_for(key).lpop(key)
377
- end
378
-
379
- # Remove and get the last element in a list.
380
- def rpop(key)
381
- node_for(key).rpop(key)
382
- end
383
-
384
- # Remove the last element in a list, append it to another list and return
385
- # it.
386
- def rpoplpush(source, destination)
387
- ensure_same_node(:rpoplpush, [source, destination]) do |node|
388
- node.rpoplpush(source, destination)
389
- end
390
- end
391
-
392
- def _bpop(cmd, args)
393
- options = {}
394
-
395
- case args.last
396
- when Hash
397
- options = args.pop
398
- when Integer
399
- # Issue deprecation notice in obnoxious mode...
400
- options[:timeout] = args.pop
401
- end
402
-
403
- if args.size > 1
404
- # Issue deprecation notice in obnoxious mode...
405
- end
406
-
407
- keys = args.flatten
408
-
409
- ensure_same_node(cmd, keys) do |node|
410
- node.__send__(cmd, keys, options)
411
- end
412
- end
413
-
414
- # Remove and get the first element in a list, or block until one is
415
- # available.
416
- def blpop(*args)
417
- _bpop(:blpop, args)
418
- end
419
-
420
- # Remove and get the last element in a list, or block until one is
421
- # available.
422
- def brpop(*args)
423
- _bpop(:brpop, args)
424
- end
425
-
426
- # Pop a value from a list, push it to another list and return it; or block
427
- # until one is available.
428
- def brpoplpush(source, destination, options = {})
429
- case options
430
- when Integer
431
- # Issue deprecation notice in obnoxious mode...
432
- options = { :timeout => options }
433
- end
434
-
435
- ensure_same_node(:brpoplpush, [source, destination]) do |node|
436
- node.brpoplpush(source, destination, options)
437
- end
438
- end
439
-
440
- # Get an element from a list by its index.
441
- def lindex(key, index)
442
- node_for(key).lindex(key, index)
443
- end
444
-
445
- # Insert an element before or after another element in a list.
446
- def linsert(key, where, pivot, value)
447
- node_for(key).linsert(key, where, pivot, value)
448
- end
449
-
450
- # Get a range of elements from a list.
451
- def lrange(key, start, stop)
452
- node_for(key).lrange(key, start, stop)
453
- end
454
-
455
- # Remove elements from a list.
456
- def lrem(key, count, value)
457
- node_for(key).lrem(key, count, value)
458
- end
459
-
460
- # Set the value of an element in a list by its index.
461
- def lset(key, index, value)
462
- node_for(key).lset(key, index, value)
463
- end
464
-
465
- # Trim a list to the specified range.
466
- def ltrim(key, start, stop)
467
- node_for(key).ltrim(key, start, stop)
468
- end
469
-
470
- # Get the number of members in a set.
471
- def scard(key)
472
- node_for(key).scard(key)
473
- end
474
-
475
- # Add one or more members to a set.
476
- def sadd(key, member)
477
- node_for(key).sadd(key, member)
478
- end
479
-
480
- # Remove one or more members from a set.
481
- def srem(key, member)
482
- node_for(key).srem(key, member)
483
- end
484
-
485
- # Remove and return a random member from a set.
486
- def spop(key, count = nil)
487
- node_for(key).spop(key, count)
488
- end
489
-
490
- # Get a random member from a set.
491
- def srandmember(key, count = nil)
492
- node_for(key).srandmember(key, count)
493
- end
494
-
495
- # Move a member from one set to another.
496
- def smove(source, destination, member)
497
- ensure_same_node(:smove, [source, destination]) do |node|
498
- node.smove(source, destination, member)
499
- end
500
- end
501
-
502
- # Determine if a given value is a member of a set.
503
- def sismember(key, member)
504
- node_for(key).sismember(key, member)
505
- end
506
-
507
- # Get all the members in a set.
508
- def smembers(key)
509
- node_for(key).smembers(key)
510
- end
511
-
512
- # Subtract multiple sets.
513
- def sdiff(*keys)
514
- ensure_same_node(:sdiff, keys) do |node|
515
- node.sdiff(*keys)
516
- end
517
- end
518
-
519
- # Subtract multiple sets and store the resulting set in a key.
520
- def sdiffstore(destination, *keys)
521
- ensure_same_node(:sdiffstore, [destination] + keys) do |node|
522
- node.sdiffstore(destination, *keys)
523
- end
524
- end
525
-
526
- # Intersect multiple sets.
527
- def sinter(*keys)
528
- ensure_same_node(:sinter, keys) do |node|
529
- node.sinter(*keys)
530
- end
531
- end
532
-
533
- # Intersect multiple sets and store the resulting set in a key.
534
- def sinterstore(destination, *keys)
535
- ensure_same_node(:sinterstore, [destination] + keys) do |node|
536
- node.sinterstore(destination, *keys)
537
- end
538
- end
539
-
540
- # Add multiple sets.
541
- def sunion(*keys)
542
- ensure_same_node(:sunion, keys) do |node|
543
- node.sunion(*keys)
544
- end
545
- end
546
-
547
- # Add multiple sets and store the resulting set in a key.
548
- def sunionstore(destination, *keys)
549
- ensure_same_node(:sunionstore, [destination] + keys) do |node|
550
- node.sunionstore(destination, *keys)
551
- end
552
- end
553
-
554
- # Get the number of members in a sorted set.
555
- def zcard(key)
556
- node_for(key).zcard(key)
557
- end
558
-
559
- # Add one or more members to a sorted set, or update the score for members
560
- # that already exist.
561
- def zadd(key, *args)
562
- node_for(key).zadd(key, *args)
563
- end
564
-
565
- # Increment the score of a member in a sorted set.
566
- def zincrby(key, increment, member)
567
- node_for(key).zincrby(key, increment, member)
568
- end
569
-
570
- # Remove one or more members from a sorted set.
571
- def zrem(key, member)
572
- node_for(key).zrem(key, member)
573
- end
574
-
575
- # Get the score associated with the given member in a sorted set.
576
- def zscore(key, member)
577
- node_for(key).zscore(key, member)
578
- end
579
-
580
- # Return a range of members in a sorted set, by index.
581
- def zrange(key, start, stop, options = {})
582
- node_for(key).zrange(key, start, stop, options)
583
- end
584
-
585
- # Return a range of members in a sorted set, by index, with scores ordered
586
- # from high to low.
587
- def zrevrange(key, start, stop, options = {})
588
- node_for(key).zrevrange(key, start, stop, options)
589
- end
590
-
591
- # Determine the index of a member in a sorted set.
592
- def zrank(key, member)
593
- node_for(key).zrank(key, member)
594
- end
595
-
596
- # Determine the index of a member in a sorted set, with scores ordered from
597
- # high to low.
598
- def zrevrank(key, member)
599
- node_for(key).zrevrank(key, member)
600
- end
601
-
602
- # Remove all members in a sorted set within the given indexes.
603
- def zremrangebyrank(key, start, stop)
604
- node_for(key).zremrangebyrank(key, start, stop)
605
- end
606
-
607
- # Return a range of members in a sorted set, by score.
608
- def zrangebyscore(key, min, max, options = {})
609
- node_for(key).zrangebyscore(key, min, max, options)
610
- end
611
-
612
- # Return a range of members in a sorted set, by score, with scores ordered
613
- # from high to low.
614
- def zrevrangebyscore(key, max, min, options = {})
615
- node_for(key).zrevrangebyscore(key, max, min, options)
616
- end
617
-
618
- # Remove all members in a sorted set within the given scores.
619
- def zremrangebyscore(key, min, max)
620
- node_for(key).zremrangebyscore(key, min, max)
621
- end
622
-
623
- # Get the number of members in a particular score range.
624
- def zcount(key, min, max)
625
- node_for(key).zcount(key, min, max)
626
- end
627
-
628
- # Intersect multiple sorted sets and store the resulting sorted set in a new
629
- # key.
630
- def zinterstore(destination, keys, options = {})
631
- ensure_same_node(:zinterstore, [destination] + keys) do |node|
632
- node.zinterstore(destination, keys, options)
633
- end
634
- end
635
-
636
- # Add multiple sorted sets and store the resulting sorted set in a new key.
637
- def zunionstore(destination, keys, options = {})
638
- ensure_same_node(:zunionstore, [destination] + keys) do |node|
639
- node.zunionstore(destination, keys, options)
640
- end
641
- end
642
-
643
- # Get the number of fields in a hash.
644
- def hlen(key)
645
- node_for(key).hlen(key)
646
- end
647
-
648
- # Set the string value of a hash field.
649
- def hset(key, field, value)
650
- node_for(key).hset(key, field, value)
651
- end
652
-
653
- # Set the value of a hash field, only if the field does not exist.
654
- def hsetnx(key, field, value)
655
- node_for(key).hsetnx(key, field, value)
656
- end
657
-
658
- # Set multiple hash fields to multiple values.
659
- def hmset(key, *attrs)
660
- node_for(key).hmset(key, *attrs)
661
- end
662
-
663
- def mapped_hmset(key, hash)
664
- node_for(key).hmset(key, *hash.to_a.flatten)
665
- end
666
-
667
- # Get the value of a hash field.
668
- def hget(key, field)
669
- node_for(key).hget(key, field)
670
- end
671
-
672
- # Get the values of all the given hash fields.
673
- def hmget(key, *fields)
674
- node_for(key).hmget(key, *fields)
675
- end
676
-
677
- def mapped_hmget(key, *fields)
678
- Hash[*fields.zip(hmget(key, *fields)).flatten]
679
- end
680
-
681
- # Delete one or more hash fields.
682
- def hdel(key, field)
683
- node_for(key).hdel(key, field)
684
- end
685
-
686
- # Determine if a hash field exists.
687
- def hexists(key, field)
688
- node_for(key).hexists(key, field)
689
- end
690
-
691
- # Increment the integer value of a hash field by the given integer number.
692
- def hincrby(key, field, increment)
693
- node_for(key).hincrby(key, field, increment)
694
- end
695
-
696
- # Increment the numeric value of a hash field by the given float number.
697
- def hincrbyfloat(key, field, increment)
698
- node_for(key).hincrbyfloat(key, field, increment)
699
- end
700
-
701
- # Get all the fields in a hash.
702
- def hkeys(key)
703
- node_for(key).hkeys(key)
704
- end
705
-
706
- # Get all the values in a hash.
707
- def hvals(key)
708
- node_for(key).hvals(key)
709
- end
710
-
711
- # Get all the fields and values in a hash.
712
- def hgetall(key)
713
- node_for(key).hgetall(key)
714
- end
715
-
716
- # Post a message to a channel.
717
- def publish(channel, message)
718
- node_for(channel).publish(channel, message)
719
- end
720
-
721
- def subscribed?
722
- !! @subscribed_node
723
- end
724
-
725
- # Listen for messages published to the given channels.
726
- def subscribe(channel, *channels, &block)
727
- if channels.empty?
728
- @subscribed_node = node_for(channel)
729
- @subscribed_node.subscribe(channel, &block)
730
- else
731
- ensure_same_node(:subscribe, [channel] + channels) do |node|
732
- @subscribed_node = node
733
- node.subscribe(channel, *channels, &block)
734
- end
735
- end
736
- end
737
-
738
- # Stop listening for messages posted to the given channels.
739
- def unsubscribe(*channels)
740
- raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
741
- @subscribed_node.unsubscribe(*channels)
742
- end
743
-
744
- # Listen for messages published to channels matching the given patterns.
745
- def psubscribe(*channels, &block)
746
- raise NotImplementedError
747
- end
748
-
749
- # Stop listening for messages posted to channels matching the given
750
- # patterns.
751
- def punsubscribe(*channels)
752
- raise NotImplementedError
753
- end
754
-
755
- # Watch the given keys to determine execution of the MULTI/EXEC block.
756
- def watch(*keys)
757
- raise CannotDistribute, :watch
758
- end
759
-
760
- # Forget about all watched keys.
761
- def unwatch
762
- raise CannotDistribute, :unwatch
763
- end
764
-
765
- def pipelined
766
- raise CannotDistribute, :pipelined
767
- end
768
-
769
- # Mark the start of a transaction block.
770
- def multi
771
- raise CannotDistribute, :multi
772
- end
773
-
774
- # Execute all commands issued after MULTI.
775
- def exec
776
- raise CannotDistribute, :exec
777
- end
778
-
779
- # Discard all commands issued after MULTI.
780
- def discard
781
- raise CannotDistribute, :discard
782
- end
783
-
784
- # Control remote script registry.
785
- def script(subcommand, *args)
786
- on_each_node(:script, subcommand, *args)
787
- end
788
-
789
- # Add one or more members to a HyperLogLog structure.
790
- def pfadd(key, member)
791
- node_for(key).pfadd(key, member)
792
- end
793
-
794
- # Get the approximate cardinality of members added to HyperLogLog structure.
795
- def pfcount(*keys)
796
- ensure_same_node(:pfcount, keys.flatten(1)) do |node|
797
- node.pfcount(keys)
798
- end
799
- end
800
-
801
- # Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
802
- # the observed Sets of the source HyperLogLog structures.
803
- def pfmerge(dest_key, *source_key)
804
- ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node|
805
- node.pfmerge(dest_key, *source_key)
806
- end
807
- end
808
-
809
- def _eval(cmd, args)
810
- script = args.shift
811
- options = args.pop if args.last.is_a?(Hash)
812
- options ||= {}
813
-
814
- keys = args.shift || options[:keys] || []
815
- argv = args.shift || options[:argv] || []
816
-
817
- ensure_same_node(cmd, keys) do |node|
818
- node.send(cmd, script, keys, argv)
819
- end
820
- end
821
-
822
- # Evaluate Lua script.
823
- def eval(*args)
824
- _eval(:eval, args)
825
- end
826
-
827
- # Evaluate Lua script by its SHA.
828
- def evalsha(*args)
829
- _eval(:evalsha, args)
830
- end
831
-
832
- def inspect
833
- "#<Redis client v#{Redis::VERSION} for #{nodes.map(&:id).join(', ')}>"
834
- end
835
-
836
- def dup
837
- self.class.new(@node_configs, @default_options)
838
- end
839
-
840
- protected
841
-
842
- def on_each_node(command, *args)
843
- nodes.map do |node|
844
- node.send(command, *args)
845
- end
846
- end
847
-
848
- def node_index_for(key)
849
- nodes.index(node_for(key))
850
- end
851
-
852
- def key_tag(key)
853
- key.to_s[@tag, 1] if @tag
854
- end
855
-
856
- def ensure_same_node(command, keys)
857
- all = true
858
-
859
- tags = keys.map do |key|
860
- tag = key_tag(key)
861
- all = false unless tag
862
- tag
863
- end
864
-
865
- if (all && tags.uniq.size != 1) || (!all && keys.uniq.size != 1)
866
- # Not 1 unique tag or not 1 unique key
867
- raise CannotDistribute, command
868
- end
869
-
870
- yield(node_for(keys.first))
871
- end
872
- end
873
- end