redis 3.3.3 → 5.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +280 -12
  3. data/README.md +141 -147
  4. data/lib/redis/client.rb +77 -539
  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 +300 -108
  23. data/lib/redis/errors.rb +22 -1
  24. data/lib/redis/hash_ring.rb +36 -79
  25. data/lib/redis/pipeline.rb +69 -83
  26. data/lib/redis/subscribe.rb +26 -19
  27. data/lib/redis/version.rb +3 -1
  28. data/lib/redis.rb +113 -2685
  29. metadata +40 -218
  30. data/.gitignore +0 -16
  31. data/.travis/Gemfile +0 -11
  32. data/.travis.yml +0 -89
  33. data/.yardopts +0 -3
  34. data/Gemfile +0 -4
  35. data/Rakefile +0 -87
  36. data/benchmarking/logging.rb +0 -71
  37. data/benchmarking/pipeline.rb +0 -51
  38. data/benchmarking/speed.rb +0 -21
  39. data/benchmarking/suite.rb +0 -24
  40. data/benchmarking/worker.rb +0 -71
  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 -44
  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 -429
  57. data/lib/redis/connection/synchrony.rb +0 -133
  58. data/lib/redis/connection.rb +0 -9
  59. data/redis.gemspec +0 -44
  60. data/test/bitpos_test.rb +0 -69
  61. data/test/blocking_commands_test.rb +0 -42
  62. data/test/client_test.rb +0 -59
  63. data/test/command_map_test.rb +0 -30
  64. data/test/commands_on_hashes_test.rb +0 -21
  65. data/test/commands_on_hyper_log_log_test.rb +0 -21
  66. data/test/commands_on_lists_test.rb +0 -20
  67. data/test/commands_on_sets_test.rb +0 -77
  68. data/test/commands_on_sorted_sets_test.rb +0 -137
  69. data/test/commands_on_strings_test.rb +0 -101
  70. data/test/commands_on_value_types_test.rb +0 -133
  71. data/test/connection_handling_test.rb +0 -277
  72. data/test/db/.gitkeep +0 -0
  73. data/test/distributed_blocking_commands_test.rb +0 -46
  74. data/test/distributed_commands_on_hashes_test.rb +0 -10
  75. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
  76. data/test/distributed_commands_on_lists_test.rb +0 -22
  77. data/test/distributed_commands_on_sets_test.rb +0 -83
  78. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  79. data/test/distributed_commands_on_strings_test.rb +0 -59
  80. data/test/distributed_commands_on_value_types_test.rb +0 -95
  81. data/test/distributed_commands_requiring_clustering_test.rb +0 -164
  82. data/test/distributed_connection_handling_test.rb +0 -23
  83. data/test/distributed_internals_test.rb +0 -79
  84. data/test/distributed_key_tags_test.rb +0 -52
  85. data/test/distributed_persistence_control_commands_test.rb +0 -26
  86. data/test/distributed_publish_subscribe_test.rb +0 -92
  87. data/test/distributed_remote_server_control_commands_test.rb +0 -66
  88. data/test/distributed_scripting_test.rb +0 -102
  89. data/test/distributed_sorting_test.rb +0 -20
  90. data/test/distributed_test.rb +0 -58
  91. data/test/distributed_transactions_test.rb +0 -32
  92. data/test/encoding_test.rb +0 -18
  93. data/test/error_replies_test.rb +0 -59
  94. data/test/fork_safety_test.rb +0 -65
  95. data/test/helper.rb +0 -232
  96. data/test/helper_test.rb +0 -24
  97. data/test/internals_test.rb +0 -457
  98. data/test/lint/blocking_commands.rb +0 -150
  99. data/test/lint/hashes.rb +0 -162
  100. data/test/lint/hyper_log_log.rb +0 -60
  101. data/test/lint/lists.rb +0 -143
  102. data/test/lint/sets.rb +0 -140
  103. data/test/lint/sorted_sets.rb +0 -316
  104. data/test/lint/strings.rb +0 -260
  105. data/test/lint/value_types.rb +0 -122
  106. data/test/persistence_control_commands_test.rb +0 -26
  107. data/test/pipelining_commands_test.rb +0 -242
  108. data/test/publish_subscribe_test.rb +0 -282
  109. data/test/remote_server_control_commands_test.rb +0 -118
  110. data/test/scanning_test.rb +0 -413
  111. data/test/scripting_test.rb +0 -78
  112. data/test/sentinel_command_test.rb +0 -80
  113. data/test/sentinel_test.rb +0 -255
  114. data/test/sorting_test.rb +0 -59
  115. data/test/ssl_test.rb +0 -73
  116. data/test/support/connection/hiredis.rb +0 -1
  117. data/test/support/connection/ruby.rb +0 -1
  118. data/test/support/connection/synchrony.rb +0 -17
  119. data/test/support/redis_mock.rb +0 -130
  120. data/test/support/ssl/gen_certs.sh +0 -31
  121. data/test/support/ssl/trusted-ca.crt +0 -25
  122. data/test/support/ssl/trusted-ca.key +0 -27
  123. data/test/support/ssl/trusted-cert.crt +0 -81
  124. data/test/support/ssl/trusted-cert.key +0 -28
  125. data/test/support/ssl/untrusted-ca.crt +0 -26
  126. data/test/support/ssl/untrusted-ca.key +0 -27
  127. data/test/support/ssl/untrusted-cert.crt +0 -82
  128. data/test/support/ssl/untrusted-cert.key +0 -28
  129. data/test/support/wire/synchrony.rb +0 -24
  130. data/test/support/wire/thread.rb +0 -5
  131. data/test/synchrony_driver.rb +0 -88
  132. data/test/test.conf.erb +0 -9
  133. data/test/thread_safety_test.rb +0 -62
  134. data/test/transactions_test.rb +0 -264
  135. data/test/unknown_commands_test.rb +0 -14
  136. data/test/url_param_test.rb +0 -138
