yam-redis-with-retries 2.2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +53 -0
- data/LICENSE +20 -0
- data/README.md +208 -0
- data/Rakefile +277 -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.rb +1166 -0
- data/lib/redis/client.rb +265 -0
- data/lib/redis/compat.rb +21 -0
- data/lib/redis/connection.rb +9 -0
- data/lib/redis/connection/command_helper.rb +45 -0
- data/lib/redis/connection/hiredis.rb +49 -0
- data/lib/redis/connection/registry.rb +12 -0
- data/lib/redis/connection/ruby.rb +135 -0
- data/lib/redis/connection/synchrony.rb +129 -0
- data/lib/redis/distributed.rb +694 -0
- data/lib/redis/hash_ring.rb +131 -0
- data/lib/redis/pipeline.rb +34 -0
- data/lib/redis/retry.rb +128 -0
- data/lib/redis/subscribe.rb +94 -0
- data/lib/redis/version.rb +3 -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 +78 -0
- data/test/commands_on_sorted_sets_test.rb +109 -0
- data/test/commands_on_strings_test.rb +80 -0
- data/test/commands_on_value_types_test.rb +88 -0
- data/test/connection_handling_test.rb +88 -0
- data/test/distributed_blocking_commands_test.rb +53 -0
- data/test/distributed_commands_on_hashes_test.rb +12 -0
- data/test/distributed_commands_on_lists_test.rb +24 -0
- data/test/distributed_commands_on_sets_test.rb +85 -0
- data/test/distributed_commands_on_strings_test.rb +50 -0
- data/test/distributed_commands_on_value_types_test.rb +73 -0
- data/test/distributed_commands_requiring_clustering_test.rb +148 -0
- data/test/distributed_connection_handling_test.rb +25 -0
- data/test/distributed_internals_test.rb +27 -0
- data/test/distributed_key_tags_test.rb +53 -0
- data/test/distributed_persistence_control_commands_test.rb +24 -0
- data/test/distributed_publish_subscribe_test.rb +101 -0
- data/test/distributed_remote_server_control_commands_test.rb +43 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +59 -0
- data/test/distributed_transactions_test.rb +34 -0
- data/test/encoding_test.rb +16 -0
- data/test/error_replies_test.rb +53 -0
- data/test/helper.rb +145 -0
- data/test/internals_test.rb +163 -0
- data/test/lint/hashes.rb +126 -0
- data/test/lint/internals.rb +37 -0
- data/test/lint/lists.rb +93 -0
- data/test/lint/sets.rb +66 -0
- data/test/lint/sorted_sets.rb +167 -0
- data/test/lint/strings.rb +137 -0
- data/test/lint/value_types.rb +84 -0
- data/test/persistence_control_commands_test.rb +22 -0
- data/test/pipelining_commands_test.rb +123 -0
- data/test/publish_subscribe_test.rb +158 -0
- data/test/redis_mock.rb +80 -0
- data/test/remote_server_control_commands_test.rb +82 -0
- data/test/retry_test.rb +225 -0
- data/test/sorting_test.rb +44 -0
- data/test/synchrony_driver.rb +57 -0
- data/test/test.conf +8 -0
- data/test/thread_safety_test.rb +30 -0
- data/test/transactions_test.rb +100 -0
- data/test/unknown_commands_test.rb +14 -0
- data/test/url_param_test.rb +60 -0
- metadata +215 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# 2.2.3 (unreleased)
|
2
|
+
|
3
|
+
# 2.2.2
|
4
|
+
|
5
|
+
* Added method `Redis::Distributed#hsetnx`.
|
6
|
+
|
7
|
+
# 2.2.1
|
8
|
+
|
9
|
+
* Internal API: Client#call and family are now called with a single array
|
10
|
+
argument, since splatting a large number of arguments (100K+) results in a
|
11
|
+
stack overflow on 1.9.2.
|
12
|
+
|
13
|
+
* The `INFO` command can optionally take a subcommand. When the subcommand is
|
14
|
+
`COMMANDSTATS`, the client will properly format the returned statistics per
|
15
|
+
command. Subcommands for `INFO` are available since Redis v2.3.0 (unstable).
|
16
|
+
|
17
|
+
* Change `IO#syswrite` back to the buffered `IO#write` since some Rubies do
|
18
|
+
short writes for large (1MB+) buffers and some don't (see issue #108).
|
19
|
+
|
20
|
+
# 2.2.0
|
21
|
+
|
22
|
+
* Added method `Redis#without_reconnect` that ensures the client will not try
|
23
|
+
to reconnect when running the code inside the specified block.
|
24
|
+
|
25
|
+
* Thread-safe by default. Thread safety can be explicitly disabled by passing
|
26
|
+
`:thread_safe => false` as argument.
|
27
|
+
|
28
|
+
* Commands called inside a MULTI/EXEC no longer raise error replies, since a
|
29
|
+
successful EXEC means the commands inside the block were executed.
|
30
|
+
|
31
|
+
* MULTI/EXEC blocks are pipelined.
|
32
|
+
|
33
|
+
* Don't disconnect on error replies.
|
34
|
+
|
35
|
+
* Use `IO#syswrite` instead of `IO#write` because write buffering is not
|
36
|
+
necessary.
|
37
|
+
|
38
|
+
* Connect to a unix socket by passing the `:path` option as argument.
|
39
|
+
|
40
|
+
* The timeout value is coerced into a float, allowing sub-second timeouts.
|
41
|
+
|
42
|
+
* Accept both `:with_scores` _and_ `:withscores` as argument to sorted set
|
43
|
+
commands.
|
44
|
+
|
45
|
+
* Use [hiredis](https://github.com/pietern/hiredis-rb) (v0.3 or higher) by
|
46
|
+
requiring "redis/connection/hiredis".
|
47
|
+
|
48
|
+
* Use [em-synchrony](https://github.com/igrigorik/em-synchrony) by requiring
|
49
|
+
"redis/connection/synchrony".
|
50
|
+
|
51
|
+
# 2.1.1
|
52
|
+
|
53
|
+
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,208 @@
|
|
1
|
+
# redis-rb
|
2
|
+
|
3
|
+
A Ruby client library for the [Redis](http://redis.io) key-value store.
|
4
|
+
|
5
|
+
## A note about versions
|
6
|
+
|
7
|
+
Versions *1.0.x* target all versions of Redis. You have to use this one if you are using Redis < 1.2.
|
8
|
+
|
9
|
+
Version *2.0* is a big refactoring of the previous version and makes little effort to be
|
10
|
+
backwards-compatible when it shouldn't. It does not support Redis' original protocol, favoring the
|
11
|
+
new, binary-safe one. You should be using this version if you're running Redis 1.2+.
|
12
|
+
|
13
|
+
## Information about Redis
|
14
|
+
|
15
|
+
Redis is a key-value store with some interesting features:
|
16
|
+
|
17
|
+
1. It's fast.
|
18
|
+
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.
|
19
|
+
|
20
|
+
See [the Redis homepage](http://redis.io) for more information.
|
21
|
+
|
22
|
+
## Getting started
|
23
|
+
|
24
|
+
You can connect to Redis by instantiating the `Redis` class:
|
25
|
+
|
26
|
+
require "redis"
|
27
|
+
|
28
|
+
redis = Redis.new
|
29
|
+
|
30
|
+
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:
|
31
|
+
|
32
|
+
redis = Redis.new(:host => "10.0.1.1", :port => 6380)
|
33
|
+
|
34
|
+
To connect to Redis listening on a unix socket, try:
|
35
|
+
|
36
|
+
redis = Redis.new(:path => "/tmp/redis.sock")
|
37
|
+
|
38
|
+
Once connected, you can start running commands against Redis:
|
39
|
+
|
40
|
+
>> redis.set "foo", "bar"
|
41
|
+
=> "OK"
|
42
|
+
|
43
|
+
>> redis.get "foo"
|
44
|
+
=> "bar"
|
45
|
+
|
46
|
+
>> redis.sadd "users", "albert"
|
47
|
+
=> true
|
48
|
+
|
49
|
+
>> redis.sadd "users", "bernard"
|
50
|
+
=> true
|
51
|
+
|
52
|
+
>> redis.sadd "users", "charles"
|
53
|
+
=> true
|
54
|
+
|
55
|
+
How many users?
|
56
|
+
|
57
|
+
>> redis.scard "users"
|
58
|
+
=> 3
|
59
|
+
|
60
|
+
Is `albert` a user?
|
61
|
+
|
62
|
+
>> redis.sismember "users", "albert"
|
63
|
+
=> true
|
64
|
+
|
65
|
+
Is `isabel` a user?
|
66
|
+
|
67
|
+
>> redis.sismember "users", "isabel"
|
68
|
+
=> false
|
69
|
+
|
70
|
+
Handle groups:
|
71
|
+
|
72
|
+
>> redis.sadd "admins", "albert"
|
73
|
+
=> true
|
74
|
+
|
75
|
+
>> redis.sadd "admins", "isabel"
|
76
|
+
=> true
|
77
|
+
|
78
|
+
Users who are also admins:
|
79
|
+
|
80
|
+
>> redis.sinter "users", "admins"
|
81
|
+
=> ["albert"]
|
82
|
+
|
83
|
+
Users who are not admins:
|
84
|
+
|
85
|
+
>> redis.sdiff "users", "admins"
|
86
|
+
=> ["bernard", "charles"]
|
87
|
+
|
88
|
+
Admins who are not users:
|
89
|
+
|
90
|
+
>> redis.sdiff "admins", "users"
|
91
|
+
=> ["isabel"]
|
92
|
+
|
93
|
+
All users and admins:
|
94
|
+
|
95
|
+
>> redis.sunion "admins", "users"
|
96
|
+
=> ["albert", "bernard", "charles", "isabel"]
|
97
|
+
|
98
|
+
|
99
|
+
## Storing objects
|
100
|
+
|
101
|
+
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:
|
102
|
+
|
103
|
+
>> redis.set "foo", [1, 2, 3].to_json
|
104
|
+
=> OK
|
105
|
+
|
106
|
+
>> JSON.parse(redis.get("foo"))
|
107
|
+
=> [1, 2, 3]
|
108
|
+
|
109
|
+
## Executing multiple commands atomically
|
110
|
+
|
111
|
+
You can use `MULTI/EXEC` to run arbitrary commands in an atomic fashion:
|
112
|
+
|
113
|
+
redis.multi do
|
114
|
+
redis.set "foo", "bar"
|
115
|
+
redis.incr "baz"
|
116
|
+
end
|
117
|
+
|
118
|
+
## Multithreaded Operation
|
119
|
+
|
120
|
+
Starting with redis-rb 2.2.0, the client is thread-safe by default. To use
|
121
|
+
earlier versions safely in a multithreaded environment, be sure to initialize
|
122
|
+
the client with `:thread_safe => true`. Thread-safety can be explicitly
|
123
|
+
disabled for versions 2.2 and up by initializing the client with `:thread_safe
|
124
|
+
=> false`.
|
125
|
+
|
126
|
+
See the tests and benchmarks for examples.
|
127
|
+
|
128
|
+
## Alternate drivers
|
129
|
+
|
130
|
+
Non-default connection drivers are only used when they are explicitly required.
|
131
|
+
By default, redis-rb uses Ruby's socket library to talk with Redis.
|
132
|
+
|
133
|
+
### hiredis
|
134
|
+
|
135
|
+
Using redis-rb with hiredis-rb (v0.3 or higher) as backend is done by requiring
|
136
|
+
`redis/connection/hiredis` before requiring `redis`. This will make redis-rb
|
137
|
+
pick up hiredis as default driver automatically. This driver optimizes for
|
138
|
+
speed, at the cost of portability. Since hiredis is a C extension, JRuby is not
|
139
|
+
supported (by default). Use hiredis when you have large array replies (think
|
140
|
+
`LRANGE`, `SMEMBERS`, `ZRANGE`, etc.) and/or large pipelines of commands.
|
141
|
+
|
142
|
+
Using redis-rb with hiredis from a Gemfile:
|
143
|
+
|
144
|
+
gem "hiredis", "~> 0.3.1"
|
145
|
+
gem "redis", "~> 2.2.0", :require => ["redis/connection/hiredis", "redis"]
|
146
|
+
|
147
|
+
### synchrony
|
148
|
+
|
149
|
+
This driver adds support for
|
150
|
+
[em-synchrony](https://github.com/igrigorik/em-synchrony). Using the synchrony
|
151
|
+
backend from redis-rb is done by requiring `redis/connection/synchrony` before
|
152
|
+
requiring `redis`. This driver makes redis-rb work with EventMachine's
|
153
|
+
asynchronous I/O, while not changing the exposed API. The hiredis gem needs to
|
154
|
+
be available as well, because the synchrony driver uses hiredis for parsing the
|
155
|
+
Redis protocol.
|
156
|
+
|
157
|
+
Using redis-rb with synchrony from a Gemfile:
|
158
|
+
|
159
|
+
gem "hiredis", "~> 0.3.1"
|
160
|
+
gem "em-synchrony"
|
161
|
+
gem "redis", "~> 2.2.0", :require => ["redis/connection/synchrony", "redis"]
|
162
|
+
|
163
|
+
## Testing
|
164
|
+
|
165
|
+
This library (v2.2) is tested against the following interpreters:
|
166
|
+
|
167
|
+
* MRI 1.8.7 (drivers: Ruby, hiredis)
|
168
|
+
* MRI 1.9.2 (drivers: Ruby, hiredis, em-synchrony)
|
169
|
+
* JRuby 1.6 (drivers: Ruby)
|
170
|
+
* Rubinius 1.2 (drivers: Ruby, hiredis)
|
171
|
+
|
172
|
+
## Known issues
|
173
|
+
|
174
|
+
* Ruby 1.9 doesn't raise on socket timeouts in `IO#read` but rather retries the
|
175
|
+
read operation. This means socket timeouts don't work on 1.9 when using the
|
176
|
+
pure Ruby I/O code. Use hiredis when you want use socket timeouts on 1.9.
|
177
|
+
|
178
|
+
* Ruby 1.8 *does* raise on socket timeouts in `IO#read`, but prints a warning
|
179
|
+
that using `IO#read` for non blocking reads is obsolete. This is wrong, since
|
180
|
+
the read is in fact blocking, but `EAGAIN` (which is returned on socket
|
181
|
+
timeouts) is interpreted as if the read was non blocking. Use hiredis to
|
182
|
+
prevent seeing this warning.
|
183
|
+
|
184
|
+
## More info
|
185
|
+
|
186
|
+
Check the [Redis Command Reference](http://redis.io/commands) or check the tests to find out how to use this client.
|
187
|
+
|
188
|
+
## Contributors
|
189
|
+
|
190
|
+
(ordered chronologically with more than 5 commits, see `git shortlog -sn` for
|
191
|
+
all contributors)
|
192
|
+
|
193
|
+
* Ezra Zygmuntowicz
|
194
|
+
* Taylor Weibley
|
195
|
+
* Matthew Clark
|
196
|
+
* Brian McKinney
|
197
|
+
* Luca Guidi
|
198
|
+
* Salvatore Sanfillipo
|
199
|
+
* Chris Wanstrath
|
200
|
+
* Damian Janowski
|
201
|
+
* Michel Martens
|
202
|
+
* Nick Quaranto
|
203
|
+
* Pieter Noordhuis
|
204
|
+
* Ilya Grigorik
|
205
|
+
|
206
|
+
## Contributing
|
207
|
+
|
208
|
+
[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,277 @@
|
|
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
|
+
def isolated(&block)
|
39
|
+
pid = fork { yield }
|
40
|
+
Process.wait(pid)
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Run the test suite"
|
44
|
+
task :test => ["test:ruby", "test:hiredis", "test:synchrony"]
|
45
|
+
|
46
|
+
namespace :test do
|
47
|
+
|
48
|
+
desc "Run the retry tests"
|
49
|
+
task :retry do
|
50
|
+
require "cutest"
|
51
|
+
isolated do
|
52
|
+
Cutest.run(Dir["./test/**/retry_test.rb"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Run tests against the Ruby driver"
|
57
|
+
task :ruby do
|
58
|
+
require "cutest"
|
59
|
+
|
60
|
+
isolated do
|
61
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Run tests against the hiredis driver"
|
66
|
+
task :hiredis do
|
67
|
+
require "cutest"
|
68
|
+
|
69
|
+
isolated do
|
70
|
+
begin
|
71
|
+
require "redis/connection/hiredis"
|
72
|
+
|
73
|
+
puts
|
74
|
+
puts "Running tests against hiredis v#{Hiredis::VERSION}"
|
75
|
+
|
76
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
77
|
+
rescue LoadError
|
78
|
+
puts "Skipping tests against hiredis"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "Run tests against the em-synchrony driver"
|
84
|
+
task :synchrony do
|
85
|
+
require "cutest"
|
86
|
+
|
87
|
+
# Synchrony needs 1.9
|
88
|
+
next if RUBY_VERSION < "1.9"
|
89
|
+
|
90
|
+
isolated do
|
91
|
+
begin
|
92
|
+
require "redis/connection/synchrony"
|
93
|
+
|
94
|
+
puts
|
95
|
+
puts "Running tests against em-synchrony"
|
96
|
+
|
97
|
+
threaded_tests = ['./test/thread_safety_test.rb']
|
98
|
+
Cutest.run(Dir['./test/**/*_test.rb'] - threaded_tests)
|
99
|
+
rescue LoadError
|
100
|
+
puts "Skipping tests against em-synchrony"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
task :doc => ["doc:generate", "doc:prepare"]
|
107
|
+
|
108
|
+
namespace :doc do
|
109
|
+
task :generate do
|
110
|
+
require "shellwords"
|
111
|
+
|
112
|
+
`rm -rf doc`
|
113
|
+
|
114
|
+
current_branch = `git branch`[/^\* (.*)$/, 1]
|
115
|
+
|
116
|
+
begin
|
117
|
+
tags = `git tag -l`.split("\n").sort.reverse
|
118
|
+
|
119
|
+
tags.each do |tag|
|
120
|
+
`git checkout -q #{tag} 2>/dev/null`
|
121
|
+
|
122
|
+
unless $?.success?
|
123
|
+
$stderr.puts "Need a clean working copy. Please git-stash away."
|
124
|
+
exit 1
|
125
|
+
end
|
126
|
+
|
127
|
+
puts tag
|
128
|
+
|
129
|
+
`mkdir -p doc/#{tag}`
|
130
|
+
|
131
|
+
files = `git ls-tree -r HEAD lib`.split("\n").map do |line|
|
132
|
+
line[/\t(.*)$/, 1]
|
133
|
+
end
|
134
|
+
|
135
|
+
opts = [
|
136
|
+
"--title", "A Ruby client for Redis",
|
137
|
+
"--output", "doc/#{tag}",
|
138
|
+
"--no-cache",
|
139
|
+
"--no-save",
|
140
|
+
"-q",
|
141
|
+
*files
|
142
|
+
]
|
143
|
+
|
144
|
+
`yardoc #{Shellwords.shelljoin opts}`
|
145
|
+
end
|
146
|
+
ensure
|
147
|
+
`git checkout -q #{current_branch}`
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
task :prepare do
|
152
|
+
versions = `git tag -l`.split("\n").grep(/^v/).sort
|
153
|
+
latest_version = versions.last
|
154
|
+
|
155
|
+
File.open("doc/.htaccess", "w") do |file|
|
156
|
+
file.puts "RedirectMatch 302 ^/?$ /#{latest_version}"
|
157
|
+
end
|
158
|
+
|
159
|
+
File.open("doc/robots.txt", "w") do |file|
|
160
|
+
file.puts "User-Agent: *"
|
161
|
+
|
162
|
+
(versions - [latest_version]).each do |version|
|
163
|
+
file.puts "Disallow: /#{version}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
google_analytics = <<-EOS
|
168
|
+
<script type="text/javascript">
|
169
|
+
|
170
|
+
var _gaq = _gaq || [];
|
171
|
+
_gaq.push(['_setAccount', 'UA-11356145-2']);
|
172
|
+
_gaq.push(['_trackPageview']);
|
173
|
+
|
174
|
+
(function() {
|
175
|
+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
176
|
+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
177
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
178
|
+
})();
|
179
|
+
|
180
|
+
</script>
|
181
|
+
EOS
|
182
|
+
|
183
|
+
Dir["doc/**/*.html"].each do |path|
|
184
|
+
lines = IO.readlines(path)
|
185
|
+
|
186
|
+
File.open(path, "w") do |file|
|
187
|
+
lines.each do |line|
|
188
|
+
if line.include?("</head>")
|
189
|
+
file.write(google_analytics)
|
190
|
+
end
|
191
|
+
|
192
|
+
file.write(line)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
task :deploy do
|
199
|
+
system "rsync --del -avz doc/ redis-rb.keyvalue.org:deploys/redis-rb.keyvalue.org/"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
namespace :commands do
|
204
|
+
def redis_commands
|
205
|
+
$redis_commands ||= doc.keys.map do |key|
|
206
|
+
key.split(" ").first.downcase
|
207
|
+
end.uniq
|
208
|
+
end
|
209
|
+
|
210
|
+
def doc
|
211
|
+
$doc ||= begin
|
212
|
+
require "open-uri"
|
213
|
+
require "json"
|
214
|
+
|
215
|
+
JSON.parse(open("https://github.com/antirez/redis-doc/raw/master/commands.json").read)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def document(file)
|
220
|
+
source = File.read(file)
|
221
|
+
|
222
|
+
doc.each do |name, command|
|
223
|
+
source.sub!(/(?:^ *# .*\n)*(^ *#\n(^ *# .+?\n)*)*^( *)def #{name.downcase}(\(|$)/) do
|
224
|
+
extra_comments, indent, extra_args = $1, $3, $4
|
225
|
+
comment = "#{indent}# #{command["summary"].strip}."
|
226
|
+
|
227
|
+
IO.popen("par p#{2 + indent.size} 80", "r+") do |io|
|
228
|
+
io.puts comment
|
229
|
+
io.close_write
|
230
|
+
comment = io.read
|
231
|
+
end
|
232
|
+
|
233
|
+
"#{comment}#{extra_comments}#{indent}def #{name.downcase}#{extra_args}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
File.open(file, "w") { |f| f.write(source) }
|
238
|
+
end
|
239
|
+
|
240
|
+
task :doc do
|
241
|
+
document "lib/redis.rb"
|
242
|
+
document "lib/redis/distributed.rb"
|
243
|
+
end
|
244
|
+
|
245
|
+
task :verify do
|
246
|
+
require "redis"
|
247
|
+
require "stringio"
|
248
|
+
|
249
|
+
require "./test/helper"
|
250
|
+
|
251
|
+
OPTIONS[:logger] = Logger.new("./tmp/log")
|
252
|
+
|
253
|
+
Rake::Task["test:ruby"].invoke
|
254
|
+
|
255
|
+
redis = Redis.new
|
256
|
+
|
257
|
+
report = ["Command", "\033[0mDefined?\033[0m", "\033[0mTested?\033[0m"]
|
258
|
+
|
259
|
+
yes, no = "\033[1;32mYes\033[0m", "\033[1;31mNo\033[0m"
|
260
|
+
|
261
|
+
log = File.read("./tmp/log")
|
262
|
+
|
263
|
+
redis_commands.sort.each do |name, _|
|
264
|
+
defined, tested = redis.respond_to?(name), log[">> #{name.upcase}"]
|
265
|
+
|
266
|
+
next if defined && tested
|
267
|
+
|
268
|
+
report << name
|
269
|
+
report << (defined ? yes : no)
|
270
|
+
report << (tested ? yes : no)
|
271
|
+
end
|
272
|
+
|
273
|
+
IO.popen("rs 0 3", "w") do |io|
|
274
|
+
io.puts report.join("\n")
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|