redis 4.0.0 → 5.0.0

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 (137) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +252 -1
  3. data/README.md +126 -88
  4. data/lib/redis/client.rb +79 -543
  5. data/lib/redis/commands/bitmaps.rb +66 -0
  6. data/lib/redis/commands/cluster.rb +28 -0
  7. data/lib/redis/commands/connection.rb +53 -0
  8. data/lib/redis/commands/geo.rb +84 -0
  9. data/lib/redis/commands/hashes.rb +254 -0
  10. data/lib/redis/commands/hyper_log_log.rb +37 -0
  11. data/lib/redis/commands/keys.rb +437 -0
  12. data/lib/redis/commands/lists.rb +285 -0
  13. data/lib/redis/commands/pubsub.rb +54 -0
  14. data/lib/redis/commands/scripting.rb +114 -0
  15. data/lib/redis/commands/server.rb +188 -0
  16. data/lib/redis/commands/sets.rb +214 -0
  17. data/lib/redis/commands/sorted_sets.rb +818 -0
  18. data/lib/redis/commands/streams.rb +384 -0
  19. data/lib/redis/commands/strings.rb +314 -0
  20. data/lib/redis/commands/transactions.rb +115 -0
  21. data/lib/redis/commands.rb +235 -0
  22. data/lib/redis/distributed.rb +301 -109
  23. data/lib/redis/errors.rb +19 -1
  24. data/lib/redis/hash_ring.rb +34 -33
  25. data/lib/redis/pipeline.rb +69 -77
  26. data/lib/redis/subscribe.rb +26 -19
  27. data/lib/redis/version.rb +3 -1
  28. data/lib/redis.rb +109 -2728
  29. metadata +37 -229
  30. data/.gitignore +0 -16
  31. data/.travis/Gemfile +0 -13
  32. data/.travis.yml +0 -73
  33. data/.yardopts +0 -3
  34. data/Gemfile +0 -3
  35. data/benchmarking/logging.rb +0 -71
  36. data/benchmarking/pipeline.rb +0 -51
  37. data/benchmarking/speed.rb +0 -21
  38. data/benchmarking/suite.rb +0 -24
  39. data/benchmarking/worker.rb +0 -71
  40. data/bors.toml +0 -14
  41. data/examples/basic.rb +0 -15
  42. data/examples/consistency.rb +0 -114
  43. data/examples/dist_redis.rb +0 -43
  44. data/examples/incr-decr.rb +0 -17
  45. data/examples/list.rb +0 -26
  46. data/examples/pubsub.rb +0 -37
  47. data/examples/sentinel/sentinel.conf +0 -9
  48. data/examples/sentinel/start +0 -49
  49. data/examples/sentinel.rb +0 -41
  50. data/examples/sets.rb +0 -36
  51. data/examples/unicorn/config.ru +0 -3
  52. data/examples/unicorn/unicorn.rb +0 -20
  53. data/lib/redis/connection/command_helper.rb +0 -38
  54. data/lib/redis/connection/hiredis.rb +0 -66
  55. data/lib/redis/connection/registry.rb +0 -12
  56. data/lib/redis/connection/ruby.rb +0 -409
  57. data/lib/redis/connection/synchrony.rb +0 -141
  58. data/lib/redis/connection.rb +0 -9
  59. data/makefile +0 -42
  60. data/redis.gemspec +0 -42
  61. data/test/bitpos_test.rb +0 -63
  62. data/test/blocking_commands_test.rb +0 -40
  63. data/test/client_test.rb +0 -59
  64. data/test/command_map_test.rb +0 -28
  65. data/test/commands_on_hashes_test.rb +0 -19
  66. data/test/commands_on_hyper_log_log_test.rb +0 -19
  67. data/test/commands_on_lists_test.rb +0 -18
  68. data/test/commands_on_sets_test.rb +0 -75
  69. data/test/commands_on_sorted_sets_test.rb +0 -150
  70. data/test/commands_on_strings_test.rb +0 -99
  71. data/test/commands_on_value_types_test.rb +0 -131
  72. data/test/connection_handling_test.rb +0 -275
  73. data/test/db/.gitkeep +0 -0
  74. data/test/distributed_blocking_commands_test.rb +0 -44
  75. data/test/distributed_commands_on_hashes_test.rb +0 -8
  76. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -31
  77. data/test/distributed_commands_on_lists_test.rb +0 -20
  78. data/test/distributed_commands_on_sets_test.rb +0 -81
  79. data/test/distributed_commands_on_sorted_sets_test.rb +0 -16
  80. data/test/distributed_commands_on_strings_test.rb +0 -57
  81. data/test/distributed_commands_on_value_types_test.rb +0 -93
  82. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  83. data/test/distributed_connection_handling_test.rb +0 -21
  84. data/test/distributed_internals_test.rb +0 -68
  85. data/test/distributed_key_tags_test.rb +0 -50
  86. data/test/distributed_persistence_control_commands_test.rb +0 -24
  87. data/test/distributed_publish_subscribe_test.rb +0 -90
  88. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  89. data/test/distributed_scripting_test.rb +0 -100
  90. data/test/distributed_sorting_test.rb +0 -18
  91. data/test/distributed_test.rb +0 -56
  92. data/test/distributed_transactions_test.rb +0 -30
  93. data/test/encoding_test.rb +0 -14
  94. data/test/error_replies_test.rb +0 -57
  95. data/test/fork_safety_test.rb +0 -60
  96. data/test/helper.rb +0 -201
  97. data/test/helper_test.rb +0 -22
  98. data/test/internals_test.rb +0 -429
  99. data/test/lint/blocking_commands.rb +0 -150
  100. data/test/lint/hashes.rb +0 -162
  101. data/test/lint/hyper_log_log.rb +0 -60
  102. data/test/lint/lists.rb +0 -143
  103. data/test/lint/sets.rb +0 -140
  104. data/test/lint/sorted_sets.rb +0 -316
  105. data/test/lint/strings.rb +0 -246
  106. data/test/lint/value_types.rb +0 -130
  107. data/test/persistence_control_commands_test.rb +0 -24
  108. data/test/pipelining_commands_test.rb +0 -238
  109. data/test/publish_subscribe_test.rb +0 -280
  110. data/test/remote_server_control_commands_test.rb +0 -175
  111. data/test/scanning_test.rb +0 -407
  112. data/test/scripting_test.rb +0 -76
  113. data/test/sentinel_command_test.rb +0 -78
  114. data/test/sentinel_test.rb +0 -253
  115. data/test/sorting_test.rb +0 -57
  116. data/test/ssl_test.rb +0 -69
  117. data/test/support/connection/hiredis.rb +0 -1
  118. data/test/support/connection/ruby.rb +0 -1
  119. data/test/support/connection/synchrony.rb +0 -17
  120. data/test/support/redis_mock.rb +0 -130
  121. data/test/support/ssl/gen_certs.sh +0 -31
  122. data/test/support/ssl/trusted-ca.crt +0 -25
  123. data/test/support/ssl/trusted-ca.key +0 -27
  124. data/test/support/ssl/trusted-cert.crt +0 -81
  125. data/test/support/ssl/trusted-cert.key +0 -28
  126. data/test/support/ssl/untrusted-ca.crt +0 -26
  127. data/test/support/ssl/untrusted-ca.key +0 -27
  128. data/test/support/ssl/untrusted-cert.crt +0 -82
  129. data/test/support/ssl/untrusted-cert.key +0 -28
  130. data/test/support/wire/synchrony.rb +0 -24
  131. data/test/support/wire/thread.rb +0 -5
  132. data/test/synchrony_driver.rb +0 -85
  133. data/test/test.conf.erb +0 -9
  134. data/test/thread_safety_test.rb +0 -60
  135. data/test/transactions_test.rb +0 -262
  136. data/test/unknown_commands_test.rb +0 -12
  137. data/test/url_param_test.rb +0 -136
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0f10522316b60319f14cbbf00cf0c82f13092997
4
- data.tar.gz: 1aab75c09b750f2f2f5038cc14366b3c79e0e01c
2
+ SHA256:
3
+ metadata.gz: f05fc65d18e66102ceebb0265050bcb894fce023ee63f8cdaa2272d5be1a5ce8
4
+ data.tar.gz: 05b344759e2826d578e960bd17d92426154f6af867642999a509e06546a00cdd
5
5
  SHA512:
