redis 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +64 -26
- data/Rakefile +6 -16
- data/lib/redis.rb +9 -8
- data/lib/redis/client.rb +202 -134
- data/lib/redis/dist_redis.rb +2 -2
- data/lib/redis/hash_ring.rb +1 -1
- data/lib/redis/pipeline.rb +1 -2
- metadata +3 -5
- data/spec/redis_spec.rb +0 -752
- data/spec/spec_helper.rb +0 -4
data/README.markdown
CHANGED
@@ -1,36 +1,74 @@
|
|
1
1
|
# redis-rb
|
2
2
|
|
3
|
-
A
|
3
|
+
A Ruby client library for the [Redis](http://code.google.com/p/redis) key-value storage system.
|
4
4
|
|
5
|
-
## Information about
|
5
|
+
## Information about Redis
|
6
6
|
|
7
|
-
Redis is a key
|
8
|
-
1. It's fast.
|
9
|
-
2. Keys are strings but values can have types of "NONE", "STRING", "LIST", or "SET". List's can be atomically push'd, pop'd, lpush'd, lpop'd and indexed. This allows you to store things like lists of comments under one key while retaining the ability to append comments without reading and putting back the whole list.
|
10
|
-
|
11
|
-
See [redis on code.google.com](http://code.google.com/p/redis/wiki/README) for more information.
|
12
|
-
|
13
|
-
See the build on [RunCodeRun](http://runcoderun.com/rsanheim/redis-rb)
|
7
|
+
Redis is a key-value store with some interesting features:
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
9
|
+
1. It's fast.
|
10
|
+
2. Keys are strings but values are typed. Currently Redis supports strings, lists, sets, sorted sets and hashes. [Atomic operations](http://code.google.com/p/redis/wiki/CommandReference) can be done on all of these types.
|
11
|
+
|
12
|
+
See [the Redis homepage](http://code.google.com/p/redis/wiki/README) for more information.
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
For all types redis-rb needs redis-server running to connect to.
|
17
|
+
|
18
|
+
### Simple Key Value Strings can be used like a large Ruby Hash (Similar to Memcached, Tokyo Cabinet)
|
19
|
+
|
20
|
+
require 'redis'
|
21
|
+
r = Redis.new
|
22
|
+
r['key_one'] = "value_one"
|
23
|
+
r['key_two'] = "value_two"
|
24
|
+
|
25
|
+
r['key_one] # => "value_one"
|
26
|
+
|
27
|
+
### Redis only stores strings. To store Objects, Array or Hashes, you must [Marshal](http://ruby-doc.org/core/classes/Marshal.html)
|
28
|
+
|
29
|
+
require 'redis'
|
30
|
+
r = Redis.new
|
31
|
+
|
32
|
+
example_hash_to_store = {:name => "Alex", :age => 21, :password => "letmein", :cool => false}
|
33
|
+
|
34
|
+
r['key_one'] = Marshal.dump(example_hash_to_store)
|
35
|
+
|
36
|
+
hash_returned_from_redis = Marshal.load(r['key_one'])
|
37
|
+
|
38
|
+
### Alternatively you can use the [Redis Commands](http://code.google.com/p/redis/wiki/CommandReference)
|
39
|
+
|
40
|
+
require 'redis'
|
41
|
+
r = Redis.new
|
42
|
+
r.set 'key_one', 'value_one'
|
43
|
+
r.get 'key_one' # => 'value_one'
|
44
|
+
|
45
|
+
# Using Redis list objects
|
46
|
+
# Push an object to the head of the list. Creates the list if it doesn't allready exsist.
|
47
|
+
|
48
|
+
blog_hash = {:title => "Redis Rules!", :body => "Ok so, like why, well like, RDBMS is like....", :created_at => Time.now.to_i}
|
49
|
+
r.lpush 'all_blogs', Marshal.dump(blog_hash)
|
50
|
+
|
51
|
+
# Get a range of strings from the all_blogs list. Similar to offset and limit in SQL (-1, means the last one)
|
52
|
+
|
53
|
+
r.lrange 'all_blogs', 0, -1
|
54
|
+
|
55
|
+
### Multiple commands at once!
|
56
|
+
|
57
|
+
require 'redis'
|
58
|
+
r = Redis.new
|
59
|
+
r.multi do
|
60
|
+
r.set 'foo', 'bar'
|
61
|
+
r.incr 'baz'
|
62
|
+
end
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
See the build on [RunCodeRun](http://runcoderun.com/rsanheim/redis-rb).
|
67
|
+
|
68
|
+
If you would like to submit patches, you'll need Redis in your development environment:
|
21
69
|
|
22
70
|
rake redis:install
|
23
71
|
|
24
|
-
2. dtach -
|
25
|
-
|
26
|
-
rake dtach:install
|
27
|
-
|
28
|
-
3. git - git is the new black.
|
29
|
-
|
30
|
-
## Setup
|
31
|
-
|
32
|
-
Use the tasks mentioned above (in Dependencies) to get your machine setup.
|
33
|
-
|
34
72
|
## Examples
|
35
73
|
|
36
|
-
Check the examples
|
74
|
+
Check the `examples/` directory. You'll need to have an instance of `redis-server` running before running the examples.
|
data/Rakefile
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/gempackagetask'
|
3
|
-
require '
|
4
|
-
require 'date'
|
5
|
-
require 'spec/rake/spectask'
|
3
|
+
require 'rake/testtask'
|
6
4
|
require 'tasks/redis.tasks'
|
7
5
|
|
8
6
|
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
@@ -10,7 +8,7 @@ require 'redis'
|
|
10
8
|
|
11
9
|
GEM = 'redis'
|
12
10
|
GEM_NAME = 'redis'
|
13
|
-
GEM_VERSION =
|
11
|
+
GEM_VERSION = Redis::VERSION
|
14
12
|
AUTHORS = ['Ezra Zygmuntowicz', 'Taylor Weibley', 'Matthew Clark', 'Brian McKinney', 'Salvatore Sanfilippo', 'Luca Guidi']
|
15
13
|
EMAIL = "ez@engineyard.com"
|
16
14
|
HOMEPAGE = "http://github.com/ezmobius/redis-rb"
|
@@ -33,12 +31,10 @@ spec = Gem::Specification.new do |s|
|
|
33
31
|
s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{lib,tasks,spec}/**/*")
|
34
32
|
end
|
35
33
|
|
36
|
-
task :default => :
|
34
|
+
task :default => :test
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
41
|
-
t.spec_opts = %w(-fs --color)
|
36
|
+
Rake::TestTask.new(:test) do |t|
|
37
|
+
t.pattern = 'test/**/*_test.rb'
|
42
38
|
end
|
43
39
|
|
44
40
|
Rake::GemPackageTask.new(spec) do |pkg|
|
@@ -51,14 +47,8 @@ task :install => [:package] do
|
|
51
47
|
end
|
52
48
|
|
53
49
|
desc "create a gemspec file"
|
54
|
-
task :
|
50
|
+
task :gemspec do
|
55
51
|
File.open("#{GEM}.gemspec", "w") do |file|
|
56
52
|
file.puts spec.to_ruby
|
57
53
|
end
|
58
54
|
end
|
59
|
-
|
60
|
-
desc "Run all examples with RCov"
|
61
|
-
Spec::Rake::SpecTask.new(:rcov) do |t|
|
62
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
63
|
-
t.rcov = true
|
64
|
-
end
|
data/lib/redis.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
|
-
|
4
|
-
VERSION = "0.
|
3
|
+
class Redis
|
4
|
+
VERSION = "1.0.0"
|
5
|
+
|
6
|
+
def self.new(*attrs)
|
7
|
+
Client.new(*attrs)
|
8
|
+
end
|
5
9
|
end
|
6
10
|
|
7
11
|
begin
|
8
12
|
if RUBY_VERSION >= '1.9'
|
9
13
|
require 'timeout'
|
10
|
-
|
14
|
+
Redis::Timer = Timeout
|
11
15
|
else
|
12
16
|
require 'system_timer'
|
13
|
-
|
17
|
+
Redis::Timer = SystemTimer
|
14
18
|
end
|
15
19
|
rescue LoadError
|
16
|
-
|
20
|
+
Redis::Timer = nil
|
17
21
|
end
|
18
22
|
|
19
23
|
require 'redis/client'
|
20
24
|
require 'redis/pipeline'
|
21
|
-
|
22
|
-
# For backwards compatibility
|
23
|
-
Redis = RedisRb::Client
|
data/lib/redis/client.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
class Redis
|
2
2
|
class Client
|
3
3
|
OK = "OK".freeze
|
4
4
|
MINUS = "-".freeze
|
@@ -28,7 +28,8 @@ module RedisRb
|
|
28
28
|
"zrevrank" => true,
|
29
29
|
"hget" => true,
|
30
30
|
"hdel" => true,
|
31
|
-
"hexists" => true
|
31
|
+
"hexists" => true,
|
32
|
+
"publish" => true
|
32
33
|
}
|
33
34
|
|
34
35
|
MULTI_BULK_COMMANDS = {
|
@@ -134,29 +135,195 @@ module RedisRb
|
|
134
135
|
@binary_keys = options[:binary_keys]
|
135
136
|
@mutex = Mutex.new if @thread_safe
|
136
137
|
@sock = nil
|
138
|
+
@pubsub = false
|
137
139
|
|
138
|
-
|
140
|
+
log(self)
|
139
141
|
end
|
140
142
|
|
141
143
|
def to_s
|
142
144
|
"Redis Client connected to #{server} against DB #{@db}"
|
143
145
|
end
|
144
146
|
|
145
|
-
def
|
146
|
-
"
|
147
|
+
def select(*args)
|
148
|
+
raise "SELECT not allowed, use the :db option when creating the object"
|
147
149
|
end
|
148
150
|
|
149
|
-
def
|
150
|
-
|
151
|
-
|
152
|
-
|
151
|
+
def [](key)
|
152
|
+
get(key)
|
153
|
+
end
|
154
|
+
|
155
|
+
def []=(key,value)
|
156
|
+
set(key, value)
|
157
|
+
end
|
158
|
+
|
159
|
+
def set(key, value, ttl = nil)
|
160
|
+
if ttl
|
161
|
+
deprecated("set with an expire", :set_with_expire, caller[0])
|
162
|
+
set_with_expire(key, value, ttl)
|
163
|
+
else
|
164
|
+
call_command([:set, key, value])
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def set_with_expire(key, value, ttl)
|
169
|
+
multi do
|
170
|
+
set(key, value)
|
171
|
+
expire(key, ttl)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def mset(*args)
|
176
|
+
if args.size == 1
|
177
|
+
deprecated("mset with a hash", :mapped_mset, caller[0])
|
178
|
+
mapped_mset(args[0])
|
179
|
+
else
|
180
|
+
call_command(args.unshift(:mset))
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def mapped_mset(hash)
|
185
|
+
mset(*hash.to_a.flatten)
|
186
|
+
end
|
187
|
+
|
188
|
+
def msetnx(*args)
|
189
|
+
if args.size == 1
|
190
|
+
deprecated("msetnx with a hash", :mapped_msetnx, caller[0])
|
191
|
+
mapped_msetnx(args[0])
|
192
|
+
else
|
193
|
+
call_command(args.unshift(:msetnx))
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def mapped_msetnx(hash)
|
198
|
+
msetnx(*hash.to_a.flatten)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Similar to memcache.rb's #get_multi, returns a hash mapping
|
202
|
+
# keys to values.
|
203
|
+
def mapped_mget(*keys)
|
204
|
+
result = {}
|
205
|
+
mget(*keys).each do |value|
|
206
|
+
key = keys.shift
|
207
|
+
result.merge!(key => value) unless value.nil?
|
208
|
+
end
|
209
|
+
result
|
210
|
+
end
|
211
|
+
|
212
|
+
def sort(key, options = {})
|
213
|
+
cmd = ["SORT"]
|
214
|
+
cmd << key
|
215
|
+
cmd << "BY #{options[:by]}" if options[:by]
|
216
|
+
cmd << "GET #{[options[:get]].flatten * ' GET '}" if options[:get]
|
217
|
+
cmd << "#{options[:order]}" if options[:order]
|
218
|
+
cmd << "LIMIT #{options[:limit].join(' ')}" if options[:limit]
|
219
|
+
cmd << "STORE #{options[:store]}" if options[:store]
|
220
|
+
call_command(cmd)
|
221
|
+
end
|
222
|
+
|
223
|
+
def incr(key, increment = nil)
|
224
|
+
call_command(increment ? ["incrby",key,increment] : ["incr",key])
|
225
|
+
end
|
226
|
+
|
227
|
+
def decr(key,decrement = nil)
|
228
|
+
call_command(decrement ? ["decrby",key,decrement] : ["decr",key])
|
229
|
+
end
|
230
|
+
|
231
|
+
# Ruby defines a now deprecated type method so we need to override it here
|
232
|
+
# since it will never hit method_missing
|
233
|
+
def type(key)
|
234
|
+
call_command(['type', key])
|
235
|
+
end
|
236
|
+
|
237
|
+
def quit
|
238
|
+
call_command(['quit'])
|
239
|
+
rescue Errno::ECONNRESET
|
240
|
+
end
|
241
|
+
|
242
|
+
def pipelined(&block)
|
243
|
+
pipeline = Pipeline.new self
|
244
|
+
yield pipeline
|
245
|
+
pipeline.execute
|
246
|
+
end
|
247
|
+
|
248
|
+
def exec
|
249
|
+
# Need to override Kernel#exec.
|
250
|
+
call_command([:exec])
|
251
|
+
end
|
252
|
+
|
253
|
+
def multi(&block)
|
254
|
+
result = call_command [:multi]
|
255
|
+
|
256
|
+
return result unless block_given?
|
257
|
+
|
258
|
+
begin
|
259
|
+
yield(self)
|
260
|
+
exec
|
261
|
+
rescue Exception => e
|
262
|
+
discard
|
263
|
+
raise e
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def subscribe(*classes)
|
268
|
+
# Sanity check, as our API is a bit tricky. You MUST call
|
269
|
+
# the top-level subscribe with a block, but you can NOT call
|
270
|
+
# the nested subscribe calls with a block, as all the messages
|
271
|
+
# are processed by the top level call.
|
272
|
+
if @pubsub == false and !block_given?
|
273
|
+
raise "You must pass a block to the top level subscribe call"
|
274
|
+
elsif @pubsub == true and block_given?
|
275
|
+
raise "Can't pass a block to nested subscribe calls"
|
276
|
+
elsif @pubsub == true
|
277
|
+
# This is a nested subscribe call without a block given.
|
278
|
+
# We just need to send the subscribe command and return asap.
|
279
|
+
call_command [:subscribe,*classes]
|
280
|
+
return true
|
281
|
+
end
|
282
|
+
@pubsub = true
|
283
|
+
call_command [:subscribe,*classes]
|
284
|
+
while true
|
285
|
+
r = read_reply
|
286
|
+
msg = {:type => r[0], :class => r[1], :data => r[2]}
|
287
|
+
yield(msg)
|
288
|
+
break if msg[:type] == "unsubscribe" and r[2] == 0
|
289
|
+
end
|
290
|
+
@pubsub = false
|
291
|
+
end
|
292
|
+
|
293
|
+
def unsubscribe(*classes)
|
294
|
+
call_command [:unsubscribe,*classes]
|
295
|
+
return true
|
296
|
+
end
|
297
|
+
|
298
|
+
protected
|
299
|
+
|
300
|
+
def call_command(argv)
|
301
|
+
log(argv.inspect, :debug)
|
302
|
+
|
303
|
+
# this wrapper to raw_call_command handle reconnection on socket
|
304
|
+
# error. We try to reconnect just one time, otherwise let the error
|
305
|
+
# araise.
|
306
|
+
connect_to_server if !@sock
|
307
|
+
|
308
|
+
begin
|
309
|
+
raw_call_command(argv.dup)
|
310
|
+
rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED
|
311
|
+
@sock.close rescue nil
|
312
|
+
@sock = nil
|
313
|
+
connect_to_server
|
314
|
+
raw_call_command(argv.dup)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def server
|
319
|
+
"#{@host}:#{@port}"
|
153
320
|
end
|
154
321
|
|
155
322
|
def connect_to(host, port, timeout=nil)
|
156
323
|
# We support connect() timeout only if system_timer is availabe
|
157
324
|
# or if we are running against Ruby >= 1.9
|
158
325
|
# Timeout reading from the socket instead will be supported anyway.
|
159
|
-
if @timeout != 0 and
|
326
|
+
if @timeout != 0 and Timer
|
160
327
|
begin
|
161
328
|
sock = TCPSocket.new(host, port)
|
162
329
|
rescue Timeout::Error
|
@@ -180,32 +347,20 @@ module RedisRb
|
|
180
347
|
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
181
348
|
rescue Exception => ex
|
182
349
|
# Solaris, for one, does not like/support socket timeouts.
|
183
|
-
|
350
|
+
log("Unable to use raw socket timeouts: #{ex.class.name}: #{ex.message}")
|
184
351
|
end
|
185
352
|
end
|
186
353
|
sock
|
187
354
|
end
|
188
355
|
|
189
|
-
def
|
190
|
-
|
356
|
+
def connect_to_server
|
357
|
+
@sock = connect_to(@host, @port, @timeout == 0 ? nil : @timeout)
|
358
|
+
call_command(["auth",@password]) if @password
|
359
|
+
call_command(["select",@db]) unless @db == 0
|
191
360
|
end
|
192
361
|
|
193
|
-
def
|
194
|
-
|
195
|
-
|
196
|
-
# this wrapper to raw_call_command handle reconnection on socket
|
197
|
-
# error. We try to reconnect just one time, otherwise let the error
|
198
|
-
# araise.
|
199
|
-
connect_to_server if !@sock
|
200
|
-
|
201
|
-
begin
|
202
|
-
raw_call_command(argv.dup)
|
203
|
-
rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED
|
204
|
-
@sock.close rescue nil
|
205
|
-
@sock = nil
|
206
|
-
connect_to_server
|
207
|
-
raw_call_command(argv.dup)
|
208
|
-
end
|
362
|
+
def method_missing(*argv)
|
363
|
+
call_command(argv)
|
209
364
|
end
|
210
365
|
|
211
366
|
def raw_call_command(argvp)
|
@@ -231,8 +386,11 @@ module RedisRb
|
|
231
386
|
command = ""
|
232
387
|
argvv.each do |argv|
|
233
388
|
bulk = nil
|
234
|
-
argv[0] = argv[0].to_s
|
235
|
-
|
389
|
+
argv[0] = argv[0].to_s
|
390
|
+
if ALIASES[argv[0]]
|
391
|
+
deprecated(argv[0], ALIASES[argv[0]], caller[4])
|
392
|
+
argv[0] = ALIASES[argv[0]]
|
393
|
+
end
|
236
394
|
raise "#{argv[0]} command is disabled" if DISABLED_COMMANDS[argv[0]]
|
237
395
|
if BULK_COMMANDS[argv[0]] and argv.length > 1
|
238
396
|
bulk = argv[-1].to_s
|
@@ -242,8 +400,13 @@ module RedisRb
|
|
242
400
|
command << "#{bulk}\r\n" if bulk
|
243
401
|
end
|
244
402
|
end
|
403
|
+
# When in Pub/Sub mode we don't read replies synchronously.
|
404
|
+
if @pubsub
|
405
|
+
@sock.write(command)
|
406
|
+
return true
|
407
|
+
end
|
408
|
+
# The normal command execution is reading and processing the reply.
|
245
409
|
results = maybe_lock { process_command(command, argvv) }
|
246
|
-
|
247
410
|
return pipeline ? results : results[0]
|
248
411
|
end
|
249
412
|
|
@@ -263,89 +426,6 @@ module RedisRb
|
|
263
426
|
end
|
264
427
|
end
|
265
428
|
|
266
|
-
def select(*args)
|
267
|
-
raise "SELECT not allowed, use the :db option when creating the object"
|
268
|
-
end
|
269
|
-
|
270
|
-
def [](key)
|
271
|
-
self.get(key)
|
272
|
-
end
|
273
|
-
|
274
|
-
def []=(key,value)
|
275
|
-
set(key,value)
|
276
|
-
end
|
277
|
-
|
278
|
-
def set(key, value, expiry=nil)
|
279
|
-
s = call_command([:set, key, value]) == OK
|
280
|
-
expire(key, expiry) if s && expiry
|
281
|
-
s
|
282
|
-
end
|
283
|
-
|
284
|
-
def mset(*args)
|
285
|
-
hsh = args.pop if Hash === args.last
|
286
|
-
if hsh
|
287
|
-
call_command(hsh.to_a.flatten.unshift(:mset))
|
288
|
-
else
|
289
|
-
call_command(args.unshift(:mset))
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def msetnx(*args)
|
294
|
-
hsh = args.pop if Hash === args.last
|
295
|
-
if hsh
|
296
|
-
call_command(hsh.to_a.flatten.unshift(:msetnx))
|
297
|
-
else
|
298
|
-
call_command(args.unshift(:msetnx))
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def sort(key, options = {})
|
303
|
-
cmd = ["SORT"]
|
304
|
-
cmd << key
|
305
|
-
cmd << "BY #{options[:by]}" if options[:by]
|
306
|
-
cmd << "GET #{[options[:get]].flatten * ' GET '}" if options[:get]
|
307
|
-
cmd << "#{options[:order]}" if options[:order]
|
308
|
-
cmd << "LIMIT #{options[:limit].join(' ')}" if options[:limit]
|
309
|
-
cmd << "STORE #{options[:store]}" if options[:store]
|
310
|
-
call_command(cmd)
|
311
|
-
end
|
312
|
-
|
313
|
-
def incr(key, increment = nil)
|
314
|
-
call_command(increment ? ["incrby",key,increment] : ["incr",key])
|
315
|
-
end
|
316
|
-
|
317
|
-
def decr(key,decrement = nil)
|
318
|
-
call_command(decrement ? ["decrby",key,decrement] : ["decr",key])
|
319
|
-
end
|
320
|
-
|
321
|
-
# Similar to memcache.rb's #get_multi, returns a hash mapping
|
322
|
-
# keys to values.
|
323
|
-
def mapped_mget(*keys)
|
324
|
-
result = {}
|
325
|
-
mget(*keys).each do |value|
|
326
|
-
key = keys.shift
|
327
|
-
result.merge!(key => value) unless value.nil?
|
328
|
-
end
|
329
|
-
result
|
330
|
-
end
|
331
|
-
|
332
|
-
# Ruby defines a now deprecated type method so we need to override it here
|
333
|
-
# since it will never hit method_missing
|
334
|
-
def type(key)
|
335
|
-
call_command(['type', key])
|
336
|
-
end
|
337
|
-
|
338
|
-
def quit
|
339
|
-
call_command(['quit'])
|
340
|
-
rescue Errno::ECONNRESET
|
341
|
-
end
|
342
|
-
|
343
|
-
def pipelined(&block)
|
344
|
-
pipeline = Pipeline.new self
|
345
|
-
yield pipeline
|
346
|
-
pipeline.execute
|
347
|
-
end
|
348
|
-
|
349
429
|
def read_reply
|
350
430
|
# We read the first byte using read() mainly because gets() is
|
351
431
|
# immune to raw socket timeouts.
|
@@ -387,28 +467,16 @@ module RedisRb
|
|
387
467
|
end
|
388
468
|
end
|
389
469
|
|
390
|
-
def
|
391
|
-
|
392
|
-
call_command([:exec])
|
470
|
+
def get_size(string)
|
471
|
+
string.respond_to?(:bytesize) ? string.bytesize : string.size
|
393
472
|
end
|
394
473
|
|
395
|
-
def
|
396
|
-
|
397
|
-
|
398
|
-
return result unless block_given?
|
399
|
-
|
400
|
-
begin
|
401
|
-
yield(self)
|
402
|
-
exec
|
403
|
-
rescue Exception => e
|
404
|
-
discard
|
405
|
-
raise e
|
406
|
-
end
|
474
|
+
def log(str, level = :info)
|
475
|
+
@logger.send(level, str.to_s) if @logger
|
407
476
|
end
|
408
477
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end
|
478
|
+
def deprecated(old, new, trace = caller[0])
|
479
|
+
$stderr.puts "\nRedis: The method #{old} is deprecated. Use #{new} instead (in #{trace})"
|
480
|
+
end
|
413
481
|
end
|
414
482
|
end
|