redis 3.2.0 → 4.6.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 (133) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +278 -15
  3. data/README.md +260 -76
  4. data/lib/redis/client.rb +239 -115
  5. data/lib/redis/cluster/command.rb +79 -0
  6. data/lib/redis/cluster/command_loader.rb +33 -0
  7. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  8. data/lib/redis/cluster/node.rb +120 -0
  9. data/lib/redis/cluster/node_key.rb +31 -0
  10. data/lib/redis/cluster/node_loader.rb +37 -0
  11. data/lib/redis/cluster/option.rb +93 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +49 -0
  14. data/lib/redis/cluster.rb +315 -0
  15. data/lib/redis/commands/bitmaps.rb +63 -0
  16. data/lib/redis/commands/cluster.rb +45 -0
  17. data/lib/redis/commands/connection.rb +58 -0
  18. data/lib/redis/commands/geo.rb +84 -0
  19. data/lib/redis/commands/hashes.rb +251 -0
  20. data/lib/redis/commands/hyper_log_log.rb +37 -0
  21. data/lib/redis/commands/keys.rb +411 -0
  22. data/lib/redis/commands/lists.rb +289 -0
  23. data/lib/redis/commands/pubsub.rb +72 -0
  24. data/lib/redis/commands/scripting.rb +114 -0
  25. data/lib/redis/commands/server.rb +188 -0
  26. data/lib/redis/commands/sets.rb +207 -0
  27. data/lib/redis/commands/sorted_sets.rb +804 -0
  28. data/lib/redis/commands/streams.rb +382 -0
  29. data/lib/redis/commands/strings.rb +313 -0
  30. data/lib/redis/commands/transactions.rb +92 -0
  31. data/lib/redis/commands.rb +242 -0
  32. data/lib/redis/connection/command_helper.rb +7 -10
  33. data/lib/redis/connection/hiredis.rb +11 -6
  34. data/lib/redis/connection/registry.rb +2 -1
  35. data/lib/redis/connection/ruby.rb +173 -64
  36. data/lib/redis/connection/synchrony.rb +32 -8
  37. data/lib/redis/connection.rb +3 -1
  38. data/lib/redis/distributed.rb +233 -74
  39. data/lib/redis/errors.rb +48 -0
  40. data/lib/redis/hash_ring.rb +30 -72
  41. data/lib/redis/pipeline.rb +145 -12
  42. data/lib/redis/subscribe.rb +20 -13
  43. data/lib/redis/version.rb +3 -1
  44. data/lib/redis.rb +171 -2476
  45. metadata +71 -165
  46. data/.gitignore +0 -15
  47. data/.travis/Gemfile +0 -11
  48. data/.travis.yml +0 -54
  49. data/.yardopts +0 -3
  50. data/Gemfile +0 -4
  51. data/Rakefile +0 -68
  52. data/benchmarking/logging.rb +0 -71
  53. data/benchmarking/pipeline.rb +0 -51
  54. data/benchmarking/speed.rb +0 -21
  55. data/benchmarking/suite.rb +0 -24
  56. data/benchmarking/worker.rb +0 -71
  57. data/examples/basic.rb +0 -15
  58. data/examples/consistency.rb +0 -114
  59. data/examples/dist_redis.rb +0 -43
  60. data/examples/incr-decr.rb +0 -17
  61. data/examples/list.rb +0 -26
  62. data/examples/pubsub.rb +0 -37
  63. data/examples/sentinel/sentinel.conf +0 -9
  64. data/examples/sentinel/start +0 -49
  65. data/examples/sentinel.rb +0 -41
  66. data/examples/sets.rb +0 -36
  67. data/examples/unicorn/config.ru +0 -3
  68. data/examples/unicorn/unicorn.rb +0 -20
  69. data/redis.gemspec +0 -43
  70. data/test/bitpos_test.rb +0 -69
  71. data/test/blocking_commands_test.rb +0 -42
  72. data/test/command_map_test.rb +0 -30
  73. data/test/commands_on_hashes_test.rb +0 -21
  74. data/test/commands_on_hyper_log_log_test.rb +0 -21
  75. data/test/commands_on_lists_test.rb +0 -20
  76. data/test/commands_on_sets_test.rb +0 -77
  77. data/test/commands_on_sorted_sets_test.rb +0 -123
  78. data/test/commands_on_strings_test.rb +0 -101
  79. data/test/commands_on_value_types_test.rb +0 -131
  80. data/test/connection_handling_test.rb +0 -189
  81. data/test/db/.gitkeep +0 -0
  82. data/test/distributed_blocking_commands_test.rb +0 -46
  83. data/test/distributed_commands_on_hashes_test.rb +0 -10
  84. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
  85. data/test/distributed_commands_on_lists_test.rb +0 -22
  86. data/test/distributed_commands_on_sets_test.rb +0 -83
  87. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  88. data/test/distributed_commands_on_strings_test.rb +0 -59
  89. data/test/distributed_commands_on_value_types_test.rb +0 -95
  90. data/test/distributed_commands_requiring_clustering_test.rb +0 -164
  91. data/test/distributed_connection_handling_test.rb +0 -23
  92. data/test/distributed_internals_test.rb +0 -70
  93. data/test/distributed_key_tags_test.rb +0 -52
  94. data/test/distributed_persistence_control_commands_test.rb +0 -26
  95. data/test/distributed_publish_subscribe_test.rb +0 -92
  96. data/test/distributed_remote_server_control_commands_test.rb +0 -66
  97. data/test/distributed_scripting_test.rb +0 -102
  98. data/test/distributed_sorting_test.rb +0 -20
  99. data/test/distributed_test.rb +0 -58
  100. data/test/distributed_transactions_test.rb +0 -32
  101. data/test/encoding_test.rb +0 -18
  102. data/test/error_replies_test.rb +0 -59
  103. data/test/fork_safety_test.rb +0 -65
  104. data/test/helper.rb +0 -232
  105. data/test/helper_test.rb +0 -24
  106. data/test/internals_test.rb +0 -434
  107. data/test/lint/blocking_commands.rb +0 -150
  108. data/test/lint/hashes.rb +0 -162
  109. data/test/lint/hyper_log_log.rb +0 -60
  110. data/test/lint/lists.rb +0 -143
  111. data/test/lint/sets.rb +0 -125
  112. data/test/lint/sorted_sets.rb +0 -238
  113. data/test/lint/strings.rb +0 -260
  114. data/test/lint/value_types.rb +0 -122
  115. data/test/persistence_control_commands_test.rb +0 -26
  116. data/test/pipelining_commands_test.rb +0 -242
  117. data/test/publish_subscribe_test.rb +0 -210
  118. data/test/remote_server_control_commands_test.rb +0 -117
  119. data/test/scanning_test.rb +0 -413
  120. data/test/scripting_test.rb +0 -78
  121. data/test/sorting_test.rb +0 -59
  122. data/test/support/connection/hiredis.rb +0 -1
  123. data/test/support/connection/ruby.rb +0 -1
  124. data/test/support/connection/synchrony.rb +0 -17
  125. data/test/support/redis_mock.rb +0 -115
  126. data/test/support/wire/synchrony.rb +0 -24
  127. data/test/support/wire/thread.rb +0 -5
  128. data/test/synchrony_driver.rb +0 -88
  129. data/test/test.conf +0 -9
  130. data/test/thread_safety_test.rb +0 -32
  131. data/test/transactions_test.rb +0 -264
  132. data/test/unknown_commands_test.rb +0 -14
  133. data/test/url_param_test.rb +0 -132