6
- metadata.gz: 78b8a72a6bc475aa55543abf515b3758af1a696a3f1adcaa9019898bf99acf0162383964880b1e6d07113205d0129ed84563de44a4680f9f15cc5893c44efae0
7
- data.tar.gz: ad7ed9b0a0afb0a6c85bf5cd9cada2081c64b3b25856e0343bef61a62e2f4c7f376f42c32013092ec4dde55ed4182c6b11d1f0ace54167f49a597181abdbcf29
6
+ metadata.gz: 9951f6209729a2de685e54e620db9ac22d18d2d6041bb6e22836de1e0fcb9b6c61e89604059034657d07cead0245b3b8d86b7382649605055c1a89941161ee1a
7
+ data.tar.gz: d5f6a938e29d61bcb2de4cfc89f15fb711a8d4b94614a27bbe1c6e8e0a87fe9fa385145f5e5a59324fb3ffa7fc2a441b8ea6d98c8748a3af395969ba5643241b
data/CHANGELOG.md CHANGED
@@ -1,4 +1,246 @@
1
- # 4.0 (unreleased)
1
+ # Unreleased
2
+
3
+ # 5.0.0
4
+
5
+ - Eagerly and strictly cast Integer and Float parameters.
6
+ - Allow to call `subscribe`, `unsubscribe`, `psubscribe` and `punsubscribe` from a subscribed client. See #1131.
7
+ - Use `MD5` for hashing server nodes in `Redis::Distributed`. This should improve keys distribution among servers. See #1089.
8
+ - Changed `sadd` and `srem` to now always return an Integer.
9
+ - Added `sadd?` and `srem?` which always return a Boolean.
10
+ - Added support for `IDLE` paramter in `xpending`.
11
+ - Cluster support has been moved to a `redis-clustering` companion gem.
12
+ - `select` no longer record the current database. If the client has to reconnect after `select` was used, it will reconnect to the original database.
13
+ - Better support Float timeout in blocking commands. See #977.
14
+ - Removed positional timeout in blocking commands (`BLPOP`, etc). Timeout now must be passed as an option: `r.blpop("key", timeout: 2.5)`
15
+ - Removed `logger` option.
16
+ - Removed `reconnect_delay_max` and `reconnect_delay`, you can pass precise sleep durations to `reconnect_attempts` instead.
17
+ - Require Ruby 2.5+.
18
+ - Removed the deprecated `queue` and `commit` methods. Use `pipelined` instead.
19
+ - Removed the deprecated `Redis::Future#==`.
20
+ - Removed the deprecated `pipelined` and `multi` signature. Commands now MUST be called on the block argument, not the original redis instance.
21
+ - Removed `Redis.current`. You shouldn't assume there is a single global Redis connection, use a connection pool instead,
22
+ and libaries using Redis should accept a Redis instance (or connection pool) as a config. E.g. `MyLibrary.redis = Redis.new(...)`.
23
+ - Removed the `synchrony` driver.
24
+ - Removed `Redis.exists_returns_integer`, it's now always enabled.
25
+
26
+ # 4.8.0
27
+
28
+ * Introduce `sadd?` and `srem?` as boolean returning versions of `sadd` and `srem`.
29
+ * Deprecate `sadd` and `srem` returning a boolean when called with a single argument.
30
+ To enable the redis 5.0 behavior you can set `Redis.sadd_returns_boolean = true`.
31
+ * Deprecate passing `timeout` as a positional argument in blocking commands (`brpop`, `blop`, etc).
32
+
33
+ # 4.7.1
34
+
35
+ * Gracefully handle OpenSSL 3.0 EOF Errors (`OpenSSL::SSL::SSLError: SSL_read: unexpected eof while reading`). See #1106
36
+ This happens frequently on heroku-22.
37
+
38
+ # 4.7.0
39
+
40
+ * Support single endpoint architecture with SSL/TLS in cluster mode. See #1086.
41
+ * `zrem` and `zadd` act as noop when provided an empty list of keys. See #1097.
42
+ * Support IPv6 URLs.
43
+ * Add `Redis#with` for better compatibility with `connection_pool` usage.
44
+ * Fix the block form of `multi` called inside `pipelined`. Previously the `MUTLI/EXEC` wouldn't be sent. See #1073.
45
+
46
+ # 4.6.0
47
+
48
+ * Deprecate `Redis.current`.
49
+ * Deprecate calling commands on `Redis` inside `Redis#pipelined`. See #1059.
50
+ ```ruby
51
+ redis.pipelined do
52
+ redis.get("key")
53
+ end
54
+ ```
55
+
56
+ should be replaced by:
57
+
58
+ ```ruby
59
+ redis.pipelined do |pipeline|
60
+ pipeline.get("key")
61
+ end
62
+ ```
63
+ * Deprecate calling commands on `Redis` inside `Redis#multi`. See #1059.
64
+ ```ruby
65
+ redis.multi do
66
+ redis.get("key")
67
+ end
68
+ ```
69
+
70
+ should be replaced by:
71
+
72
+ ```ruby
73
+ redis.multi do |transaction|
74
+ transaction.get("key")
75
+ end
76
+ ```
77
+ * Deprecate `Redis#queue` and `Redis#commit`. See #1059.
78
+
79
+ * Fix `zpopmax` and `zpopmin` when called inside a pipeline. See #1055.
80
+ * `Redis#synchronize` is now private like it should always have been.
81
+
82
+ * Add `Redis.silence_deprecations=` to turn off deprecation warnings.
83
+ If you don't wish to see warnings yet, you can set `Redis.silence_deprecations = true`.
84
+ It is however heavily recommended to fix them instead when possible.
85
+ * Add `Redis.raise_deprecations=` to turn deprecation warnings into errors.
86
+ This makes it easier to identitify the source of deprecated APIs usage.
87
+ It is recommended to set `Redis.raise_deprecations = true` in development and test environments.
88
+ * Add new options to ZRANGE. See #1053.
89
+ * Add ZRANGESTORE command. See #1053.
90
+ * Add SCAN support for `Redis::Cluster`. See #1049.
91
+ * Add COPY command. See #1053. See #1048.
92
+ * Add ZDIFFSTORE command. See #1046.
93
+ * Add ZDIFF command. See #1044.
94
+ * Add ZUNION command. See #1042.
95
+ * Add HRANDFIELD command. See #1040.
96
+
97
+ # 4.5.1
98
+
99
+ * Restore the accidential auth behavior of redis-rb 4.3.0 with a warning. If provided with the `default` user's password, but a wrong username,
100
+ redis-rb will first try to connect as the provided user, but then will fallback to connect as the `default` user with the provided password.
101
+ This behavior is deprecated and will be removed in Redis 4.6.0. Fix #1038.
102
+
103
+ # 4.5.0
104
+
105
+ * Handle parts of the command using incompatible encodings. See #1037.
106
+ * Add GET option to SET command. See #1036.
107
+ * Add ZRANDMEMBER command. See #1035.
108
+ * Add LMOVE/BLMOVE commands. See #1034.
109
+ * Add ZMSCORE command. See #1032.
110
+ * Add LT/GT options to ZADD. See #1033.
111
+ * Add SMISMEMBER command. See #1031.
112
+ * Add EXAT/PXAT options to SET. See #1028.
113
+ * Add GETDEL/GETEX commands. See #1024.
114
+ * `Redis#exists` now returns an Integer by default, as warned since 4.2.0. The old behavior can be restored with `Redis.exists_returns_integer = false`.
115
+ * Fix Redis < 6 detection during connect. See #1025.
116
+ * Fix fetching command details in Redis cluster when the first node is unhealthy. See #1026.
117
+
118
+ # 4.4.0
119
+
120
+ * Redis cluster: fix cross-slot validation in pipelines. Fix ##1019.
121
+ * Add support for `XAUTOCLAIM`. See #1018.
122
+ * Properly issue `READONLY` when reconnecting to replicas. Fix #1017.
123
+ * Make `del` a noop if passed an empty list of keys. See #998.
124
+ * Add support for `ZINTER`. See #995.
125
+
126
+ # 4.3.1
127
+
128
+ * Fix password authentication against redis server 5 and older.
129
+
130
+ # 4.3.0
131
+
132
+ * Add the TYPE argument to scan and scan_each. See #985.
133
+ * Support AUTH command for ACL. See #967.
134
+
135
+ # 4.2.5
136
+
137
+ * Optimize the ruby connector write buffering. See #964.
138
+
139
+ # 4.2.4
140
+
141
+ * Fix bytesize calculations in the ruby connector, and work on a copy of the buffer. Fix #961, #962.
142
+
143
+ # 4.2.3
144
+
145
+ * Use io/wait instead of IO.select in the ruby connector. See #960.
146
+ * Use exception free non blocking IOs in the ruby connector. See #926.
147
+ * Prevent corruption of the client when an interrupt happen during inside a pipeline block. See #945.
148
+
149
+ # 4.2.2
150
+
151
+ * Fix `WATCH` support for `Redis::Distributed`. See #941.
152
+ * Fix handling of empty stream responses. See #905, #929.
153
+
154
+ # 4.2.1
155
+
156
+ * Fix `exists?` returning an actual boolean when called with multiple keys. See #918.
157
+ * Setting `Redis.exists_returns_integer = false` disables warning message about new behaviour. See #920.
158
+
159
+ # 4.2.0
160
+
161
+ * Convert commands to accept keyword arguments rather than option hashes. This both help catching typos, and reduce needless allocations.
162
+ * Deprecate the synchrony driver. It will be removed in 5.0 and hopefully maintained as a separate gem. See #915.
163
+ * Make `Redis#exists` variadic, will return an Integer if called with multiple keys.
164
+ * Add `Redis#exists?` to get a Boolean if any of the keys exists.
165
+ * `Redis#exists` when called with a single key will warn that future versions will return an Integer.
166
+ Set `Redis.exists_returns_integer = true` to opt-in to the new behavior.
167
+ * Support `keepttl` ooption in `set`. See #913.
168
+ * Optimized initialization of Redis::Cluster. See #912.
169
+ * Accept sentinel options even with string key. See #599.
170
+ * Verify TLS connections by default. See #900.
171
+ * Make `Redis#hset` variadic. It now returns an integer, not a boolean. See #910.
172
+
173
+ # 4.1.4
174
+
175
+ * Alias `Redis#disconnect` as `#close`. See #901.
176
+ * Handle clusters with multiple slot ranges. See #894.
177
+ * Fix password authentication to a redis cluster. See #889.
178
+ * Handle recursive MOVED responses. See #882.
179
+ * Increase buffer size in the ruby connector. See #880.
180
+ * Fix thread safety of `Redis.queue`. See #878.
181
+ * Deprecate `Redis::Future#==` as it's likely to be a mistake. See #876.
182
+ * Support `KEEPTTL` option for SET command. See #913.
183
+
184
+ # 4.1.3
185
+
186
+ * Fix the client hanging forever when connecting with SSL to a non-SSL server. See #835.
187
+
188
+ # 4.1.2
189
+
190
+ * Fix several authentication problems with sentinel. See #850 and #856.
191
+ * Explicitly drop Ruby 2.2 support.
192
+
193
+
194
+ # 4.1.1
195
+
196
+ * Fix error handling in multi blocks. See #754.
197
+ * Fix geoadd to accept arrays like georadius and georadiusbymember. See #841.
198
+ * Fix georadius command failing when long == lat. See #841.
199
+ * Fix timeout error in xread block: 0. See #837.
200
+ * Fix incompatibility issue with redis-objects. See #834.
201
+ * Properly handle Errno::EADDRNOTAVAIL on connect.
202
+ * Fix password authentication to sentinel instances. See #813.
203
+
204
+ # 4.1.0
205
+
206
+ * Add Redis Cluster support. See #716.
207
+ * Add streams support. See #799 and #811.
208
+ * Add ZPOP* support. See #812.
209
+ * Fix issues with integer-like objects as BPOP timeout
210
+
211
+ # 4.0.3
212
+
213
+ * Fix raising command error for first command in pipeline. See #788.
214
+ * Fix the gemspec to stop exposing a `build` executable. See #785.
215
+ * Add `:reconnect_delay` and `:reconnect_delay_max` options. See #778.
216
+
217
+ # 4.0.2
218
+
219
+ * Added `Redis#unlink`. See #766.
220
+
221
+ * `Redis.new` now accept a custom connector via `:connector`. See #591.
222
+
223
+ * `Redis#multi` no longer perform empty transactions. See #747.
224
+
225
+ * `Redis#hdel` now accepts hash keys as multiple arguments like `#del`. See #755.
226
+
227
+ * Allow to skip SSL verification. See #745.
228
+
229
+ * Add Geo commands: `geoadd`, `geohash`, `georadius`, `georadiusbymember`, `geopos`, `geodist`. See #730.
230
+
231
+ # 4.0.1
232
+
233
+ * `Redis::Distributed` now supports `mget` and `mapped_mget`. See #687.
234
+
235
+ * `Redis::Distributed` now supports `sscan` and `sscan_each`. See #572.
236
+
237
+ * `Redis#connection` returns a hash with connection information.
238
+ You shouldn't need to call `Redis#_client`, ever.
239
+
240
+ * `Redis#flushdb` and `Redis#flushall` now support the `:async` option. See #706.
241
+
242
+
243
+ # 4.0
2
244
 
