Module: Redis::Protocol

Included in:
Bin::RubyRedisServer
Defined in:
lib/redis/protocol.rb

Instance Method Summary collapse

Instance Method Details

#initialize(*args) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/redis/protocol.rb', line 4

def initialize *args
  @reader = Reader.new
  @multi = nil
  @deferred = nil
  @watcher = nil
  super
end

#receive_data(data) ⇒ Object

Process incoming redis protocol



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/redis/protocol.rb', line 19

def receive_data data
  return unless @reader
  @reader.feed data
  until (strings = @reader.gets) == false
    if @multi and !%w{WATCH DISCARD MULTI EXEC DEBUG}.include?(strings[0].upcase)
      @multi << strings
      send_redis :'+QUEUED'
    else
      result = __send__ "redis_#{strings[0].upcase}", *strings[1..-1]
      if Integer === result
        send_data ":#{result}\r\n"
      elsif EventMachine::Deferrable === result
        @deferred.unbind if @deferred and @deferred != result
        @deferred = result
      elsif result == :quit
        @reader = nil
        close_connection_after_writing
        break
      elsif result != :exec
        send_redis result
      end
    end
  end
rescue Exception => e
  raise e if Interrupt === e
  # This sometimes comes in handy for the TCL tests
  # @logger.warn "#{e.class}:/#{e.backtrace[0]} #{e.message}"
  # e.backtrace[1..-1].each {|bt| @logger.warn bt}
  send_data "-ERR #{e.class.name}: #{e.message}\r\n" 
end

#redis_DISCARDObject



71
72
73
74
75
# File 'lib/redis/protocol.rb', line 71

def redis_DISCARD
  redis_UNWATCH
  @multi = nil
  :'+OK'
end

#redis_EXECObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/redis/protocol.rb', line 77

def redis_EXEC
  if @watcher
    still_bound = @watcher.bound
    redis_UNWATCH
    unless still_bound
      @multi = nil
      return :'*-1' 
    end
  end
  send_data "*#{@multi.size}\r\n"
  response = []
  @multi.each do |strings|
    begin
      result = __send__ "redis_#{strings[0].upcase}", *strings[1..-1]
    rescue Exception => e
      raise e if Interrupt === e
      result = e
    end
    if EventMachine::Deferrable === result
      result.unbind
      send_redis nil
    elsif Exception === result
      send_data "-ERR #{result.class.name}: #{result.message}"
    else
      send_redis result
    end
  end
  @multi = nil
  :exec
end

#redis_MULTIObject



65
66
67
68
69
# File 'lib/redis/protocol.rb', line 65

def redis_MULTI
  raise 'MULTI nesting not allowed' if @multi
  @multi = []
  :'+OK'
end

#redis_UNWATCHObject



57
58
59
60
61
62
63
# File 'lib/redis/protocol.rb', line 57

def redis_UNWATCH
  if @watcher
    @watcher.unbind
    @watcher = nil
  end
  :'+OK'
end

#redis_WATCH(*keys) ⇒ Object



50
51
52
53
54
55
# File 'lib/redis/protocol.rb', line 50

def redis_WATCH *keys
  raise 'WATCH inside MULTI is not allowed' if @multi
  @watcher ||= Database::Watcher.new
  @watcher.bind @database, *keys
  :'+OK'
end

#unbindObject



12
13
14
15
16
# File 'lib/redis/protocol.rb', line 12

def unbind
  @deferred.unbind if @deferred
  @watcher.unbind if @watcher
  super
end