redis 3.0.0.rc1 → 3.0.0.rc2

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 (77) hide show
  1. data/.travis.yml +50 -0
  2. data/.travis/Gemfile +11 -0
  3. data/CHANGELOG.md +47 -19
  4. data/README.md +160 -149
  5. data/Rakefile +15 -50
  6. data/examples/pubsub.rb +1 -1
  7. data/examples/unicorn/config.ru +1 -1
  8. data/examples/unicorn/unicorn.rb +1 -1
  9. data/lib/redis.rb +790 -390
  10. data/lib/redis/client.rb +137 -49
  11. data/lib/redis/connection/hiredis.rb +26 -15
  12. data/lib/redis/connection/ruby.rb +170 -53
  13. data/lib/redis/connection/synchrony.rb +23 -35
  14. data/lib/redis/distributed.rb +92 -32
  15. data/lib/redis/errors.rb +4 -2
  16. data/lib/redis/pipeline.rb +17 -6
  17. data/lib/redis/version.rb +1 -1
  18. data/redis.gemspec +4 -6
  19. data/test/blocking_commands_test.rb +42 -0
  20. data/test/command_map_test.rb +18 -17
  21. data/test/commands_on_hashes_test.rb +13 -12
  22. data/test/commands_on_lists_test.rb +35 -45
  23. data/test/commands_on_sets_test.rb +55 -54
  24. data/test/commands_on_sorted_sets_test.rb +106 -105
  25. data/test/commands_on_strings_test.rb +64 -55
  26. data/test/commands_on_value_types_test.rb +66 -54
  27. data/test/connection_handling_test.rb +136 -151
  28. data/test/distributed_blocking_commands_test.rb +33 -40
  29. data/test/distributed_commands_on_hashes_test.rb +6 -7
  30. data/test/distributed_commands_on_lists_test.rb +13 -14
  31. data/test/distributed_commands_on_sets_test.rb +57 -58
  32. data/test/distributed_commands_on_sorted_sets_test.rb +11 -12
  33. data/test/distributed_commands_on_strings_test.rb +31 -32
  34. data/test/distributed_commands_on_value_types_test.rb +61 -46
  35. data/test/distributed_commands_requiring_clustering_test.rb +108 -108
  36. data/test/distributed_connection_handling_test.rb +14 -15
  37. data/test/distributed_internals_test.rb +7 -19
  38. data/test/distributed_key_tags_test.rb +36 -36
  39. data/test/distributed_persistence_control_commands_test.rb +17 -14
  40. data/test/distributed_publish_subscribe_test.rb +61 -69
  41. data/test/distributed_remote_server_control_commands_test.rb +39 -28
  42. data/test/distributed_sorting_test.rb +12 -13
  43. data/test/distributed_test.rb +40 -41
  44. data/test/distributed_transactions_test.rb +20 -21
  45. data/test/encoding_test.rb +12 -9
  46. data/test/error_replies_test.rb +42 -36
  47. data/test/helper.rb +118 -85
  48. data/test/helper_test.rb +20 -6
  49. data/test/internals_test.rb +167 -103
  50. data/test/lint/blocking_commands.rb +124 -0
  51. data/test/lint/hashes.rb +115 -93
  52. data/test/lint/lists.rb +86 -80
  53. data/test/lint/sets.rb +68 -62
  54. data/test/lint/sorted_sets.rb +200 -195
  55. data/test/lint/strings.rb +112 -94
  56. data/test/lint/value_types.rb +76 -55
  57. data/test/persistence_control_commands_test.rb +17 -12
  58. data/test/pipelining_commands_test.rb +135 -126
  59. data/test/publish_subscribe_test.rb +105 -110
  60. data/test/remote_server_control_commands_test.rb +74 -58
  61. data/test/sorting_test.rb +31 -29
  62. data/test/support/connection/hiredis.rb +1 -0
  63. data/test/support/connection/ruby.rb +1 -0
  64. data/test/support/connection/synchrony.rb +17 -0
  65. data/test/{redis_mock.rb → support/redis_mock.rb} +24 -21
  66. data/test/support/wire/synchrony.rb +24 -0
  67. data/test/support/wire/thread.rb +5 -0
  68. data/test/synchrony_driver.rb +9 -9
  69. data/test/test.conf +1 -1
  70. data/test/thread_safety_test.rb +21 -19
  71. data/test/transactions_test.rb +189 -118
  72. data/test/unknown_commands_test.rb +9 -8
  73. data/test/url_param_test.rb +46 -41
  74. metadata +28 -43
  75. data/TODO.md +0 -4
  76. data/benchmarking/thread_safety.rb +0 -38
  77. data/test/lint/internals.rb +0 -36