3
245
  * Removed `Redis.connect`. Use `Redis.new`.
4
246
 
@@ -9,6 +251,15 @@
9
251
 
10
252
  * Dropped official support for Ruby < 2.2.2.
11
253
 
254
+ # 3.3.5
255
+
256
+ * Fixed Ruby 1.8 compatibility after backporting `Redis#connection`. See #719.
257
+
258
+ # 3.3.4 (yanked)
259
+
260
+ * `Redis#connection` returns a hash with connection information.
261
+ You shouldn't need to call `Redis#_client`, ever.
262
+
12
263
  # 3.3.3
13
264
 
14
265
  * Improved timeout handling after dropping Timeout module.
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link]
1
+ # redis-rb [![Build Status][gh-actions-image]][gh-actions-link] [![Inline docs][inchpages-image]][inchpages-link]
2
2
 
3
- A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still
4
- providing an idiomatic interface.
3
+ A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still providing an idiomatic interface.
5
4
 
5
+ See [RubyDoc.info][rubydoc] for the API docs of the latest published gem.
6
6
 
7
7
  ## Getting started
8
8
 
@@ -34,9 +34,8 @@ You can also specify connection options as a [`redis://` URL][redis-url]:
34
34
  redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
35
35
  ```
36
36
 
37
- By default, the client will try to read the `REDIS_URL` environment variable
38
- and use that as URL to connect to. The above statement is therefore equivalent
39
- to setting this environment variable and calling `Redis.new` without arguments.
37
+ The client expects passwords with special chracters to be URL-encoded (i.e.
38
+ `CGI.escape(password)`).
40
39
 
41
40
  To connect to Redis listening on a Unix socket, try:
42
41
 
@@ -50,6 +49,12 @@ To connect to a password protected Redis instance, use:
50
49
  redis = Redis.new(password: "mysecret")
51
50
  ```
