Class: Arpie::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/arpie/client.rb

Overview

A Client is a connection manager, and acts as the glue between a user-defined medium (for example, a TCP socket), and a protocol, with automatic reconnecting and fault handling.

See README for examples.

Direct Known Subclasses

EventedClient, RPCClient

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*protocols) ⇒ Client

Returns a new instance of Client.



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/arpie/client.rb', line 26

def initialize *protocols
  @protocol = Arpie::ProtocolChain.new(*protocols)
  @read_io = nil
  @write_io = nil
  @connector = lambda { raise ArgumentError, "No connector specified, cannot connect to Endpoint." }
  @connect_retry = nil
  @connect_sleep = 1.0
  @on_error = lambda {|client, exception|
    $stderr.puts "Error in Transport IO: #{exception.message.to_s}"
    $stderr.puts exception.backtrace.join("\n")
    $stderr.puts "Set Transport#on_error &block to override this."
  }
end

Instance Attribute Details

#connect_retryObject

How often should this Client retry a connection. 0 for never, greater than 0 for that many attempts, nil for infinite (default). Values other than nil will raise network exceptions to the caller.



18
19
20
# File 'lib/arpie/client.rb', line 18

def connect_retry
  @connect_retry
end

#connect_sleepObject

How long should the caller sleep after each reconnect attempt. (default: 1.0). The default value is probably okay. Do not set this to 0; that will produce unnecessary load in case of network failure.



24
25
26
# File 'lib/arpie/client.rb', line 24

def connect_sleep
  @connect_sleep
end

#protocolObject (readonly)

The protocol chain used.



11
12
13
# File 'lib/arpie/client.rb', line 11

def protocol
  @protocol
end

Instance Method Details

#connect(connect_immediately = false, &connector) ⇒ Object

Provide a connector block, which will be called each time a connection is needed. Expectes an IO object. Alternatively, you can return a two-item array. To test something without involving any networking, simply run IO.pipe in this block. Set connect_immediately to true to connect immediately, instead on the first message.



48
49
50
51
52
# File 'lib/arpie/client.rb', line 48

def connect connect_immediately = false, &connector
  @connector = connector
  _connect if connect_immediately
  self
end

#io_retry(&block) ⇒ Object

Execute the given block until all connection attempts have been exceeded. Yields self. You do not usually want to use this.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/arpie/client.rb', line 81

def io_retry &block
  try = 0

  begin
    _connect
    yield self
  rescue IOError => e
    try += 1
    @on_error.call(self, e) if @on_error
    p e

    if @connect_retry == 0 || (@connect_retry && try > @connect_retry)
      raise EOFError, "Cannot read from io: lost connection after #{try} attempts (#{e.message.to_s})"
    end

    sleep @connect_sleep
    begin; @read_io.close if @read_io; rescue; end
    @read_io = nil
    begin; @write_io.close if @write_io; rescue; end
    @write_io = nil
    retry
  end
end

#on_error(&handler) ⇒ Object

Set an error handler. It will be called with two parameters, the client, and the exception that occured. Optional, and just for notification.



57
58
59
60
# File 'lib/arpie/client.rb', line 57

def on_error &handler #:yields: client, exception
  @on_error = handler
  self
end

#read_messageObject

Receive a message. Blocks until received.



71
72
73
74
75
# File 'lib/arpie/client.rb', line 71

def read_message
  io_retry do
    return @protocol.read_message(@read_io)
  end
end

#write_message(message) ⇒ Object Also known as: <<

Send a message. Returns immediately.



63
64
65
66
67
# File 'lib/arpie/client.rb', line 63

def write_message message
  io_retry do
    @protocol.write_message(@write_io, message)
  end
end