data/README.md CHANGED
@@ -1,46 +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-ci.org/github/redis/redis-rb.png
7
- [inchpages-link]: http://inch-ci.org/github/redis/redis-rb
3
+ A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still providing an idiomatic interface.
8
4
 
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
5
+ See [RubyDoc.info][rubydoc] for the API docs of the latest published gem.
23
6
 
24
7
  ## Getting started
25
8
 
26
- To install **redis-rb**, run the following command:
27
-
28
- ```
29
- gem install redis
30
- ```
31
-
32
- Or if you are using **bundler**, add
9
+ Install with:
33
10
 
34
11
  ```
35
- gem 'redis', '~>3.2'
12
+ $ gem install redis
36
13
  ```
37
14
 
38
- to your `Gemfile`, and run `bundle install`
39
-
40
- As of version 2.0 this client only targets Redis version 2.0 and higher.
41
- You can use an older version of this client if you need to interface
42
- with a Redis instance older than 2.0, but this is no longer supported.
43
-
44
15
  You can connect to Redis by instantiating the `Redis` class:
45
16
 
46
17
  ```ruby
@@ -54,31 +25,34 @@ listening on `localhost`, port 6379. If you need to connect to a remote
54
25
  server or a different port, try:
55
26
 
56
27
  ```ruby
57
- redis = Redis.new(:host => "10.0.1.1", :port => 6380, :db => 15)
28
+ redis = Redis.new(host: "10.0.1.1", port: 6380, db: 15)
58
29
  ```
59
30
 
60
31
  You can also specify connection options as a [`redis://` URL][redis-url]:
61
32
 
62
33
  ```ruby
63
- redis = Redis.new(:url => "redis://:p4ssw0rd@10.0.1.1:6380/15")
34
+ redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
64
35
  ```
65
36
 
66
- [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
67
-
68
- By default, the client will try to read the `REDIS_URL` environment variable
69
- and use that as URL to connect to. The above statement is therefore equivalent
70
- 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)`).
71
39
 
72
40
  To connect to Redis listening on a Unix socket, try:
73
41
 
74
42
  ```ruby
75
- redis = Redis.new(:path => "/tmp/redis.sock")
43
+ redis = Redis.new(path: "/tmp/redis.sock")
76
44
  ```
77
45
 
78
46
  To connect to a password protected Redis instance, use:
79
47
 
80
48
  ```ruby
81
- redis = Redis.new(:password => "mysecret")
49
+ redis = Redis.new(password: "mysecret")
50
+ ```
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')
82
56
  ```
83
57
 
