gorsuch-redis 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/.gitignore +10 -0
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +113 -0
  4. data/LICENSE +20 -0
  5. data/README.md +214 -0
  6. data/Rakefile +260 -0
  7. data/TODO.md +4 -0
  8. data/benchmarking/logging.rb +62 -0
  9. data/benchmarking/pipeline.rb +51 -0
  10. data/benchmarking/speed.rb +21 -0
  11. data/benchmarking/suite.rb +24 -0
  12. data/benchmarking/thread_safety.rb +38 -0
  13. data/benchmarking/worker.rb +71 -0
  14. data/examples/basic.rb +15 -0
  15. data/examples/dist_redis.rb +43 -0
  16. data/examples/incr-decr.rb +17 -0
  17. data/examples/list.rb +26 -0
  18. data/examples/pubsub.rb +31 -0
  19. data/examples/sets.rb +36 -0
  20. data/examples/unicorn/config.ru +3 -0
  21. data/examples/unicorn/unicorn.rb +20 -0
  22. data/lib/redis/client.rb +303 -0
  23. data/lib/redis/connection/command_helper.rb +44 -0
  24. data/lib/redis/connection/hiredis.rb +52 -0
  25. data/lib/redis/connection/registry.rb +12 -0
  26. data/lib/redis/connection/ruby.rb +136 -0
  27. data/lib/redis/connection/synchrony.rb +131 -0
  28. data/lib/redis/connection.rb +9 -0
  29. data/lib/redis/distributed.rb +696 -0
  30. data/lib/redis/errors.rb +38 -0
  31. data/lib/redis/hash_ring.rb +131 -0
  32. data/lib/redis/pipeline.rb +106 -0
  33. data/lib/redis/subscribe.rb +79 -0
  34. data/lib/redis/version.rb +3 -0
  35. data/lib/redis.rb +1724 -0
  36. data/redis.gemspec +43 -0
  37. data/test/command_map_test.rb +29 -0
  38. data/test/commands_on_hashes_test.rb +20 -0
  39. data/test/commands_on_lists_test.rb +60 -0
  40. data/test/commands_on_sets_test.rb +76 -0
  41. data/test/commands_on_sorted_sets_test.rb +108 -0
  42. data/test/commands_on_strings_test.rb +80 -0
  43. data/test/commands_on_value_types_test.rb +87 -0
  44. data/test/connection_handling_test.rb +204 -0
  45. data/test/db/.gitignore +1 -0
  46. data/test/distributed_blocking_commands_test.rb +53 -0
  47. data/test/distributed_commands_on_hashes_test.rb +11 -0
  48. data/test/distributed_commands_on_lists_test.rb +23 -0
  49. data/test/distributed_commands_on_sets_test.rb +84 -0
  50. data/test/distributed_commands_on_sorted_sets_test.rb +19 -0
  51. data/test/distributed_commands_on_strings_test.rb +49 -0
  52. data/test/distributed_commands_on_value_types_test.rb +72 -0
  53. data/test/distributed_commands_requiring_clustering_test.rb +148 -0
  54. data/test/distributed_connection_handling_test.rb +24 -0
  55. data/test/distributed_internals_test.rb +27 -0
  56. data/test/distributed_key_tags_test.rb +52 -0
  57. data/test/distributed_persistence_control_commands_test.rb +23 -0
  58. data/test/distributed_publish_subscribe_test.rb +100 -0
  59. data/test/distributed_remote_server_control_commands_test.rb +42 -0
  60. data/test/distributed_sorting_test.rb +21 -0
  61. data/test/distributed_test.rb +59 -0
  62. data/test/distributed_transactions_test.rb +33 -0
  63. data/test/encoding_test.rb +15 -0
  64. data/test/error_replies_test.rb +53 -0
  65. data/test/helper.rb +155 -0
  66. data/test/helper_test.rb +8 -0
  67. data/test/internals_test.rb +152 -0
  68. data/test/lint/hashes.rb +140 -0
  69. data/test/lint/internals.rb +36 -0
  70. data/test/lint/lists.rb +107 -0
  71. data/test/lint/sets.rb +90 -0
  72. data/test/lint/sorted_sets.rb +196 -0
  73. data/test/lint/strings.rb +133 -0
  74. data/test/lint/value_types.rb +81 -0
  75. data/test/persistence_control_commands_test.rb +21 -0
  76. data/test/pipelining_commands_test.rb +186 -0
  77. data/test/publish_subscribe_test.rb +158 -0
  78. data/test/redis_mock.rb +89 -0
  79. data/test/remote_server_control_commands_test.rb +88 -0
  80. data/test/sorting_test.rb +43 -0
  81. data/test/synchrony_driver.rb +57 -0
  82. data/test/test.conf +9 -0
  83. data/test/thread_safety_test.rb +30 -0
  84. data/test/transactions_test.rb +173 -0
  85. data/test/unknown_commands_test.rb +13 -0
  86. data/test/url_param_test.rb +59 -0
  87. metadata +236 -0
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ nohup.out
2
+ redis/*
3
+ rdsrv
4
+ pkg/*
5
+ coverage/*
6
+ .idea
7
+ *.rdb
8
+ *.swp
9
+ .yardoc
10
+ doc/
data/.yardopts ADDED
@@ -0,0 +1,3 @@
1
+ --exclude redis/connection
2
+ --exclude redis/compat
3
+ --markup markdown
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