data/README.md CHANGED
@@ -1,31 +1,17 @@
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
- [travis-image]: https://secure.travis-ci.org/redis/redis-rb.png?branch=master
4
- [travis-link]: http://travis-ci.org/redis/redis-rb
5
- [travis-home]: http://travis-ci.org/
6
- [inchpages-image]: http://inch-pages.github.io/github/redis/redis-rb.png
7
- [inchpages-link]: http://inch-pages.github.io/github/redis/redis-rb
3
+ A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still
4
+ providing an idiomatic interface.
8
5
 
9
- A Ruby client library for [Redis][redis-home].
10
-
11
- [redis-home]: http://redis.io
12
-
13
- A Ruby client that tries to match Redis' API one-to-one, while still
14
- providing an idiomatic interface. It features thread-safety, client-side
15
- sharding, pipelining, and an obsession for performance.
16
-
17
- ## Upgrading from 2.x to 3.0
18
-
19
- Please refer to the [CHANGELOG][changelog-3.0.0] for a summary of the
20
- most important changes, as well as a full list of changes.
21
-
22
- [changelog-3.0.0]: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#300
6
+ See [RubyDoc.info][rubydoc] for the API docs of the latest published gem.
23
7
 
24
8
  ## Getting started
25
9
 
26
- As of version 2.0 this client only targets Redis version 2.0 and higher.
27
- You can use an older version of this client if you need to interface
28
- with a Redis instance older than 2.0, but this is no longer supported.
10
+ Install with:
11
+
12
+ ```
13
+ $ gem install redis
14
+ ```
29
15
 
