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
# 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 StandardError, LoadError, SyntaxError => 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



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

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

#redis_EXECObject



76
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
# File 'lib/redis/protocol.rb', line 76

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 StandardError, LoadError, SyntaxError => 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



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

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

#redis_UNWATCHObject



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

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

#redis_WATCH(*keys) ⇒ Object



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

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