@@ -0,0 +1,50 @@
1
+ language: ruby
2
+
3
+ branches:
4
+ only:
5
+ - master
6
+ - test-unit
7
+
8
+ rvm:
9
+ - 1.8.7
10
+ - 1.9.2
11
+ - 1.9.3
12
+ - jruby-18mode
13
+ - jruby-19mode
14
+
15
+ gemfile:
16
+ - .travis/Gemfile
17
+
18
+ env:
19
+ - conn=ruby
20
+ - conn=hiredis
21
+ - conn=synchrony
22
+
23
+ matrix:
24
+ exclude:
25
+ # hiredis
26
+ - rvm: jruby-18mode
27
+ gemfile: .travis/Gemfile
28
+ env: conn=hiredis
29
+ - rvm: jruby-19mode
30
+ gemfile: .travis/Gemfile
31
+ env: conn=hiredis
32
+
33
+ # synchrony
34
+ - rvm: 1.8.7
35
+ gemfile: .travis/Gemfile
36
+ env: conn=synchrony
37
+ - rvm: jruby-18mode
38
+ gemfile: .travis/Gemfile
39
+ env: conn=synchrony
40
+ - rvm: jruby-19mode
41
+ gemfile: .travis/Gemfile
42
+ env: conn=synchrony
43
+
44
+ notifications:
45
+ irc:
46
+ - irc.freenode.net#redis-rb
47
+ email:
48
+ - damian.janowski@gmail.com
49
+ - michel@soveran.com
50
+ - pcnoordhuis@gmail.com
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ case ENV["conn"]
6
+ when "hiredis"
7
+ gem "hiredis"
8
+ when "synchrony"
9
+ gem "hiredis"
10
+ gem "em-synchrony"
11
+ end
@@ -1,5 +1,33 @@
1
1
  # 3.0 (unreleased)
2
2
 
