Class: Arborist::Monitor::Socket::TCP

Inherits:
Object
  • Object
show all
Extended by:
Loggability
Includes:
ConnectionBatching
Defined in:
lib/arborist/monitor/socket.rb

Overview

Arborist TCP socket monitor logic

Constant Summary collapse

USED_PROPERTIES =

Always request the node addresses and port.

[ :addresses, :port ].freeze

Constants included from ConnectionBatching

ConnectionBatching::DEFAULT_BATCH_SIZE, ConnectionBatching::DEFAULT_TIMEOUT

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ConnectionBatching

#handle_connections, included, #run, #with_batch_size, #with_timeout

Constructor Details

#initialize(timeout: Arborist::Monitor::Socket.default_timeout, batch_size: Arborist::Monitor::Socket.batch_size) ⇒ TCP

Create a new TCP monitor with the specified options. Valid options are:

:timeout

Set the number of seconds to wait for a connection for each node.

:batch_size

The number of UDP connection attempts to perform simultaneously.


65
66
67
68
# File 'lib/arborist/monitor/socket.rb', line 65

def initialize( timeout: Arborist::Monitor::Socket.default_timeout, batch_size: Arborist::Monitor::Socket.batch_size )
  self.timeout = timeout
  self.batch_size = batch_size
end

Class Method Details

.node_propertiesObject

Return the properties used by this monitor.



54
55
56
# File 'lib/arborist/monitor/socket.rb', line 54

def self::node_properties
  return USED_PROPERTIES
end

.run(nodes) ⇒ Object

Instantiate a monitor check and run it for the specified nodes.



48
49
50
# File 'lib/arborist/monitor/socket.rb', line 48

def self::run( nodes )
  return self.new.run( nodes )
end

Instance Method Details

#make_connections_enum(nodes) ⇒ Object

Return an Enumerator that lazily yields Hashes of the form expected by the ConnectionBatching mixin for each of the specified nodes.



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/arborist/monitor/socket.rb', line 77

def make_connections_enum( nodes )
  return nodes.lazy.map do |identifier, node_data|
    self.log.debug "Creating a socket for %s" % [ identifier ]

    # :TODO: Should this try all the addresses? Should you be able to specify an
    # address for a Service?
    address = node_data['addresses'].first
    port = node_data['port']
    sockaddr = nil

    self.log.debug "Creating TCP connection for %s:%d" % [ address, port ]
    sock = Socket.new( :INET, :STREAM )

    conn = begin
        sockaddr = Socket.sockaddr_in( port, address )
        sock.connect_nonblock( sockaddr )
        sock
      rescue Errno::EINPROGRESS
        self.log.debug "  connection started"
        sock
      rescue => err
        self.log.error "  %p setting up connection: %s" % [ err.class, err.message ]
        err
      end

    { conn: conn, identifier: identifier }
  end
end

#status_for_conn(conn_hash, duration) ⇒ Object

Build a status for the specified conn_hash after its :conn has indicated it is ready.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/arborist/monitor/socket.rb', line 109

def status_for_conn( conn_hash, duration )
  sock = conn_hash[:conn]
  # Why getpeername? Testing socket success without read()ing, I think?
  # FreeBSD source?
  sock.getpeername
  return {
    tcp_socket_connect: { duration: duration }
  }
rescue SocketError, SystemCallError => err
  self.log.debug "Got %p while connecting to %s" % [ err.class, conn_hash[:identifier] ]
  begin
    sock.read( 1 )
  rescue => err
    return { error: err.message }
  end
ensure
  sock.close if sock
end