Clone this wiki locally
Timeline of events in a Goliath Server
Lifecycle of a request
Complete from reactor start onwards
Starting the Reactor
- code is loaded
- the application.rb
at_exithandler fires, invoking Application.run!
Application.run!creates an instance of the class named after the app_file name.
Application.run!creates a runner for that api instance. The runner parses the options hash.
Application.run!decorates the runner with the middleware chain (in runner.app, built by Goliath::Rack::Builder) and the plugins (from klass.plugins)
runner.runjust plain calls
run_server(if daemonize is false), or forks (killing the runner) to call
runner.run_serverconstructs a logger, tells you to watch out for stones
runner.run_serverconstructs a server, hands its app, api, plugins and the server_options off to it, and starts it.
server.startruns within an EM.synchrony block.
server.startloads the config file, and invokes
#runon each plugin.
server.startinvokes EM.start_server on a Goliath::Connection. This starts the reactor; the program does not exit until the server has halted.
Within the server's Connection
- the Connection's
post_inithook fires once the reactor comes on line. It builds a new
Http::Parser, and decorates it with three callbacks:
- When the connection receives data, it dispatches it to the parser.
on_headers_complete: fires when the parser has seen a full header block. This constructs a new
Goliath::Request, asks it to adopt and parse the headers, and enqueues it onto the tail of
on_body: fires when a chunk of body rolls in, passes it to the head of
on_message_complete: fires when the request body is complete. This dequeues the head of
@requests. If there is no
@currentrequest, make that the @current request and invoke its #succeed callback; otherwise, enqueue it onto the
@pendingqueue. Lastly, invokes the request's process method.
terminate_request: invoked by the request (on stream_close or in post_process) or on an HTTP parser error.
Within a request
stream_start=> @conn.send_data(head) ;
on_headersmethod, if any
on_bodymethod, if any
on_closemethod, if any
async_callback=> request.post_process method
@env[ASYNC_HEADERS]if it exists
parse: accumulates body. calls
@env[ASYNC_BODY](if it exists) on each chunk.
post_processon the results of
post_process: stores the response in a callback, invoked when the client is ready to consume the data.
- new fiber created and launched.
Within Goliath::Api.call's fiber
- response(env) called.
- a normal response is sent up the
- a streaming response invokes the
STREAM_STARTcallback chain. Your API class is responsible for calling
stream_close. Note that these bypass the ASYNC_CALLBACK chain.
- if an error occurs, it is caught, turned into a
validation_error, and sent up the