3
+ * The repository now lives at [https://github.com/redis/redis-rb](https://github.com/redis/redis-rb).
4
+ Thanks, Ezra!
5
+
6
+ * Added support for `PEXPIRE`, `PTTL`, `PEXPIREAT`, `PSETEX`,
7
+ `INCRYBYFLOAT`, `HINCRYBYFLOAT` and `TIME` (Redis 2.6).
8
+
9
+ * `Redis.current` is now thread unsafe, because the client itself is thread safe.
10
+
11
+ In the future you'll be able to do something like:
12
+
13
+ Redis.current = Redis::Pool.connect
14
+
15
+ This makes `Redis.current` actually usable in multi-threaded environments,
16
+ while not affecting those running a single thread.
17
+
18
+ * Change API for `BLPOP`, `BRPOP` and `BRPOPLPUSH`. Both `BLPOP` and
19
+ `BRPOP` now take a single argument equal to a string key, or an array
20
+ with string keys, followed by an optional hash with a `:timeout` key.
21
+ `BRPOPLPUSH` also takes an optional hash with a `:timeout` key as last
22
+ argument for consistency. By default, these commands use a timeout of
23
+ `0` to not time out.
24
+
25
+ * When `SORT` is passed multiple key patterns to get via the `:get`
26
+ option, it now returns an array per result element, holding all `GET`
27
+ substitutions.
28
+
29
+ * The `MSETNX` command now returns a boolean.
30
+
3
31
  * The `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE` and `ZREVRANGEBYSCORE` commands
4
32
  now return an array containing `[String, Float]` pairs when
5
33
  `:with_scores => true` is passed.
@@ -9,34 +37,34 @@
9
37
 
10
38
  * The client now raises custom exceptions where it makes sense.
11
39
 
12
- If by any chance you were rescuing low-level exceptions (`Errno::*`),
13
- you should now rescue as follows:
40
+ If by any chance you were rescuing low-level exceptions (`Errno::*`),
41
+ you should now rescue as follows:
14
42
 
15
- Errno::ECONNRESET -> Redis::ConnectionError
16
- Errno::EPIPE -> Redis::ConnectionError
17
- Errno::ECONNABORTED -> Redis::ConnectionError
18
- Errno::EBADF -> Redis::ConnectionError
19
- Errno::EINVAL -> Redis::ConnectionError
20
- Errno::EAGAIN -> Redis::TimeoutError
21
- Errno::ECONNREFUSED -> Redis::CannotConnectError
43
+ Errno::ECONNRESET -> Redis::ConnectionError
44
+ Errno::EPIPE -> Redis::ConnectionError
45
+ Errno::ECONNABORTED -> Redis::ConnectionError
46
+ Errno::EBADF -> Redis::ConnectionError
47
+ Errno::EINVAL -> Redis::ConnectionError
48
+ Errno::EAGAIN -> Redis::TimeoutError
49
+ Errno::ECONNREFUSED -> Redis::CannotConnectError
22
50
 
23
51
  * Always raise exceptions originating from erroneous command invocation
24
52
  inside pipelines and MULTI/EXEC blocks.
25
53
 
26
- The old behavior (swallowing exceptions) could cause application bugs
27
- to go unnoticed.
54
+ The old behavior (swallowing exceptions) could cause application bugs
55
+ to go unnoticed.
28
56
 
29
57
  * Implement futures for assigning values inside pipelines and MULTI/EXEC
30
58
  blocks. Futures are assigned their value after the pipeline or
31
59
  MULTI/EXEC block has executed.
32
60
 
33
- ```ruby
34
- $redis.pipelined do
35
- @future = $redis.get "key"
36
- end
61
+ ```ruby
62
+ $redis.pipelined do
63
+ @future = $redis.get "key"
64
+ end
37
65
 
38
- puts @future.value
39
- ```
66
+ puts @future.value
67
+ ```
40
68
 
41
69
  * Ruby 1.8.6 is officially not supported.
42
70
 
@@ -45,7 +73,7 @@ puts @future.value
45
73
  * Pipelined commands now return the same replies as when called outside
46
74
  a pipeline.
47
75
 
48
- In the past, pipelined replies were returned without post-processing.
76
+ In the past, pipelined replies were returned without post-processing.
49
77
 
50
78
  * Support `SLOWLOG` command (Michael Bernstein).
51
79
 
@@ -56,7 +84,7 @@ puts @future.value
56
84
 
57
85
  * Connecting using a URL now checks that a host is given.
58
86
 
59
- It's just a small sanity check, cf. #126
87
+ It's just a small sanity check, cf. #126
60
88
 
61
89
  * Support variadic commands introduced in Redis 2.4.
62
90
 
data/README.md CHANGED
@@ -1,195 +1,205 @@
1
- # redis-rb
1
+ # redis-rb [![Build Status][travis-image]][travis-link]
2
2
 
3
- A Ruby client library for the [Redis](http://redis.io) key-value store.
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/
4
6
 
5
- A simple Ruby client trying to match Redis' API one-to-one while still providing a Rubystic interface.
6
- It features thread safety, client-side sharding, and an obsession for performance.
7
+ A Ruby client library for [Redis][redis-home].
7
8
 
8
- ## A note about versions
9
+ [redis-home]: http://redis.io
9
10
 
10
- Versions *1.0.x* target all versions of Redis. You have to use this one if you are using Redis < 1.2.
11
-
12
- Version *2.0* is a big refactoring of the previous version and makes little effort to be
13
- backwards-compatible when it shouldn't. It does not support Redis' original protocol, favoring the
14
- new, binary-safe one. You should be using this version if you're running Redis 1.2+.
15
-
16
- ## Information about Redis
17
-
18
- Redis is a key-value store with some interesting features:
19
-
20
- 1. It's fast.
21
- 2. Keys are strings but values are typed. Currently Redis supports strings, lists, sets, sorted sets and hashes. [Atomic operations](http://redis.io/commands) can be done on all of these types.
22
-
23
- See [the Redis homepage](http://redis.io) for more information.
11
+ A Ruby client that tries to match Redis' API one-to-one, while still
12
+ providing an idiomatic interface. It features thread-safety, client-side
13
+ sharding, pipelining, and an obsession for performance.
24
14
 
25
15
  ## Getting started
26
16
 
27
- You can connect to Redis by instantiating the `Redis` class:
28
-
29
- require "redis"
30
-
31
- redis = Redis.new
32
-
33
- This assumes Redis was started with default values listening on `localhost`, port 6379. If you need to connect to a remote server or a different port, try:
34
-
35
- redis = Redis.new(:host => "10.0.1.1", :port => 6380)
36
-
37
- To connect to Redis listening on a unix socket, try:
38
-
39
- redis = Redis.new(:path => "/tmp/redis.sock")
40
-
41
- Once connected, you can start running commands against Redis:
42
-
43
- >> redis.set "foo", "bar"
44
- => "OK"
45
-
46
- >> redis.get "foo"
47
- => "bar"
48
-
49
- >> redis.sadd "users", "albert"
50
- => true
51
-
52
- >> redis.sadd "users", "bernard"
53
- => true
54
-
55
- >> redis.sadd "users", "charles"
56
- => true
57
-
58
- How many users?
59
-
60
- >> redis.scard "users"
61
- => 3
17
+ As of version 2.0 this client only targets Redis version 2.0 and higher.
18
+ You can use an older version of this client if you need to interface
19
+ with a Redis instance older than 2.0, but this is no longer supported.
62
20
 
63
- Is `albert` a user?
64
-
65
- >> redis.sismember "users", "albert"
66
- => true
67
-
68
- Is `isabel` a user?
69
-
70
- >> redis.sismember "users", "isabel"
71
- => false
21
+ You can connect to Redis by instantiating the `Redis` class:
72
22
 
73
- Handle groups:
23
+ ```ruby
24
+ require "redis"
74
25
 
75
- >> redis.sadd "admins", "albert"
76
- => true
26
+ redis = Redis.new
27
+ ```
77
28
 
78
- >> redis.sadd "admins", "isabel"
79
- => true
29
+ This assumes Redis was started with a default configuration, and it
30
+ listening on `localhost`, port 6379. If you need to connect to a remote
31
+ server or a different port, try:
80
32
 
81
- Users who are also admins:
33
+ ```ruby
34
+ redis = Redis.new(:host => "10.0.1.1", :port => 6380)
35
+ ```
82
36
 
83
- >> redis.sinter "users", "admins"
84
- => ["albert"]
37
+ To connect to Redis listening on a Unix socket, try:
85
38
 
86
- Users who are not admins:
39
+ ```ruby
40
+ redis = Redis.new(:path => "/tmp/redis.sock")
41
+ ```
87
42
 
88
- >> redis.sdiff "users", "admins"
89
- => ["bernard", "charles"]
43
+ The Redis class exports methods that are named identical to the commands
44
+ they execute. The arguments these methods accept are often identical to
45
+ the arguments specified on the [Redis website][redis-commands]. For
46
+ instance, the `SET` and `GET` commands can be called like this:
90
47
 
91
- Admins who are not users:
48
+ [redis-commands]: http://redis.io/commands
92
49
 
93
- >> redis.sdiff "admins", "users"
94
- => ["isabel"]
50
+ ```ruby
51
+ redis.set("mykey", "hello world")
52
+ # => "OK"
95
53
 
96
- All users and admins:
54
+ redis.get("mykey")
55
+ # => "hello world"
56
+ ```
97
57
 
98
- >> redis.sunion "admins", "users"
99
- => ["albert", "bernard", "charles", "isabel"]
58
+ All commands, their arguments and return values are documented, and
59
+ available on [rdoc.info][rdoc].
100
60
 
61
+ [rdoc]: http://rdoc.info/github/redis/redis-rb/
101
62
 
102
63
  ## Storing objects
103
64
 
104
- Redis only stores strings as values. If you want to store an object inside a key, you can use a serialization/deseralization mechanism like JSON:
105
-
106
- >> require 'json'
107
- => true
108
-
109
- >> redis.set "foo", [1, 2, 3].to_json
110
- => OK
111
-
112
- >> JSON.parse(redis.get("foo"))
113
- => [1, 2, 3]
114
-
115
- ## Executing multiple commands atomically
116
-
117
- You can use `MULTI/EXEC` to run arbitrary commands in an atomic fashion:
118
-
119
- redis.multi do
120
- redis.set "foo", "bar"
121
- redis.incr "baz"
122
- end
123
-
124
- ## Multithreaded Operation
125
-
126
- Starting with redis-rb 2.2.0, the client is thread-safe by default. To use
127
- earlier versions safely in a multithreaded environment, be sure to initialize
128
- the client with `:thread_safe => true`. Thread-safety can be explicitly
129
- disabled for versions 2.2 and up by initializing the client with `:thread_safe
130
- => false`.
131
-
132
- See the tests and benchmarks for examples.
65
+ Redis only stores strings as values. If you want to store an object, you
66
+ can use a serialization mechanism such as JSON:
67
+
68
+ ```ruby
69
+ require "json"
70
+
71
+ redis.set "foo", [1, 2, 3].to_json
72
+ # => OK
73
+
74
+ JSON.parse(redis.get("foo"))
75
+ # => [1, 2, 3]
76
+ ```
77
+
78
+ ## Pipelining
79
+
80
+ When multiple commands are executed sequentially, but are not dependent,
81
+ the calls can be *pipelined*. This means that the client doesn't wait
82
+ for reply of the first command before sending the next command. The
83
+ advantage is that multiple commands are sent at once, resulting in
84
+ faster overall execution.
85
+
86
+ The client can be instructed to pipeline commands by using the
87
+ `#pipelined` method. After the block is executed, the client sends all
88
+ commands to Redis and gathers their replies. These replies are returned
89
+ by the `#pipelined` method.
90
+
91
+ ```ruby
92
+ redis.pipelined do
93
+ redis.set "foo", "bar"
94
+ redis.incr "baz"
95
+ end
96
+ # => ["OK", 1]
97
+ ```
98
+
99
+ ### Executing commands atomically
100
+
101
+ You can use `MULTI/EXEC` to run a number of commands in an atomic
102
+ fashion. This is similar to executing a pipeline, but the commands are
103
+ preceded by a call to `MULTI`, and followed by a call to `EXEC`. Like
104
+ the regular pipeline, the replies to the commands are returned by the
105
+ `#multi` method.
106
+
107
+ ```ruby
108
+ redis.multi do
109
+ redis.set "foo", "bar"
110
+ redis.incr "baz"
111
+ end
112
+ # => ["OK", 1]
113
+ ```
114
+
115
+ ### Futures
116
+
117
+ Replies to commands in a pipeline can be accessed via the *futures* they
118
+ emit (since redis-rb 3.0). All calls inside a pipeline block return a
119
+ `Future` object, which responds to the `#value` method. When the
120
+ pipeline has succesfully executed, all futures are assigned their
121
+ respective replies and can be used.
122
+
123
+ ```ruby
124
+ redis.pipelined do
125
+ @set = redis.set "foo", "bar"
126
+ @incr = redis.incr "baz"
127
+ end
128
+
129
+ @set.value
130
+ # => "OK"
131
+
132
+ @incr.value
133
+ # => 1
134
+ ```
133
135
 
134
136
  ## Alternate drivers
135
137
 
136
- Non-default connection drivers are only used when they are explicitly required.
137
138
  By default, redis-rb uses Ruby's socket library to talk with Redis.
139
+ To use an alternative connection driver it should be specified as option
140
+ when instantiating the client object. These instructions are only valid
141
+ for **redis-rb 3.0**. For instructions on how to use alternate drivers from
142
+ **redis-rb 2.2**, please refer to an [older README][readme-2.2.2].
143
+
144
+ [readme-2.2.2]: https://github.com/redis/redis-rb/blob/v2.2.2/README.md
138
145
 
139
146
  ### hiredis
140
147
 
141
- Using redis-rb with hiredis-rb (v0.3 or higher) as backend is done by requiring
142
- `redis/connection/hiredis` before requiring `redis`. This will make redis-rb
143
- pick up hiredis as default driver automatically. This driver optimizes for
144
- speed, at the cost of portability. Since hiredis is a C extension, JRuby is not
145
- supported (by default). Use hiredis when you have large array replies (think
146
- `LRANGE`, `SMEMBERS`, `ZRANGE`, etc.) and/or large pipelines of commands.
148
+ The hiredis driver uses the connection facility of hiredis-rb. In turn,
149
+ hiredis-rb is a binding to the official hiredis client library. It
150
+ optimizes for speed, at the cost of portability. Because it is a C
151
+ extension, JRuby is not supported (by default).
147
152
 
148
- Using redis-rb with hiredis from a Gemfile:
153
+ It is best to use hiredis when you have large replies (for example:
154
+ `LRANGE`, `SMEMBERS`, `ZRANGE`, etc.) and/or use big pipelines.
149
155
 
150
- gem "hiredis", "~> 0.3.1"
151
- gem "redis", "~> 2.2.0", :require => ["redis/connection/hiredis", "redis"]
156
+ In your Gemfile, include hiredis:
152
157
 
153
- ### synchrony
158
+ ```ruby
159
+ gem "redis", "~> 3.0.0.rc2"
160
+ gem "hiredis", "~> 0.4.5"
161
+ ```
154
162
 
155
- This driver adds support for
156
- [em-synchrony](https://github.com/igrigorik/em-synchrony). Using the synchrony
157
- backend from redis-rb is done by requiring `redis/connection/synchrony` before
158
- requiring `redis`. This driver makes redis-rb work with EventMachine's
159
- asynchronous I/O, while not changing the exposed API. The hiredis gem needs to
160
- be available as well, because the synchrony driver uses hiredis for parsing the
161
- Redis protocol.
163
+ When instantiating the client object, specify hiredis:
162
164
 
163
- Using redis-rb with synchrony from a Gemfile:
165
+ ```ruby
166
+ redis = Redis.new(:driver => :hiredis)
167
+ ```
164
168
 
165
- gem "hiredis", "~> 0.3.1"
166
- gem "em-synchrony"
167
- gem "redis", "~> 2.2.0", :require => ["redis/connection/synchrony", "redis"]
169
+ ### synchrony
168
170
 
169
- ## Testing
171
+ The synchrony driver adds support for [em-synchrony][em-synchrony].
172
+ This makes redis-rb work with EventMachine's asynchronous I/O, while not
173
+ changing the exposed API. The hiredis gem needs to be available as
174
+ well, because the synchrony driver uses hiredis for parsing the Redis
175
+ protocol.
170
176
 
171
- This library (v2.2) is tested against the following interpreters:
177
+ [em-synchrony]: https://github.com/igrigorik/em-synchrony
172
178
 
173
- * MRI 1.8.7 (drivers: Ruby, hiredis)
174
- * MRI 1.9.2 (drivers: Ruby, hiredis, em-synchrony)
175
- * JRuby 1.6 (drivers: Ruby)
176
- * Rubinius 1.2 (drivers: Ruby, hiredis)
179
+ In your Gemfile, include em-synchrony and hiredis:
177
180
 
178
- ## Known issues
181
+ ```ruby
182
+ gem "redis", "~> 3.0.0.rc2"
183
+ gem "hiredis", "~> 0.4.5"
184
+ gem "em-synchrony"
185
+ ```
179
186
 
180
- * Ruby 1.9 doesn't raise on socket timeouts in `IO#read` but rather retries the
181
- read operation. This means socket timeouts don't work on 1.9 when using the
182
- pure Ruby I/O code. Use hiredis when you want use socket timeouts on 1.9.
187
+ When instantiating the client object, specify hiredis:
183
188
 
184
- * Ruby 1.8 *does* raise on socket timeouts in `IO#read`, but prints a warning
185
- that using `IO#read` for non blocking reads is obsolete. This is wrong, since
186
- the read is in fact blocking, but `EAGAIN` (which is returned on socket
187
- timeouts) is interpreted as if the read was non blocking. Use hiredis to
188
- prevent seeing this warning.
189
+ ```ruby
190
+ redis = Redis.new(:driver => :synchrony)
191
+ ```
192
+
193
+ ## Testing
189
194
 
190
- ## More info
195
+ This library is tested using [Travis][travis-home], where it is tested
196
+ against the following interpreters and drivers:
191
197
 
192
- Check the [Redis Command Reference](http://redis.io/commands) or check the tests to find out how to use this client.
198
+ * MRI 1.8.7 (drivers: ruby, hiredis)
199
+ * MRI 1.9.2 (drivers: ruby, hiredis, synchrony)
200
+ * MRI 1.9.3 (drivers: ruby, hiredis, synchrony)
201
+ * JRuby 1.6 (1.8 mode) (drivers: ruby)
202
+ * JRuby 1.6 (1.9 mode) (drivers: ruby)
193
203
 
194
204
  ## Contributors
195
205
 
@@ -211,4 +221,5 @@ all contributors)
211
221
 
212
222
  ## Contributing
213
223
 
214
- [Fork the project](http://github.com/ezmobius/redis-rb) and send pull requests. You can also ask for help at `#redis-rb` on Freenode.
224
+ [Fork the project](https://github.com/redis/redis-rb) and send pull
225
+ requests. You can also ask for help at `#redis-rb` on Freenode.