# encoding: utf-8 module Hatetepe class Client include Support::Handlers include Connection::Status attr_reader :config def initialize(config) @config = config @requests = [] setup_connection setup_handlers notify_handlers(:post_init) end def request(http_method, uri) request = Request.new(http_method, uri) request.finished.fulfill perform(request) request.served.sync end def perform(request) @requests << request fiber = Fiber.new do notify_handlers(:perform, request) @connection.serialize(request) end fiber.resume end def close @connection.close end def receive(response) unless (request = correlate(response)) raise ClientError, 'Unable to correlate with request' end setup_cleanup(request, response) notify_handlers(:receive, request, response) end def teardown(reason) while (request = @requests.shift) if (response = request.served.value) response.finished.reject(reason) else request.served.reject(reason) end end end private def setup_connection @connection = EM.connect(@config[:address], @config[:port], Connection::EventMachine) @connection.parse(method(:receive)) @connection.closed.then(method(:teardown)) end def correlate(response) @requests .detect { |request| request.served.pending? } .tap { |request| request.served.fulfill(response) if request } end def setup_cleanup(request, response) callback = proc { @requests.delete(request) } response.finished.then(callback, callback) end end end