class Falcon::Service::Supervisor

Implements a host supervisor which can restart the host services and provide various metrics about the running processes.

def do_metrics(message)

Capture process metrics relating to the process group that the supervisor belongs to.
def do_metrics(message)
	Process::Metrics::General.capture(pid: Process.ppid, ppid: Process.ppid)
end

def do_restart(message)

Restart the process group that the supervisor belongs to.
def do_restart(message)
	# Tell the parent of this process group to spin up a new process group/container.
	# Wait for that to start accepting new connections.
	# Stop accepting connections.
	# Wait for existing connnections to drain.
	# Terminate this process group.
	signal = message[:signal] || :INT
	
	Process.kill(signal, Process.ppid)
end

def endpoint

Typically a unix pipe in the same directory as the host.
The endpoint which the supervisor will bind to.
def endpoint
	@evaluator.endpoint
end

def handle(message)

@parameter message [Hash] The decoded message.
Handle an incoming request.
def handle(message)
	case message[:please]
	when 'restart'
		self.do_restart(message)
	when 'metrics'
		self.do_metrics(message)
	end
end

def initialize(...)

@parameter environment [Build::Environment]
Initialize the supervisor using the given environment.
def initialize(...)
	super
	
	@bound_endpoint = nil
end

def invoke(command)

def invoke(command)
	@bound_endpoint.local_address_endpoint.connect do |peer|
		stream = ::IO::Stream(peer)
		
		stream.puts(command.to_json, separator: "\0")
		
		response = JSON.parse(stream.read_until("\0"), symbolize_names: true)
		
		return response
	end
end

def setup(container)

@parameter container [Async::Container::Generic]
Start the supervisor process which accepts connections from the bound endpoint and processes JSON formatted messages.
def setup(container)
	container.run(name: self.name, restart: true, count: 1) do |instance|
		Async do
			@bound_endpoint.accept do |peer|
				stream = ::IO::Stream(peer)
				
				while message = stream.read_until("\0")
					response = handle(JSON.parse(message, symbolize_names: true))
					stream.puts(response.to_json, separator: "\0")
				end
			end
			
			instance.ready!
		end
	end
	
	super
end

def start

Bind the supervisor to the specified endpoint.
def start
	Console.logger.info(self) {"Binding to #{self.endpoint}..."}
	
	@bound_endpoint = Sync{self.endpoint.bound}
	
	super
end

def stop

Release the bound endpoint.
def stop
	@bound_endpoint&.close
	@bound_endpoint = nil
	
	super
end