30
16
  You can connect to Redis by instantiating the `Redis` class:
31
17
 
@@ -40,15 +26,18 @@ listening on `localhost`, port 6379. If you need to connect to a remote
40
26
  server or a different port, try:
41
27
 
42
28
  ```ruby
43
- redis = Redis.new(:host => "10.0.1.1", :port => 6380, :db => 15)
29
+ redis = Redis.new(host: "10.0.1.1", port: 6380, db: 15)
44
30
  ```
45
31
 
46
- You can also specify connection options as an URL:
32
+ You can also specify connection options as a [`redis://` URL][redis-url]:
47
33
 
48
34
  ```ruby
49
- redis = Redis.new(:url => "redis://:p4ssw0rd@10.0.1.1:6380/15")
35
+ redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
50
36
  ```
51
37
 
38
+ The client expects passwords with special chracters to be URL-encoded (i.e.
39
+ `CGI.escape(password)`).
40
+
52
41
  By default, the client will try to read the `REDIS_URL` environment variable
53
42
  and use that as URL to connect to. The above statement is therefore equivalent
54
43
  to setting this environment variable and calling `Redis.new` without arguments.
@@ -56,13 +45,19 @@ to setting this environment variable and calling `Redis.new` without arguments.
56
45
  To connect to Redis listening on a Unix socket, try:
57
46
 
58
47
  ```ruby
59
- redis = Redis.new(:path => "/tmp/redis.sock")
48
+ redis = Redis.new(path: "/tmp/redis.sock")
60
49
  ```
61
50
 
62
51
  To connect to a password protected Redis instance, use:
63
52
 
