]> git.saurik.com Git - redis.git/blob - client-libraries/ruby_2/rubyredis.rb
Automagically reconnection of RubyRedis
[redis.git] / client-libraries / ruby_2 / rubyredis.rb
1 # RubyRedis is an alternative implementatin of Ruby client library written
2 # by Salvatore Sanfilippo.
3 #
4 # The aim of this library is to create an alternative client library that is
5 # much simpler and does not implement every command explicitly but uses
6 # method_missing instead.
7
8 require 'socket'
9
10 class RedisClient
11 BulkCommands = {
12 "set"=>true, "setnx"=>true, "rpush"=>true, "lpush"=>true, "lset"=>true,
13 "lrem"=>true, "sadd"=>true, "srem"=>true, "sismember"=>true,
14 "echo"=>true, "getset"=>true, "smove"=>true
15 }
16
17 def initialize(opts={})
18 opts = {:host => 'localhost', :port => '6379', :db => 0}.merge(opts)
19 @host = opts[:host]
20 @port = opts[:port]
21 @db = opts[:db]
22 connect_to_server
23 end
24
25 def to_s
26 "Redis Client connected to #{@host}:#{@port} against DB #{@db}"
27 end
28
29 def connect_to_server
30 @sock = TCPSocket.new(@host, @port, 0)
31 call_command(["select",@db]) if @db != 0
32 end
33
34 def method_missing(*argv)
35 call_command(argv)
36 end
37
38 def call_command(argv)
39 # this wrapper to raw_call_command handle reconnection on socket
40 # error. We try to reconnect just one time, otherwise let the error
41 # araise.
42 begin
43 raw_call_command(argv)
44 rescue Errno::ECONNRESET
45 @sock.close
46 connect_to_server
47 raw_call_command(argv)
48 end
49 end
50
51 def raw_call_command(argv)
52 bulk = nil
53 argv[0] = argv[0].to_s.downcase
54 if BulkCommands[argv[0]]
55 bulk = argv[-1]
56 argv[-1] = bulk.length
57 end
58 @sock.write(argv.join(" ")+"\r\n")
59 @sock.write(bulk+"\r\n") if bulk
60 read_reply
61 end
62
63 def select(*args)
64 raise "SELECT not allowed, use the :db option when creating the object"
65 end
66
67 def [](key)
68 get(key)
69 end
70
71 def []=(key,value)
72 set(key,value)
73 end
74
75 def read_reply
76 line = @sock.gets
77 raise Errno::ECONNRESET,"Connection lost" if !line
78 case line[0..0]
79 when "-"
80 raise line.strip
81 when "+"
82 line[1..-1].strip
83 when ":"
84 line[1..-1].to_i
85 when "$"
86 bulklen = line[1..-1].to_i
87 return nil if bulklen == -1
88 data = @sock.read(bulklen)
89 @sock.read(2) # CRLF
90 data
91 when "*"
92 objects = line[1..-1].to_i
93 return nil if bulklen == -1
94 res = []
95 objects.times {
96 res << read_reply
97 }
98 res
99 end
100 end
101 end