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