52
51
 
52
+ To connect a Redis instance using [ACL](https://redis.io/topics/acl), use:
53
+
54
+ ```ruby
55
+ redis = Redis.new(username: 'myname', password: 'mysecret')
56
+ ```
57
+
53
58
  The Redis class exports methods that are named identical to the commands
54
59
  they execute. The arguments these methods accept are often identical to
55
60
  the arguments specified on the [Redis website][redis-commands]. For
@@ -66,6 +71,26 @@ redis.get("mykey")
66
71
  All commands, their arguments, and return values are documented and
67
72
  available on [RubyDoc.info][rubydoc].
68
73
 
74
+ ## Connection Pooling and Thread safety
75
+
76
+ The client does not provide connection pooling. Each `Redis` instance
77
+ has one and only one connection to the server, and use of this connection
78
+ is protected by a mutex.
79
+
80
+ As such it is heavilly recommended to use the [`connection_pool` gem](https://github.com/mperham/connection_pool), e.g.:
81
+
82
+ ```ruby
83
+ module MyApp
84
+ def self.redis
85
+ @redis ||= ConnectionPool.new do
86
+ Redis.new(url: ENV["REDIS_URL"])
87
+ end
88
+ end
89
+ end
90
+
91
+ MyApp.redis.incr("some-counter")
92
+ ```
93
+
69
94
  ## Sentinel support
70
95
 
71
96
  The client is able to perform automatic failover by using [Redis
@@ -95,21 +120,19 @@ but a few so that if one is down the client will try the next one. The client
95
120
  is able to remember the last Sentinel that was able to reply correctly and will
96
121
  use it for the next requests.
97
122
 
98
- ## Storing objects
99
-
100
- Redis only stores strings as values. If you want to store an object, you
101
- can use a serialization mechanism such as JSON:
123
+ If you want to [authenticate](https://redis.io/topics/sentinel#configuring-sentinel-instances-with-authentication) Sentinel itself, you must specify the `password` option per instance.
102
124
 
103
125
  ```ruby
104
- require "json"
105
-
106
- redis.set "foo", [1, 2, 3].to_json
107
- # => OK
126
+ SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
127
+ { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
108
128
 
109
- JSON.parse(redis.get("foo"))
110
- # => [1, 2, 3]
129
+ redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master)
111
130
  ```
112
131
 
132
+ ## Cluster support
133
+
134
+ [Clustering](https://redis.io/topics/cluster-spec). is supported via the [`redis-clustering` gem](cluster/).
135
+
113
136
  ## Pipelining
114
137
 
115
138
  When multiple commands are executed sequentially, but are not dependent,
@@ -124,13 +147,24 @@ commands to Redis and gathers their replies. These replies are returned
124
147
  by the `#pipelined` method.
125
148
 
126
149
  ```ruby
127
- redis.pipelined do
128
- redis.set "foo", "bar"
129
- redis.incr "baz"
150
+ redis.pipelined do |pipeline|
151
+ pipeline.set "foo", "bar"
152
+ pipeline.incr "baz"
130
153
  end
131
154
  # => ["OK", 1]
132
155
  ```
133
156
 
157
+ Commands must be called on the yielded objects. If you call methods
158
+ on the original client objects from inside a pipeline, they will be sent immediately:
159
+
160
+ ```ruby
161
+ redis.pipelined do |pipeline|
162
+ pipeline.set "foo", "bar"
163
+ redis.incr "baz" # => 1
164
+ end
165
+ # => ["OK"]
166
+ ```
167
+
134
168
  ### Executing commands atomically
135
169
 
136
170
  You can use `MULTI/EXEC` to run a number of commands in an atomic
@@ -140,9 +174,9 @@ the regular pipeline, the replies to the commands are returned by the
140
174
  `#multi` method.
141
175
 
142
176
  ```ruby
143
- redis.multi do
144
- redis.set "foo", "bar"
145
- redis.incr "baz"
177
+ redis.multi do |transaction|
178
+ transaction.set "foo", "bar"
179
+ transaction.incr "baz"
146
180
  end
147
181
  # => ["OK", 1]
148
182
  ```
@@ -150,21 +184,22 @@ end
150
184
  ### Futures
151
185
 
152
186
  Replies to commands in a pipeline can be accessed via the *futures* they
153
- emit (since redis-rb 3.0). All calls inside a pipeline block return a
187
+ emit. All calls on the pipeline object return a
154
188
  `Future` object, which responds to the `#value` method. When the
155
189
  pipeline has successfully executed, all futures are assigned their
156
190
  respective replies and can be used.
157
191
 
158
192
  ```ruby
159
- redis.pipelined do
160
- @set = redis.set "foo", "bar"
161
- @incr = redis.incr "baz"
193
+ set = incr = nil
194
+ redis.pipelined do |pipeline|
195
+ set = pipeline.set "foo", "bar"
196
+ incr = pipeline.incr "baz"
162
197
  end
163
198
 
164
- @set.value
199
+ set.value
165
200
  # => "OK"
166
201
 
167
- @incr.value
202
+ incr.value
168
203
  # => 1
169
204
  ```
170
205
 
@@ -176,7 +211,7 @@ it can't connect to the server a `Redis::CannotConnectError` error will be raise
176
211
  ```ruby
177
212
  begin
178
213
  redis.ping
179
- rescue Exception => e
214
+ rescue Redis::BaseError => e
180
215
  e.inspect
181
216
  # => #<Redis::CannotConnectError: Timed out connecting to Redis on 10.0.1.1:6380>
182
217
 
@@ -211,6 +246,7 @@ All timeout values are specified in seconds.
211
246
  When using pub/sub, you can subscribe to a channel using a timeout as well:
212
247
 
213
248
  ```ruby
249
+ redis = Redis.new(reconnect_attempts: 0)
214
250
  redis.subscribe_with_timeout(5, "news") do |on|
215
251
  on.message do |channel, message|
216
252
  # ...
@@ -220,14 +256,41 @@ end
220
256
 
221
257
  If no message is received after 5 seconds, the client will unsubscribe.
222
258
 
259
+ ## Reconnections
223
260
 
224
- ## SSL/TLS Support
261
+ **By default**, this gem will only **retry a connection once** and then fail, but
262
+ the client allows you to configure how many `reconnect_attempts` it should
263
+ complete before declaring a connection as failed.
264
+
265
+ ```ruby
266
+ Redis.new(reconnect_attempts: 0)
267
+ Redis.new(reconnect_attempts: 3)
268
+ ```
225
269
 
226
- This library supports natively terminating client side SSL/TLS connections
227
- when talking to Redis via a server-side proxy such as [stunnel], [hitch],
228
- or [ghostunnel].
270
+ If you wish to wait between reconnection attempts, you can instead pass a list
271
+ of durations:
229
272
 
230
- To enable SSL support, pass the `:ssl => :true` option when configuring the
273
+ ```ruby
274
+ Redis.new(reconnect_attempts: [
275
+ 0, # retry immediately
276
+ 0.25 # retry a second time after 250ms
277
+ 1 # retry a third and final time after another 1s
278
+ ])
279
+ ```
280
+
281
+ If you wish to disable reconnection only for some commands, you can use
282
+ `disable_reconnection`:
283
+
284
+ ```ruby
285
+ redis.get("some-key") # this may be retried
286
+ redis.disable_reconnection do
287
+ redis.incr("some-counter") # this won't be retried.
288
+ end
289
+ ```
290
+
291
+ ## SSL/TLS Support
292
+
293
+ To enable SSL support, pass the `:ssl => true` option when configuring the
231
294
  Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
232
295
  You will also need to pass in an `:ssl_params => { ... }` hash used to
233
296
  configure the `OpenSSL::SSL::SSLContext` object used for the connection:
@@ -260,13 +323,7 @@ redis = Redis.new(
260
323
  )
261
324
  ```
262
325
 
263
- [stunnel]: https://www.stunnel.org/
264
- [hitch]: https://hitch-tls.org/
265
- [ghostunnel]: https://github.com/square/ghostunnel
266
- [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
267
-
268
- *NOTE:* SSL is only supported by the default "Ruby" driver
269
-
326
+ [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.5.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
270
327
 
271
328
  ## Expert-Mode Options
272
329
 
@@ -280,17 +337,9 @@ redis = Redis.new(
280
337
  Improper use of `inherit_socket` will result in corrupted and/or incorrect
281
338
  responses.
282
339
 
283
- ## Alternate drivers
340
+ ## hiredis binding
284
341
 
285
342
  By default, redis-rb uses Ruby's socket library to talk with Redis.
286
- To use an alternative connection driver it should be specified as option
287
- when instantiating the client object. These instructions are only valid
288
- for **redis-rb 3.0**. For instructions on how to use alternate drivers from
289
- **redis-rb 2.2**, please refer to an [older README][readme-2.2.2].
290
-
291
- [readme-2.2.2]: https://github.com/redis/redis-rb/blob/v2.2.2/README.md
292
-
293
- ### hiredis
294
343
 
295
344
  The hiredis driver uses the connection facility of hiredis-rb. In turn,
296
345
  hiredis-rb is a binding to the official hiredis client library. It
@@ -300,47 +349,37 @@ extension, JRuby is not supported (by default).
300
349
  It is best to use hiredis when you have large replies (for example:
301
350
  `LRANGE`, `SMEMBERS`, `ZRANGE`, etc.) and/or use big pipelines.
302
351
 
303
- In your Gemfile, include hiredis:
352
+ In your Gemfile, include `hiredis-client`:
304
353
 
305
354
  ```ruby
306
- gem "redis", "~> 3.0.1"
307
- gem "hiredis", "~> 0.4.5"
355
+ gem "redis"
356
+ gem "hiredis-client"
308
357
  ```
309
358
 
310
- When instantiating the client object, specify hiredis:
359
+ If your application doesn't call `Bundler.require`, you may have
360
+ to require it explictly:
311
361
 
312
362
  ```ruby
313
- redis = Redis.new(:driver => :hiredis)
314
- ```
315
-
316
- ### synchrony
317
-
318
- The synchrony driver adds support for [em-synchrony][em-synchrony].
319
- This makes redis-rb work with EventMachine's asynchronous I/O, while not
320
- changing the exposed API. The hiredis gem needs to be available as
321
- well, because the synchrony driver uses hiredis for parsing the Redis
322
- protocol.
323
-
324
- [em-synchrony]: https://github.com/igrigorik/em-synchrony
325
-
326
- In your Gemfile, include em-synchrony and hiredis:
363
+ require "hiredis-client"
364
+ ````
327
365
 
328
- ```ruby
329
- gem "redis", "~> 3.0.1"
330
- gem "hiredis", "~> 0.4.5"
331
- gem "em-synchrony"
332
- ```
366
+ This makes the hiredis driver the default.
333
367
 
334
- When instantiating the client object, specify synchrony:
368
+ If you want to be certain hiredis is being used, when instantiating
369
+ the client object, specify hiredis:
335
370
 
336
371
  ```ruby
337
- redis = Redis.new(:driver => :synchrony)
372
+ redis = Redis.new(driver: :hiredis)
338
373
  ```
339
374
 
340
375
  ## Testing
341
376
 
342
377
  This library is tested against recent Ruby and Redis versions.
343
- Check [Travis][travis-link] for the exact versions supported.
378
+ Check [Github Actions][gh-actions-link] for the exact versions supported.
379
+
380
+ ## See Also
381
+
382
+ - [async-redis](https://github.com/socketry/async-redis) — An [async](https://github.com/socketry/async) compatible Redis client.
344
383
 
345
384
  ## Contributors
346
385
 
@@ -352,15 +391,14 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
352
391
  ## Contributing
353
392
 
354
393
  [Fork the project](https://github.com/redis/redis-rb) and send pull
355
- requests. You can also ask for help at `#redis-rb` on Freenode.
356
-
357
-
358
- [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
359
- [inchpages-link]: https://inch-ci.org/github/redis/redis-rb
360
- [redis-commands]: https://redis.io/commands
361
- [redis-home]: https://redis.io
362
- [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
363
- [travis-home]: https://travis-ci.org/
364
- [travis-image]: https://secure.travis-ci.org/redis/redis-rb.svg?branch=master
365
- [travis-link]: https://travis-ci.org/redis/redis-rb
366
- [rubydoc]: https://www.rubydoc.info/gems/redis
394
+ requests.
395
+
396
+
397
+ [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
398
+ [inchpages-link]: https://inch-ci.org/github/redis/redis-rb
399
+ [redis-commands]: https://redis.io/commands
400
+ [redis-home]: https://redis.io
401
+ [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
402
+ [gh-actions-image]: https://github.com/redis/redis-rb/workflows/Test/badge.svg
403
+ [gh-actions-link]: https://github.com/redis/redis-rb/actions
404
+ [rubydoc]: http://www.rubydoc.info/gems/redis