84
58
  The Redis class exports methods that are named identical to the commands
@@ -86,8 +60,6 @@ they execute. The arguments these methods accept are often identical to
86
60
  the arguments specified on the [Redis website][redis-commands]. For
87
61
  instance, the `SET` and `GET` commands can be called like this:
88
62
 
89
- [redis-commands]: http://redis.io/commands
90
-
91
63
  ```ruby
92
64
  redis.set("mykey", "hello world")
93
65
  # => "OK"
@@ -96,24 +68,42 @@ redis.get("mykey")
96
68
  # => "hello world"
97
69
  ```
98
70
 
99
- All commands, their arguments and return values are documented, and
100
- available on [rdoc.info][rdoc].
71
+ All commands, their arguments, and return values are documented and
72
+ available on [RubyDoc.info][rubydoc].
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.:
101
81
 
102
- [rdoc]: http://rdoc.info/github/redis/redis-rb/
82
+ ```ruby
83
+ module MyApp
84
+ def self.redis
85
+ @redis ||= ConnectionPool::Wrapper.new do
86
+ Redis.new(url: ENV["REDIS_URL"])
87
+ end
88
+ end
89
+ end
90
+
91
+ MyApp.redis.incr("some-counter")
92
+ ```
103
93
 
104
94
  ## Sentinel support
105
95
 
