gorsuch-redis 3.0.0.rc1
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.
- data/.gitignore +10 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +113 -0
- data/LICENSE +20 -0
- data/README.md +214 -0
- data/Rakefile +260 -0
- data/TODO.md +4 -0
- data/benchmarking/logging.rb +62 -0
- data/benchmarking/pipeline.rb +51 -0
- data/benchmarking/speed.rb +21 -0
- data/benchmarking/suite.rb +24 -0
- data/benchmarking/thread_safety.rb +38 -0
- data/benchmarking/worker.rb +71 -0
- data/examples/basic.rb +15 -0
- data/examples/dist_redis.rb +43 -0
- data/examples/incr-decr.rb +17 -0
- data/examples/list.rb +26 -0
- data/examples/pubsub.rb +31 -0
- data/examples/sets.rb +36 -0
- data/examples/unicorn/config.ru +3 -0
- data/examples/unicorn/unicorn.rb +20 -0
- data/lib/redis/client.rb +303 -0
- data/lib/redis/connection/command_helper.rb +44 -0
- data/lib/redis/connection/hiredis.rb +52 -0
- data/lib/redis/connection/registry.rb +12 -0
- data/lib/redis/connection/ruby.rb +136 -0
- data/lib/redis/connection/synchrony.rb +131 -0
- data/lib/redis/connection.rb +9 -0
- data/lib/redis/distributed.rb +696 -0
- data/lib/redis/errors.rb +38 -0
- data/lib/redis/hash_ring.rb +131 -0
- data/lib/redis/pipeline.rb +106 -0
- data/lib/redis/subscribe.rb +79 -0
- data/lib/redis/version.rb +3 -0
- data/lib/redis.rb +1724 -0
- data/redis.gemspec +43 -0
- data/test/command_map_test.rb +29 -0
- data/test/commands_on_hashes_test.rb +20 -0
- data/test/commands_on_lists_test.rb +60 -0
- data/test/commands_on_sets_test.rb +76 -0
- data/test/commands_on_sorted_sets_test.rb +108 -0
- data/test/commands_on_strings_test.rb +80 -0
- data/test/commands_on_value_types_test.rb +87 -0
- data/test/connection_handling_test.rb +204 -0
- data/test/db/.gitignore +1 -0
- data/test/distributed_blocking_commands_test.rb +53 -0
- data/test/distributed_commands_on_hashes_test.rb +11 -0
- data/test/distributed_commands_on_lists_test.rb +23 -0
- data/test/distributed_commands_on_sets_test.rb +84 -0
- data/test/distributed_commands_on_sorted_sets_test.rb +19 -0
- data/test/distributed_commands_on_strings_test.rb +49 -0
- data/test/distributed_commands_on_value_types_test.rb +72 -0
- data/test/distributed_commands_requiring_clustering_test.rb +148 -0
- data/test/distributed_connection_handling_test.rb +24 -0
- data/test/distributed_internals_test.rb +27 -0
- data/test/distributed_key_tags_test.rb +52 -0
- data/test/distributed_persistence_control_commands_test.rb +23 -0
- data/test/distributed_publish_subscribe_test.rb +100 -0
- data/test/distributed_remote_server_control_commands_test.rb +42 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +59 -0
- data/test/distributed_transactions_test.rb +33 -0
- data/test/encoding_test.rb +15 -0
- data/test/error_replies_test.rb +53 -0
- data/test/helper.rb +155 -0
- data/test/helper_test.rb +8 -0
- data/test/internals_test.rb +152 -0
- data/test/lint/hashes.rb +140 -0
- data/test/lint/internals.rb +36 -0
- data/test/lint/lists.rb +107 -0
- data/test/lint/sets.rb +90 -0
- data/test/lint/sorted_sets.rb +196 -0
- data/test/lint/strings.rb +133 -0
- data/test/lint/value_types.rb +81 -0
- data/test/persistence_control_commands_test.rb +21 -0
- data/test/pipelining_commands_test.rb +186 -0
- data/test/publish_subscribe_test.rb +158 -0
- data/test/redis_mock.rb +89 -0
- data/test/remote_server_control_commands_test.rb +88 -0
- data/test/sorting_test.rb +43 -0
- data/test/synchrony_driver.rb +57 -0
- data/test/test.conf +9 -0
- data/test/thread_safety_test.rb +30 -0
- data/test/transactions_test.rb +173 -0
- data/test/unknown_commands_test.rb +13 -0
- data/test/url_param_test.rb +59 -0
- metadata +236 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# 3.0 (unreleased)
|
2
|
+
|
3
|
+
* The `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE` and `ZREVRANGEBYSCORE` commands
|
4
|
+
now return an array containing `[String, Float]` pairs when
|
5
|
+
`:with_scores => true` is passed.
|
6
|
+
|
7
|
+
* The `ZINCRBY` and `ZSCORE` commands now return a `Float` score instead
|
8
|
+
of a string holding a representation of the score.
|
9
|
+
|
10
|
+
* The client now raises custom exceptions where it makes sense.
|
11
|
+
|
12
|
+
If by any chance you were rescuing low-level exceptions (`Errno::*`),
|
13
|
+
you should now rescue as follows:
|
14
|
+
|
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
|
22
|
+
|
23
|
+
* Always raise exceptions originating from erroneous command invocation
|
24
|
+
inside pipelines and MULTI/EXEC blocks.
|
25
|
+
|
26
|
+
The old behavior (swallowing exceptions) could cause application bugs
|
27
|
+
to go unnoticed.
|
28
|
+
|
29
|
+
* Implement futures for assigning values inside pipelines and MULTI/EXEC
|
30
|
+
blocks. Futures are assigned their value after the pipeline or
|
31
|
+
MULTI/EXEC block has executed.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
$redis.pipelined do
|
35
|
+
@future = $redis.get "key"
|
36
|
+
end
|
37
|
+
|
38
|
+
puts @future.value
|
39
|
+
```
|
40
|
+
|
41
|
+
* Ruby 1.8.6 is officially not supported.
|
42
|
+
|
43
|
+
* Support `ZCOUNT` in `Redis::Distributed` (Michael Dungan).
|
44
|
+
|
45
|
+
* Pipelined commands now return the same replies as when called outside
|
46
|
+
a pipeline.
|
47
|
+
|
48
|
+
In the past, pipelined replies were returned without post-processing.
|
49
|
+
|
50
|
+
* Support `SLOWLOG` command (Michael Bernstein).
|
51
|
+
|
52
|
+
* Calling `SHUTDOWN` effectively disconnects the client (Stefan Kaes).
|
53
|
+
|
54
|
+
* Basic support for mapping commands so that they can be renamed on the
|
55
|
+
server.
|
56
|
+
|
57
|
+
* Connecting using a URL now checks that a host is given.
|
58
|
+
|
59
|
+
It's just a small sanity check, cf. #126
|
60
|
+
|
61
|
+
* Support variadic commands introduced in Redis 2.4.
|
62
|
+
|
63
|
+
# 2.2.2
|
64
|
+
|
65
|
+
* Added method `Redis::Distributed#hsetnx`.
|
66
|
+
|
67
|
+
# 2.2.1
|
68
|
+
|
69
|
+
* Internal API: Client#call and family are now called with a single array
|
70
|
+
argument, since splatting a large number of arguments (100K+) results in a
|
71
|
+
stack overflow on 1.9.2.
|
72
|
+
|
73
|
+
* The `INFO` command can optionally take a subcommand. When the subcommand is
|
74
|
+
`COMMANDSTATS`, the client will properly format the returned statistics per
|
75
|
+
command. Subcommands for `INFO` are available since Redis v2.3.0 (unstable).
|
76
|
+
|
77
|
+
* Change `IO#syswrite` back to the buffered `IO#write` since some Rubies do
|
78
|
+
short writes for large (1MB+) buffers and some don't (see issue #108).
|
79
|
+
|
80
|
+
# 2.2.0
|
81
|
+
|
82
|
+
* Added method `Redis#without_reconnect` that ensures the client will not try
|
83
|
+
to reconnect when running the code inside the specified block.
|
84
|
+
|
85
|
+
* Thread-safe by default. Thread safety can be explicitly disabled by passing
|
86
|
+
`:thread_safe => false` as argument.
|
87
|
+
|
88
|
+
* Commands called inside a MULTI/EXEC no longer raise error replies, since a
|
89
|
+
successful EXEC means the commands inside the block were executed.
|
90
|
+
|
91
|
+
* MULTI/EXEC blocks are pipelined.
|
92
|
+
|
93
|
+
* Don't disconnect on error replies.
|
94
|
+
|
95
|
+
* Use `IO#syswrite` instead of `IO#write` because write buffering is not
|
96
|
+
necessary.
|
97
|
+
|
98
|
+
* Connect to a unix socket by passing the `:path` option as argument.
|
99
|
+
|
100
|
+
* The timeout value is coerced into a float, allowing sub-second timeouts.
|
101
|
+
|
102
|
+
* Accept both `:with_scores` _and_ `:withscores` as argument to sorted set
|
103
|
+
commands.
|
104
|
+
|
105
|
+
* Use [hiredis](https://github.com/pietern/hiredis-rb) (v0.3 or higher) by
|
106
|
+
requiring "redis/connection/hiredis".
|
107
|
+
|
108
|
+
* Use [em-synchrony](https://github.com/igrigorik/em-synchrony) by requiring
|
109
|
+
"redis/connection/synchrony".
|
110
|
+
|
111
|
+
# 2.1.1
|
112
|
+
|
113
|
+
See commit log.
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ezra Zygmuntowicz
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# redis-rb
|
2
|
+
|
3
|
+
A Ruby client library for the [Redis](http://redis.io) key-value store.
|
4
|
+
|
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
|
+
|
8
|
+
## A note about versions
|
9
|
+
|
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.
|
24
|
+
|
25
|
+
## Getting started
|
26
|
+
|
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
|
62
|
+
|
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
|
72
|
+
|
73
|
+
Handle groups:
|
74
|
+
|
75
|
+
>> redis.sadd "admins", "albert"
|
76
|
+
=> true
|
77
|
+
|
78
|
+
>> redis.sadd "admins", "isabel"
|
79
|
+
=> true
|
80
|
+
|
81
|
+
Users who are also admins:
|
82
|
+
|
83
|
+
>> redis.sinter "users", "admins"
|
84
|
+
=> ["albert"]
|
85
|
+
|
86
|
+
Users who are not admins:
|
87
|
+
|
88
|
+
>> redis.sdiff "users", "admins"
|
89
|
+
=> ["bernard", "charles"]
|
90
|
+
|
91
|
+
Admins who are not users:
|
92
|
+
|
93
|
+
>> redis.sdiff "admins", "users"
|
94
|
+
=> ["isabel"]
|
95
|
+
|
96
|
+
All users and admins:
|
97
|
+
|
98
|
+
>> redis.sunion "admins", "users"
|
99
|
+
=> ["albert", "bernard", "charles", "isabel"]
|
100
|
+
|
101
|
+
|
102
|
+
## Storing objects
|
103
|
+
|
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.
|
133
|
+
|
134
|
+
## Alternate drivers
|
135
|
+
|
136
|
+
Non-default connection drivers are only used when they are explicitly required.
|
137
|
+
By default, redis-rb uses Ruby's socket library to talk with Redis.
|
138
|
+
|
139
|
+
### hiredis
|
140
|
+
|
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.
|
147
|
+
|
148
|
+
Using redis-rb with hiredis from a Gemfile:
|
149
|
+
|
150
|
+
gem "hiredis", "~> 0.3.1"
|
151
|
+
gem "redis", "~> 2.2.0", :require => ["redis/connection/hiredis", "redis"]
|
152
|
+
|
153
|
+
### synchrony
|
154
|
+
|
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.
|
162
|
+
|
163
|
+
Using redis-rb with synchrony from a Gemfile:
|
164
|
+
|
165
|
+
gem "hiredis", "~> 0.3.1"
|
166
|
+
gem "em-synchrony"
|
167
|
+
gem "redis", "~> 2.2.0", :require => ["redis/connection/synchrony", "redis"]
|
168
|
+
|
169
|
+
## Testing
|
170
|
+
|
171
|
+
This library (v2.2) is tested against the following interpreters:
|
172
|
+
|
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)
|
177
|
+
|
178
|
+
## Known issues
|
179
|
+
|
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.
|
183
|
+
|
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
|
+
|
190
|
+
## More info
|
191
|
+
|
192
|
+
Check the [Redis Command Reference](http://redis.io/commands) or check the tests to find out how to use this client.
|
193
|
+
|
194
|
+
## Contributors
|
195
|
+
|
196
|
+
(ordered chronologically with more than 5 commits, see `git shortlog -sn` for
|
197
|
+
all contributors)
|
198
|
+
|
199
|
+
* Ezra Zygmuntowicz
|
200
|
+
* Taylor Weibley
|
201
|
+
* Matthew Clark
|
202
|
+
* Brian McKinney
|
203
|
+
* Luca Guidi
|
204
|
+
* Salvatore Sanfillipo
|
205
|
+
* Chris Wanstrath
|
206
|
+
* Damian Janowski
|
207
|
+
* Michel Martens
|
208
|
+
* Nick Quaranto
|
209
|
+
* Pieter Noordhuis
|
210
|
+
* Ilya Grigorik
|
211
|
+
|
212
|
+
## Contributing
|
213
|
+
|
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.
|
data/Rakefile
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
6
|
+
require 'redis/version'
|
7
|
+
|
8
|
+
REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
|
9
|
+
REDIS_CNF = File.join(REDIS_DIR, "test.conf")
|
10
|
+
REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
|
11
|
+
|
12
|
+
task :default => :run
|
13
|
+
|
14
|
+
desc "Run tests and manage server start/stop"
|
15
|
+
task :run => [:start, :test, :stop]
|
16
|
+
|
17
|
+
desc "Start the Redis server"
|
18
|
+
task :start do
|
19
|
+
redis_running = \
|
20
|
+
begin
|
21
|
+
File.exists?(REDIS_PID) && Process.kill(0, File.read(REDIS_PID).to_i)
|
22
|
+
rescue Errno::ESRCH
|
23
|
+
FileUtils.rm REDIS_PID
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
system "redis-server #{REDIS_CNF}" unless redis_running
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Stop the Redis server"
|
31
|
+
task :stop do
|
32
|
+
if File.exists?(REDIS_PID)
|
33
|
+
Process.kill "INT", File.read(REDIS_PID).to_i
|
34
|
+
FileUtils.rm REDIS_PID
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Run the test suite"
|
39
|
+
task :test => ["test:ruby", "test:hiredis", "test:synchrony"]
|
40
|
+
|
41
|
+
namespace :test do
|
42
|
+
desc "Run tests against the Ruby driver"
|
43
|
+
task :ruby do
|
44
|
+
require "cutest"
|
45
|
+
|
46
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Run tests against the hiredis driver"
|
50
|
+
task :hiredis do
|
51
|
+
require "cutest"
|
52
|
+
|
53
|
+
begin
|
54
|
+
require "redis/connection/hiredis"
|
55
|
+
|
56
|
+
puts
|
57
|
+
puts "Running tests against hiredis v#{Hiredis::VERSION}"
|
58
|
+
|
59
|
+
ENV["REDIS_CONNECTION_DRIVER"] = "hiredis"
|
60
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
61
|
+
rescue LoadError
|
62
|
+
puts "Skipping tests against hiredis"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Run tests against the em-synchrony driver"
|
67
|
+
task :synchrony do
|
68
|
+
require "cutest"
|
69
|
+
|
70
|
+
# Synchrony needs 1.9
|
71
|
+
next if RUBY_VERSION < "1.9"
|
72
|
+
|
73
|
+
begin
|
74
|
+
require "redis/connection/synchrony"
|
75
|
+
|
76
|
+
puts
|
77
|
+
puts "Running tests against em-synchrony"
|
78
|
+
|
79
|
+
threaded_tests = ['./test/thread_safety_test.rb']
|
80
|
+
|
81
|
+
ENV["REDIS_CONNECTION_DRIVER"] = "synchrony"
|
82
|
+
Cutest.run(Dir['./test/**/*_test.rb'] - threaded_tests)
|
83
|
+
rescue LoadError
|
84
|
+
puts "Skipping tests against em-synchrony"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
task :doc => ["doc:generate", "doc:prepare"]
|
90
|
+
|
91
|
+
namespace :doc do
|
92
|
+
task :generate do
|
93
|
+
require "shellwords"
|
94
|
+
|
95
|
+
`rm -rf doc`
|
96
|
+
|
97
|
+
current_branch = `git branch`[/^\* (.*)$/, 1]
|
98
|
+
|
99
|
+
begin
|
100
|
+
tags = `git tag -l`.split("\n").sort.reverse
|
101
|
+
|
102
|
+
tags.each do |tag|
|
103
|
+
`git checkout -q #{tag} 2>/dev/null`
|
104
|
+
|
105
|
+
unless $?.success?
|
106
|
+
$stderr.puts "Need a clean working copy. Please git-stash away."
|
107
|
+
exit 1
|
108
|
+
end
|
109
|
+
|
110
|
+
puts tag
|
111
|
+
|
112
|
+
`mkdir -p doc/#{tag}`
|
113
|
+
|
114
|
+
files = `git ls-tree -r HEAD lib`.split("\n").map do |line|
|
115
|
+
line[/\t(.*)$/, 1]
|
116
|
+
end
|
117
|
+
|
118
|
+
opts = [
|
119
|
+
"--title", "A Ruby client for Redis",
|
120
|
+
"--output", "doc/#{tag}",
|
121
|
+
"--no-cache",
|
122
|
+
"--no-save",
|
123
|
+
"-q",
|
124
|
+
*files
|
125
|
+
]
|
126
|
+
|
127
|
+
`yardoc #{Shellwords.shelljoin opts}`
|
128
|
+
end
|
129
|
+
ensure
|
130
|
+
`git checkout -q #{current_branch}`
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
task :prepare do
|
135
|
+
versions = `git tag -l`.split("\n").grep(/^v/).sort
|
136
|
+
latest_version = versions.last
|
137
|
+
|
138
|
+
File.open("doc/.htaccess", "w") do |file|
|
139
|
+
file.puts "RedirectMatch 302 ^/?$ /#{latest_version}"
|
140
|
+
end
|
141
|
+
|
142
|
+
File.open("doc/robots.txt", "w") do |file|
|
143
|
+
file.puts "User-Agent: *"
|
144
|
+
|
145
|
+
(versions - [latest_version]).each do |version|
|
146
|
+
file.puts "Disallow: /#{version}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
google_analytics = <<-EOS
|
151
|
+
<script type="text/javascript">
|
152
|
+
|
153
|
+
var _gaq = _gaq || [];
|
154
|
+
_gaq.push(['_setAccount', 'UA-11356145-2']);
|
155
|
+
_gaq.push(['_trackPageview']);
|
156
|
+
|
157
|
+
(function() {
|
158
|
+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
159
|
+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
160
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
161
|
+
})();
|
162
|
+
|
163
|
+
</script>
|
164
|
+
EOS
|
165
|
+
|
166
|
+
Dir["doc/**/*.html"].each do |path|
|
167
|
+
lines = IO.readlines(path)
|
168
|
+
|
169
|
+
File.open(path, "w") do |file|
|
170
|
+
lines.each do |line|
|
171
|
+
if line.include?("</head>")
|
172
|
+
file.write(google_analytics)
|
173
|
+
end
|
174
|
+
|
175
|
+
file.write(line)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
task :deploy do
|
182
|
+
system "rsync --del -avz doc/ redis-rb.keyvalue.org:deploys/redis-rb.keyvalue.org/"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
namespace :commands do
|
187
|
+
def redis_commands
|
188
|
+
$redis_commands ||= doc.keys.map do |key|
|
189
|
+
key.split(" ").first.downcase
|
190
|
+
end.uniq
|
191
|
+
end
|
192
|
+
|
193
|
+
def doc
|
194
|
+
$doc ||= begin
|
195
|
+
require "open-uri"
|
196
|
+
require "json"
|
197
|
+
|
198
|
+
JSON.parse(open("https://github.com/antirez/redis-doc/raw/master/commands.json").read)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def document(file)
|
203
|
+
source = File.read(file)
|
204
|
+
|
205
|
+
doc.each do |name, command|
|
206
|
+
source.sub!(/(?:^ *# .*\n)*(^ *#\n(^ *# .+?\n)*)*^( *)def #{name.downcase}(\(|$)/) do
|
207
|
+
extra_comments, indent, extra_args = $1, $3, $4
|
208
|
+
comment = "#{indent}# #{command["summary"].strip}."
|
209
|
+
|
210
|
+
IO.popen("par p#{2 + indent.size} 80", "r+") do |io|
|
211
|
+
io.puts comment
|
212
|
+
io.close_write
|
213
|
+
comment = io.read
|
214
|
+
end
|
215
|
+
|
216
|
+
"#{comment}#{extra_comments}#{indent}def #{name.downcase}#{extra_args}"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
File.open(file, "w") { |f| f.write(source) }
|
221
|
+
end
|
222
|
+
|
223
|
+
task :doc do
|
224
|
+
document "lib/redis.rb"
|
225
|
+
document "lib/redis/distributed.rb"
|
226
|
+
end
|
227
|
+
|
228
|
+
task :verify do
|
229
|
+
require "redis"
|
230
|
+
require "stringio"
|
231
|
+
|
232
|
+
require "./test/helper"
|
233
|
+
|
234
|
+
OPTIONS[:logger] = Logger.new("./tmp/log")
|
235
|
+
|
236
|
+
Rake::Task["test:ruby"].invoke
|
237
|
+
|
238
|
+
redis = Redis.new
|
239
|
+
|
240
|
+
report = ["Command", "\033[0mDefined?\033[0m", "\033[0mTested?\033[0m"]
|
241
|
+
|
242
|
+
yes, no = "\033[1;32mYes\033[0m", "\033[1;31mNo\033[0m"
|
243
|
+
|
244
|
+
log = File.read("./tmp/log")
|
245
|
+
|
246
|
+
redis_commands.sort.each do |name, _|
|
247
|
+
defined, tested = redis.respond_to?(name), log[">> #{name.upcase}"]
|
248
|
+
|
249
|
+
next if defined && tested
|
250
|
+
|
251
|
+
report << name
|
252
|
+
report << (defined ? yes : no)
|
253
|
+
report << (tested ? yes : no)
|
254
|
+
end
|
255
|
+
|
256
|
+
IO.popen("rs 0 3", "w") do |io|
|
257
|
+
io.puts report.join("\n")
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|