64
53
  ```ruby
65
- redis = Redis.new(:password => "mysecret")
54
+ redis = Redis.new(password: "mysecret")
55
+ ```
56
+
57
+ To connect a Redis instance using [ACL](https://redis.io/topics/acl), use:
58
+
59
+ ```ruby
60
+ redis = Redis.new(username: 'myname', password: 'mysecret')
66
61
  ```
67
62
 
68
63
  The Redis class exports methods that are named identical to the commands
@@ -70,8 +65,6 @@ they execute. The arguments these methods accept are often identical to
70
65
  the arguments specified on the [Redis website][redis-commands]. For
71
66
  instance, the `SET` and `GET` commands can be called like this:
72
67
 
73
- [redis-commands]: http://redis.io/commands
74
-
75
68
  ```ruby
76
69
  redis.set("mykey", "hello world")
77
70
  # => "OK"
@@ -80,24 +73,22 @@ redis.get("mykey")
80
73
  # => "hello world"
81
74
  ```
82
75
 
83
- All commands, their arguments and return values are documented, and
84
- available on [rdoc.info][rdoc].
85
-
86
- [rdoc]: http://rdoc.info/github/redis/redis-rb/
76
+ All commands, their arguments, and return values are documented and
77
+ available on [RubyDoc.info][rubydoc].
87
78
 
88
79
  ## Sentinel support
89
80
 
90
- The client is able to perform automatic failovers by using [Redis
81
+ The client is able to perform automatic failover by using [Redis
91
82
  Sentinel](http://redis.io/topics/sentinel). Make sure to run Redis 2.8+
92
83
  if you want to use this feature.
93
84
 
94
85
  To connect using Sentinel, use:
95
86
 
96
87
  ```ruby
97
- SENTINELS = [{:host => "127.0.0.1", :port => 26380},
98
- {:host => "127.0.0.1", :port => 26381}]
88
+ SENTINELS = [{ host: "127.0.0.1", port: 26380 },
89
+ { host: "127.0.0.1", port: 26381 }]
99
90
 
100
- redis = Redis.new(:url => "redis://mymaster", :sentinels => SENTINELS, :role => :master)
91
+ redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master)
101
92
  ```
102
93
 
103
94
  * The master name identifies a group of Redis instances composed of a master
@@ -105,7 +96,8 @@ and one or more slaves (`mymaster` in the example).
105
96
 
106
97
  * It is possible to optionally provide a role. The allowed roles are `master`
107
98
  and `slave`. When the role is `slave`, the client will try to connect to a
108
- random slave of the specified master.
99
+ random slave of the specified master. If a role is not specified, the client
100
+ will connect to the master.
109
101
 
110
102
  * When using the Sentinel support you need to specify a list of sentinels to
111
103
  connect to. The list does not need to enumerate all your Sentinel instances,
@@ -113,10 +105,60 @@ but a few so that if one is down the client will try the next one. The client
113
105
  is able to remember the last Sentinel that was able to reply correctly and will
114
106
  use it for the next requests.
115
107
 
108
+ 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.
109
+
110
+ ```ruby
111
+ SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
112
+ { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
113
+
114
+ redis = Redis.new(host: 'mymaster', sentinels: SENTINELS, role: :master)
115
+ ```
116
+
117
+ ## Cluster support
118
+
119
+ `redis-rb` supports [clustering](https://redis.io/topics/cluster-spec).
120
+
121
+ ```ruby
122
+ # Nodes can be passed to the client as an array of connection URLs.
123
+ nodes = (7000..7005).map { |port| "redis://127.0.0.1:#{port}" }
124
+ redis = Redis.new(cluster: nodes)
125
+
126
+ # You can also specify the options as a Hash. The options are the same as for a single server connection.
127
+ (7000..7005).map { |port| { host: '127.0.0.1', port: port } }
128
+ ```
129
+
130
+ You can also specify only a subset of the nodes, and the client will discover the missing ones using the [CLUSTER NODES](https://redis.io/commands/cluster-nodes) command.
131
+
132
+ ```ruby
133
+ Redis.new(cluster: %w[redis://127.0.0.1:7000])
134
+ ```
135
+
136
+ If you want [the connection to be able to read from any replica](https://redis.io/commands/readonly), you must pass the `replica: true`. Note that this connection won't be usable to write keys.
137
+
138
+ ```ruby
139
+ Redis.new(cluster: nodes, replica: true)
140
+ ```
141
+
142
+ The calling code is responsible for [avoiding cross slot commands](https://redis.io/topics/cluster-spec#keys-distribution-model).
143
+
144
+ ```ruby
145
+ redis = Redis.new(cluster: %w[redis://127.0.0.1:7000])
146
+
147
+ redis.mget('key1', 'key2')
148
+ #=> Redis::CommandError (CROSSSLOT Keys in request don't hash to the same slot)
149
+
150
+ redis.mget('{key}1', '{key}2')
151
+ #=> [nil, nil]
152
+ ```
153
+
154
+ * The client automatically reconnects after a failover occurred, but the caller is responsible for handling errors while it is happening.
155
+ * The client support permanent node failures, and will reroute requests to promoted slaves.
156
+ * The client supports `MOVED` and `ASK` redirections transparently.
157
+
116
158
  ## Storing objects
117
159
 
118
- Redis only stores strings as values. If you want to store an object, you
119
- can use a serialization mechanism such as JSON:
160
+ Redis "string" types can be used to store serialized Ruby objects, for
161
+ example with JSON:
120
162
 
121
163
  ```ruby
122
164
  require "json"
@@ -142,9 +184,9 @@ commands to Redis and gathers their replies. These replies are returned
142
184
  by the `#pipelined` method.
143
185
 
144
186
  ```ruby
145
- redis.pipelined do
146
- redis.set "foo", "bar"
147
- redis.incr "baz"
187
+ redis.pipelined do |pipeline|
188
+ pipeline.set "foo", "bar"
189
+ pipeline.incr "baz"
148
190
  end
149
191
  # => ["OK", 1]
150
192
  ```
@@ -158,9 +200,9 @@ the regular pipeline, the replies to the commands are returned by the
158
200
  `#multi` method.
159
201
 
160
202
  ```ruby
161
- redis.multi do
162
- redis.set "foo", "bar"
163
- redis.incr "baz"
203
+ redis.multi do |transaction|
204
+ transaction.set "foo", "bar"
205
+ transaction.incr "baz"
164
206
  end
165
207
  # => ["OK", 1]
166
208
  ```
@@ -168,15 +210,15 @@ end
168
210
  ### Futures
169
211
 
170
212
  Replies to commands in a pipeline can be accessed via the *futures* they
171
- emit (since redis-rb 3.0). All calls inside a pipeline block return a
213
+ emit (since redis-rb 3.0). All calls on the pipeline object return a
172
214
  `Future` object, which responds to the `#value` method. When the
173
- pipeline has succesfully executed, all futures are assigned their
215
+ pipeline has successfully executed, all futures are assigned their
174
216
  respective replies and can be used.
175
217
 
176
218
  ```ruby
177
- redis.pipelined do
178
- @set = redis.set "foo", "bar"
179
- @incr = redis.incr "baz"
219
+ redis.pipelined do |pipeline|
220
+ @set = pipeline.set "foo", "bar"
221
+ @incr = pipeline.incr "baz"
180
222
  end
181
223
 
182
224
  @set.value
@@ -186,6 +228,152 @@ end
186
228
  # => 1
187
229
  ```
188
230
 
231
+ ## Error Handling
232
+
233
+ In general, if something goes wrong you'll get an exception. For example, if
234
+ it can't connect to the server a `Redis::CannotConnectError` error will be raised.
235
+
236
+ ```ruby
237
+ begin
238
+ redis.ping
239
+ rescue StandardError => e
240
+ e.inspect
241
+ # => #<Redis::CannotConnectError: Timed out connecting to Redis on 10.0.1.1:6380>
242
+
243
+ e.message
244
+ # => Timed out connecting to Redis on 10.0.1.1:6380
245
+ end
246
+ ```
247
+
248
+ See lib/redis/errors.rb for information about what exceptions are possible.
249
+
250
+ ## Timeouts
251
+
252
+ The client allows you to configure connect, read, and write timeouts.
253
+ Passing a single `timeout` option will set all three values:
254
+
255
+ ```ruby
256
+ Redis.new(:timeout => 1)
257
+ ```
258
+
259
+ But you can use specific values for each of them:
260
+
261
+ ```ruby
262
+ Redis.new(
263
+ :connect_timeout => 0.2,
264
+ :read_timeout => 1.0,
265
+ :write_timeout => 0.5
266
+ )
267
+ ```
268
+
269
+ All timeout values are specified in seconds.
270
+
271
+ When using pub/sub, you can subscribe to a channel using a timeout as well:
272
+
273
+ ```ruby
274
+ redis = Redis.new(reconnect_attempts: 0)
275
+ redis.subscribe_with_timeout(5, "news") do |on|
276
+ on.message do |channel, message|
277
+ # ...
278
+ end
279
+ end
280
+ ```
281
+
282
+ If no message is received after 5 seconds, the client will unsubscribe.
283
+
284
+ ## Reconnections
285
+
286
+ The client allows you to configure how many `reconnect_attempts` it should
287
+ complete before declaring a connection as failed. Furthermore, you may want
288
+ to control the maximum duration between reconnection attempts with
289
+ `reconnect_delay` and `reconnect_delay_max`.
290
+
291
+ ```ruby
292
+ Redis.new(
293
+ :reconnect_attempts => 10,
294
+ :reconnect_delay => 1.5,
295
+ :reconnect_delay_max => 10.0,
296
+ )
297
+ ```
298
+
299
+ The delay values are specified in seconds. With the above configuration, the
300
+ client would attempt 10 reconnections, exponentially increasing the duration
301
+ between each attempt but it never waits longer than `reconnect_delay_max`.
302
+
303
+ This is the retry algorithm:
304
+
305
+ ```ruby
306
+ attempt_wait_time = [(reconnect_delay * 2**(attempt-1)), reconnect_delay_max].min
307
+ ```
308
+
309
+ **By default**, this gem will only **retry a connection once** and then fail, but with the
310
+ above configuration the reconnection attempt would look like this:
311
+
312
+ #|Attempt wait time|Total wait time
313
+ :-:|:-:|:-:
314
+ 1|1.5s|1.5s
315
+ 2|3.0s|4.5s
316
+ 3|6.0s|10.5s
317
+ 4|10.0s|20.5s
318
+ 5|10.0s|30.5s
319
+ 6|10.0s|40.5s
320
+ 7|10.0s|50.5s
321
+ 8|10.0s|60.5s
322
+ 9|10.0s|70.5s
323
+ 10|10.0s|80.5s
324
+
325
+ So if the reconnection attempt #10 succeeds 70 seconds have elapsed trying
326
+ to reconnect, this is likely fine in long-running background processes, but if
327
+ you use Redis to drive your website you might want to have a lower
328
+ `reconnect_delay_max` or have less `reconnect_attempts`.
329
+
330
+ ## SSL/TLS Support
331
+
332
+ This library supports natively terminating client side SSL/TLS connections
333
+ when talking to Redis via a server-side proxy such as [stunnel], [hitch],
334
+ or [ghostunnel].
335
+
336
+ To enable SSL support, pass the `:ssl => true` option when configuring the
337
+ Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
338
+ You will also need to pass in an `:ssl_params => { ... }` hash used to
339
+ configure the `OpenSSL::SSL::SSLContext` object used for the connection:
340
+
341
+ ```ruby
342
+ redis = Redis.new(
343
+ :url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
344
+ :ssl_params => {
345
+ :ca_file => "/path/to/ca.crt"
346
+ }
347
+ )
348
+ ```
349
+
350
+ The options given to `:ssl_params` are passed directly to the
351
+ `OpenSSL::SSL::SSLContext#set_params` method and can be any valid attribute
352
+ of the SSL context. Please see the [OpenSSL::SSL::SSLContext documentation]
353
+ for all of the available attributes.
354
+
355
+ Here is an example of passing in params that can be used for SSL client
356
+ certificate authentication (a.k.a. mutual TLS):
357
+
358
+ ```ruby
359
+ redis = Redis.new(
360
+ :url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
361
+ :ssl_params => {
362
+ :ca_file => "/path/to/ca.crt",
363
+ :cert => OpenSSL::X509::Certificate.new(File.read("client.crt")),
364
+ :key => OpenSSL::PKey::RSA.new(File.read("client.key"))
365
+ }
366
+ )
367
+ ```
368
+
369
+ [stunnel]: https://www.stunnel.org/
370
+ [hitch]: https://hitch-tls.org/
371
+ [ghostunnel]: https://github.com/square/ghostunnel
372
+ [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
373
+
374
+ *NOTE:* SSL is only supported by the default "Ruby" driver
375
+
376
+
189
377
  ## Expert-Mode Options
190
378
 
191
379
  - `inherit_socket: true`: disable safety check that prevents a forked child
@@ -257,35 +445,31 @@ redis = Redis.new(:driver => :synchrony)
257
445
 
258
446
  ## Testing
259
447
 
260
- This library is tested using [Travis][travis-home], where it is tested
261
- against the following interpreters and drivers:
448
+ This library is tested against recent Ruby and Redis versions.
449
+ Check [Github Actions][gh-actions-link] for the exact versions supported.
450
+
451
+ ## See Also
262
452
 
263
- * MRI 1.8.7 (drivers: ruby, hiredis)
264
- * MRI 1.9.2 (drivers: ruby, hiredis, synchrony)
265
- * MRI 1.9.3 (drivers: ruby, hiredis, synchrony)
266
- * MRI 2.0.0 (drivers: ruby, hiredis, synchrony)
267
- * JRuby 1.7 (1.8 mode) (drivers: ruby)
268
- * JRuby 1.7 (1.9 mode) (drivers: ruby)
453
+ - [async-redis](https://github.com/socketry/async-redis) — An [async](https://github.com/socketry/async) compatible Redis client.
269
454
 
270
455
  ## Contributors
271
456
 
272
- (ordered chronologically with more than 5 commits, see `git shortlog -sn` for
273
- all contributors)
274
-
275
- * Ezra Zygmuntowicz
276
- * Taylor Weibley
277
- * Matthew Clark
278
- * Brian McKinney
279
- * Luca Guidi
280
- * Salvatore Sanfillipo
281
- * Chris Wanstrath
282
- * Damian Janowski
283
- * Michel Martens
284
- * Nick Quaranto
285
- * Pieter Noordhuis
286
- * Ilya Grigorik
457
+ Several people contributed to redis-rb, but we would like to especially
458
+ mention Ezra Zygmuntowicz. Ezra introduced the Ruby community to many
459
+ new cool technologies, like Redis. He wrote the first version of this
460
+ client and evangelized Redis in Rubyland. Thank you, Ezra.
287
461
 
288
462
  ## Contributing
289
463
 
290
464
  [Fork the project](https://github.com/redis/redis-rb) and send pull
291
- requests. You can also ask for help at `#redis-rb` on Freenode.
465
+ requests.
466
+
467
+
468
+ [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
469
+ [inchpages-link]: https://inch-ci.org/github/redis/redis-rb
470
+ [redis-commands]: https://redis.io/commands
471
+ [redis-home]: https://redis.io
472
+ [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
473
+ [gh-actions-image]: https://github.com/redis/redis-rb/workflows/Test/badge.svg
474
+ [gh-actions-link]: https://github.com/redis/redis-rb/actions
475
+ [rubydoc]: http://www.rubydoc.info/gems/redis