106
- The client is able to perform automatic failovers by using [Redis
96
+ The client is able to perform automatic failover by using [Redis
107
97
  Sentinel](http://redis.io/topics/sentinel). Make sure to run Redis 2.8+
108
98
  if you want to use this feature.
109
99
 
110
100
  To connect using Sentinel, use:
111
101
 
112
102
  ```ruby
113
- SENTINELS = [{:host => "127.0.0.1", :port => 26380},
114
- {:host => "127.0.0.1", :port => 26381}]
103
+ SENTINELS = [{ host: "127.0.0.1", port: 26380 },
104
+ { host: "127.0.0.1", port: 26381 }]
115
105
 
116
- redis = Redis.new(:url => "redis://mymaster", :sentinels => SENTINELS, :role => :master)
106
+ redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master)
117
107
  ```
118
108
 
119
109
  * The master name identifies a group of Redis instances composed of a master
@@ -130,21 +120,19 @@ but a few so that if one is down the client will try the next one. The client
130
120
  is able to remember the last Sentinel that was able to reply correctly and will
131
121
  use it for the next requests.
132
122
 
133
- ## Storing objects
134
-
135
- Redis only stores strings as values. If you want to store an object, you
136
- 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.
137
124
 
138
125
  ```ruby
139
- require "json"
126
+ SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
127
+ { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
140
128
 
141
- redis.set "foo", [1, 2, 3].to_json
142
- # => OK
143
-
144
- JSON.parse(redis.get("foo"))
145
- # => [1, 2, 3]
129
+ redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master)
146
130
  ```
147
131
 
132
+ ## Cluster support
133
+
134
+ [Clustering](https://redis.io/topics/cluster-spec). is supported via the [`redis-clustering` gem](cluster/).
135
+
148
136
  ## Pipelining
149
137
 
150
138
  When multiple commands are executed sequentially, but are not dependent,
@@ -159,13 +147,24 @@ commands to Redis and gathers their replies. These replies are returned
159
147
  by the `#pipelined` method.
160
148
 
161
149
  ```ruby
162
- redis.pipelined do
163
- redis.set "foo", "bar"
164
- redis.incr "baz"
150
+ redis.pipelined do |pipeline|
151
+ pipeline.set "foo", "bar"
152
+ pipeline.incr "baz"
165
153
  end
166
154
  # => ["OK", 1]
167
155
  ```
168
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
+
169
168
  ### Executing commands atomically
170
169
 
171
170
  You can use `MULTI/EXEC` to run a number of commands in an atomic
@@ -175,9 +174,9 @@ the regular pipeline, the replies to the commands are returned by the
175
174
  `#multi` method.
176
175
 
177
176
  ```ruby
178
- redis.multi do
179
- redis.set "foo", "bar"
180
- redis.incr "baz"
177
+ redis.multi do |transaction|
178
+ transaction.set "foo", "bar"
179
+ transaction.incr "baz"
181
180
  end
182
181
  # => ["OK", 1]
183
182
  ```
@@ -185,21 +184,22 @@ end
185
184
  ### Futures
186
185
 
187
186
  Replies to commands in a pipeline can be accessed via the *futures* they
188
- emit (since redis-rb 3.0). All calls inside a pipeline block return a
187
+ emit. All calls on the pipeline object return a
189
188
  `Future` object, which responds to the `#value` method. When the
190
189
  pipeline has successfully executed, all futures are assigned their
191
190
  respective replies and can be used.
192
191
 
193
192
  ```ruby
194
- redis.pipelined do
195
- @set = redis.set "foo", "bar"
196
- @incr = redis.incr "baz"
193
+ set = incr = nil
194
+ redis.pipelined do |pipeline|
195
+ set = pipeline.set "foo", "bar"
196
+ incr = pipeline.incr "baz"
197
197
  end
198
198
 
199
- @set.value
199
+ set.value
200
200
  # => "OK"
201
201
 
202
- @incr.value
202
+ incr.value
203
203
  # => 1
204
204
  ```
205
205
 
@@ -211,7 +211,7 @@ it can't connect to the server a `Redis::CannotConnectError` error will be raise
211
211
  ```ruby
212
212
  begin
213
213
  redis.ping
214
- rescue Exception => e
214
+ rescue Redis::BaseError => e
215
215
  e.inspect
216
216
  # => #<Redis::CannotConnectError: Timed out connecting to Redis on 10.0.1.1:6380>
217
217
 
@@ -246,6 +246,7 @@ All timeout values are specified in seconds.
246
246
  When using pub/sub, you can subscribe to a channel using a timeout as well:
247
247
 
248
248
  ```ruby
249
+ redis = Redis.new(reconnect_attempts: 0)
249
250
  redis.subscribe_with_timeout(5, "news") do |on|
250
251
  on.message do |channel, message|
251
252
  # ...
@@ -255,14 +256,41 @@ end
255
256
 
256
257
  If no message is received after 5 seconds, the client will unsubscribe.
257
258
 
259
+ ## Reconnections
258
260
 
259
- ## 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
+ ```
269
+
270
+ If you wish to wait between reconnection attempts, you can instead pass a list
271
+ of durations:
260
272
 
261
- This library supports natively terminating client side SSL/TLS connections
262
- when talking to Redis via a server-side proxy such as [stunnel], [hitch],
263
- or [ghostunnel].
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
+ ```
264
290
 
265
- To enable SSL support, pass the `:ssl => :true` option when configuring the
291
+ ## SSL/TLS Support
292
+
293
+ To enable SSL support, pass the `:ssl => true` option when configuring the
266
294
  Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
267
295
  You will also need to pass in an `:ssl_params => { ... }` hash used to
268
296
  configure the `OpenSSL::SSL::SSLContext` object used for the connection:
@@ -295,13 +323,7 @@ redis = Redis.new(
295
323
  )
296
324
  ```
297
325
 
298
- [stunnel]: https://www.stunnel.org/
299
- [hitch]: https://hitch-tls.org/
300
- [ghostunnel]: https://github.com/square/ghostunnel
301
- [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
302
-
303
- *NOTE:* SSL is only supported by the default "Ruby" driver
304
-
326
+ [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.5.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
305
327
 
306
328
  ## Expert-Mode Options
307
329
 
@@ -315,17 +337,9 @@ redis = Redis.new(
315
337
  Improper use of `inherit_socket` will result in corrupted and/or incorrect
316
338
  responses.
317
339
 
318
- ## Alternate drivers
340
+ ## hiredis binding
319
341
 
320
342
  By default, redis-rb uses Ruby's socket library to talk with Redis.
321
- To use an alternative connection driver it should be specified as option
322
- when instantiating the client object. These instructions are only valid
323
- for **redis-rb 3.0**. For instructions on how to use alternate drivers from
324
- **redis-rb 2.2**, please refer to an [older README][readme-2.2.2].
325
-
326
- [readme-2.2.2]: https://github.com/redis/redis-rb/blob/v2.2.2/README.md
327
-
328
- ### hiredis
329
343
 
330
344
  The hiredis driver uses the connection facility of hiredis-rb. In turn,
331
345
  hiredis-rb is a binding to the official hiredis client library. It
@@ -335,76 +349,56 @@ extension, JRuby is not supported (by default).
335
349
  It is best to use hiredis when you have large replies (for example:
336
350
  `LRANGE`, `SMEMBERS`, `ZRANGE`, etc.) and/or use big pipelines.
337
351
 
338
- In your Gemfile, include hiredis:
352
+ In your Gemfile, include `hiredis-client`:
339
353
 
340
354
  ```ruby
341
- gem "redis", "~> 3.0.1"
342
- gem "hiredis", "~> 0.4.5"
355
+ gem "redis"
356
+ gem "hiredis-client"
343
357
  ```
344
358
 
345
- When instantiating the client object, specify hiredis:
359
+ If your application doesn't call `Bundler.require`, you may have
360
+ to require it explictly:
346
361
 
347
362
  ```ruby
348
- redis = Redis.new(:driver => :hiredis)
349
- ```
350
-
351
- ### synchrony
352
-
353
- The synchrony driver adds support for [em-synchrony][em-synchrony].
354
- This makes redis-rb work with EventMachine's asynchronous I/O, while not
355
- changing the exposed API. The hiredis gem needs to be available as
356
- well, because the synchrony driver uses hiredis for parsing the Redis
357
- protocol.
363
+ require "hiredis-client"
364
+ ````
358
365
 
359
- [em-synchrony]: https://github.com/igrigorik/em-synchrony
366
+ This makes the hiredis driver the default.
360
367
 
361
- In your Gemfile, include em-synchrony and hiredis:
368
+ If you want to be certain hiredis is being used, when instantiating
369
+ the client object, specify hiredis:
362
370
 
363
371
  ```ruby
364
- gem "redis", "~> 3.0.1"
365
- gem "hiredis", "~> 0.4.5"
366
- gem "em-synchrony"
367
- ```
368
-
369
- When instantiating the client object, specify synchrony:
370
-
371
- ```ruby
372
- redis = Redis.new(:driver => :synchrony)
372
+ redis = Redis.new(driver: :hiredis)
373
373
  ```
374
374
 
375
375
  ## Testing
376
376
 
377
- This library is tested using [Travis][travis-home], where it is tested
378
- against the following interpreters and drivers:
377
+ This library is tested against recent Ruby and Redis versions.
378
+ Check [Github Actions][gh-actions-link] for the exact versions supported.
379
379
 
380
- * MRI 1.8.7 (drivers: ruby, hiredis)
381
- * MRI 1.9.3 (drivers: ruby, hiredis, synchrony)
382
- * MRI 2.0 (drivers: ruby, hiredis, synchrony)
383
- * MRI 2.1 (drivers: ruby, hiredis, synchrony)
384
- * MRI 2.2 (drivers: ruby, hiredis, synchrony)
385
- * MRI 2.3 (drivers: ruby, hiredis, synchrony)
386
- * JRuby 1.7 (1.8 mode) (drivers: ruby)
387
- * JRuby 1.7 (1.9 mode) (drivers: ruby)
380
+ ## See Also
381
+
382
+ - [async-redis](https://github.com/socketry/async-redis) — An [async](https://github.com/socketry/async) compatible Redis client.
388
383
 
389
384
  ## Contributors
390
385
 
391
- (ordered chronologically with more than 5 commits, see `git shortlog -sn` for
392
- all contributors)
393
-
394
- * Ezra Zygmuntowicz
395
- * Taylor Weibley
396
- * Matthew Clark
397
- * Brian McKinney
398
- * Luca Guidi
399
- * Salvatore Sanfilippo
400
- * Chris Wanstrath
401
- * Damian Janowski
402
- * Michel Martens
403
- * Nick Quaranto
404
- * Pieter Noordhuis
405
- * Ilya Grigorik
386
+ Several people contributed to redis-rb, but we would like to especially
387
+ mention Ezra Zygmuntowicz. Ezra introduced the Ruby community to many
388
+ new cool technologies, like Redis. He wrote the first version of this
389
+ client and evangelized Redis in Rubyland. Thank you, Ezra.
406
390
 
407
391
  ## Contributing
408
392
 
409
393
  [Fork the project](https://github.com/redis/redis-rb) and send pull
410
- requests. You can also ask for help at `#redis-rb` on Freenode.
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