Class: Raptor::ControlServer
- Inherits:
-
Object
- Object
- Raptor::ControlServer
- Defined in:
- lib/raptor/control_server.rb,
sig/generated/raptor/control_server.rbs
Overview
Serves cluster statistics over a Unix socket.
Constant Summary collapse
- SHUTDOWN =
:shutdown
Instance Method Summary collapse
-
#bind ⇒ void
Binds the Unix socket.
-
#handle(client) ⇒ void
Writes the response for one control-socket request.
-
#initialize(url) { ... } ⇒ ControlServer
constructor
Creates a control server for
urlwithout binding it. -
#remove_stale_socket ⇒ void
Removes a stale socket while refusing to replace an active server.
-
#serve ⇒ void
Accepts and handles control requests until shutdown begins.
-
#shutdown ⇒ void
Stops serving and removes the socket.
-
#start ⇒ void
Starts serving requests in a background thread.
Constructor Details
#initialize(url) { ... } ⇒ ControlServer
Creates a control server for url without binding it.
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/raptor/control_server.rb', line 30 def initialize(url, &stats) uri = URI(url) raise ArgumentError, "control_url must use unix://" unless uri.scheme == "unix" && !uri.path.empty? @path = uri.path @stats = stats @server = nil @client = Atom.new(nil) @thread = nil end |
Instance Method Details
#bind ⇒ void
This method returns an undefined value.
Binds the Unix socket.
46 47 48 49 |
# File 'lib/raptor/control_server.rb', line 46 def bind remove_stale_socket @server = UNIXServer.new(@path) end |
#handle(client) ⇒ void
This method returns an undefined value.
Writes the response for one control-socket request.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/raptor/control_server.rb', line 132 def handle(client) request_line = client.gets while line = client.gets break if line == "\r\n" end if request_line&.start_with?("GET /stats ") body = JSON.generate(@stats.call) client.write("HTTP/1.0 200 OK\r\nContent-Type: application/json\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}") else client.write("HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\n\r\n") end rescue IOError, SystemCallError ensure client.close rescue nil @client.swap { |current| current.equal?(client) ? nil : current } end |
#remove_stale_socket ⇒ void
This method returns an undefined value.
Removes a stale socket while refusing to replace an active server.
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/raptor/control_server.rb', line 92 def remove_stale_socket return unless File.exist?(@path) begin UNIXSocket.new(@path).close raise "Socket #{@path.inspect} is already in use" rescue Errno::ECONNREFUSED File.delete(@path) end end |
#serve ⇒ void
This method returns an undefined value.
Accepts and handles control requests until shutdown begins.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/raptor/control_server.rb', line 108 def serve until @client.value == SHUTDOWN readable, = IO.select([@server], nil, nil, 1) next unless readable client = @server.accept_nonblock(exception: false) next unless client.is_a?(UNIXSocket) if @client.swap { |current| current == SHUTDOWN ? current : client } == SHUTDOWN client.close return end handle(client) end rescue IOError, Errno::EBADF end |
#shutdown ⇒ void
This method returns an undefined value.
Stops serving and removes the socket.
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/raptor/control_server.rb', line 72 def shutdown client = nil @client.swap do |current| client = current SHUTDOWN end @server&.close client.close if client.is_a?(UNIXSocket) @thread&.join File.delete(@path) rescue nil end |
#start ⇒ void
This method returns an undefined value.
Starts serving requests in a background thread.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/raptor/control_server.rb', line 56 def start owner_pid = Process.pid at_exit { File.delete(@path) rescue nil if Process.pid == owner_pid } @thread = Thread.new do Thread.current.name = "Control Server" serve end end |