-
Notifications
You must be signed in to change notification settings - Fork 216
Timeline
mrflip edited this page Jun 27, 2011
·
4 revisions
- 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) -
Application.run!invokes runner.run -
runner.runjust plain callsrun_server(if daemonize is false), or forks (killing the runner) to callrun_server. -
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.
- the Connection's
post_inithook fires once the reactor comes on line. It builds a newHttp::Parser, and decorates it with three callbacks:on_headers_complete,on_bodyandon_message_complete. - When the connection receives data, it dispatches it to the parser.
- parser
on_headers_complete: fires when the parser has seen a full header block. This constructs a newGoliath::Request, asks it to adopt and parse the headers, and enqueues it onto the tail of@requests. - parser
on_body: fires when a chunk of body rolls in, passes it to the head ofrequeststo parse. - parser
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. - connection
terminate_request: invoked by the request (on stream_close or in post_process) or on an HTTP parser error.
Callbacks:
-
stream_send=> @conn.send_data -
stream_close=> @conn.terminate_request -
stream_start=> @conn.send_data(head) ;@conn.send_data(headers_output) -
async_headers=> apion_headersmethod, if any -
async_body=> apion_bodymethod, if any -
async_close=> apion_closemethod, if any -
async_callback=> request.post_process method
Timeline:
-
parse_header: calls@env[ASYNC_HEADERS]if it exists -
parse: accumulates body. calls@env[ASYNC_BODY](if it exists) on each chunk. -
process: callspost_processon the results of@app.call(@env) -
post_process: stores the response in a callback, invoked when the client is ready to consume the data.
- new fiber created and launched.
- response(env) called.
- a normal response is sent up the
ASYNC_CALLBACKchain. - a streaming response invokes the
STREAM_STARTcallback chain. Your API class is responsible for callingstream_sendand eventuallystream_close. Note that these bypass the ASYNC_CALLBACK chain. - if an error occurs, it is caught, turned into a
validation_error, and sent up theASYNC_CALLBACKchain.