best approach for content phase handler to run again with event timer & ngx_done?
bsfranks at gmail.com
bsfranks at gmail.com
Mon Jun 2 18:05:14 UTC 2014
Maxim - thank you for your helpful response. I will review the memcached
module.
In the meantime, I had tried a few things and ended up with the following
approach (as a rough example):
static ngx_int_t content_phase_handler(ngx_http_request_t *r) {
...
/* some function that returns AGAIN or OK to either wait or proceed */
rc = function();
if (rc == NGX_AGAIN) {
r->main->count++;
ctx->ev.handler = event_handler;
ctx->ev.data = r;
ctx->ev.log = r->connection->log;
ngx_add_timer(&ctx->ev, 100);
return NGX_DONE;
}
...normal work of content phase handler...
}
static void event_handler(ngx_event_t *ev) {
ngx_http_request *r;
r = ev->data;
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
return;
}
I had noticed from the DEBUG log output sequence that
nginx_finalize_request() was getting called after NGX_DONE was returned
from the content phase handler. From the source, nginx_finalize_request()
called nginx_http_finalize_connection() if (r->main->count != 1), which
then called nginx_http_close_request() which decremented the count and
returned without freeing the req or closing the connection.
So, it seems like some of what you've recommended (incrementing req count,
and having finalize_request called) is then being done.
This seemed to work correctly and each time the event handler triggered,
the content phase handler was called again. However, is calling
core_run_phases() a poor/dangerous approach or not recommended?
Also, is there a recommended lower bound for the millisecond timer? For
example, don't make it smaller than X ms, otherwise the event cycle gets
run too frequently?
Thanks,
Ben
On Mon, Jun 2, 2014 at 9:26 AM, Maxim Dounin <mdounin at mdounin.ru> wrote:
> Hello!
>
> On Fri, May 30, 2014 at 02:27:36PM -0700, bfranks781 at gmail.com wrote:
>
> > If a content phase handler needs to wait on some potentially delayed
> > result, my understanding is that it should return NGX_DONE so that it is
> > called again.
> >
> > I've been reading through the eval, echo, and http_limit_req modules to
> see
> > how to integrate an nginx_add_timer event prior to returning NGX_DONE. A
> > short timer event seems reasonable, because the content phase handler
> isn't
> > waiting on some other event type (subrequest result, timeout, etc). The
> > timer event seems fairly straight-forward -- configure the event in a
> > request context and set the event handler, data and log.
> >
> > I don't really want my timer event handler to do anything -- rather I
> just
> > want the same content phase handler that had previously returned NGX_DONE
> > to run again. In that case, should my timer event handler actually do
> > anything at all? Is there a best practice for this -- i.e. have it point
> > to the write_event_handler(), call ngx_http_core_run_phases() or
> > ngx_http_run_posted_requests(), etc?
>
> A content phase handler will not be called again (or at least it's
> not supposed to). If a content phase handler returns NGX_DONE, it
> means that it's responsible for further request handling, in
> particular:
>
> - you've already done proper request reference counting tweaks
> (normally, by just calling ngx_http_read_client_request_body(),
> which will do r->count++);
>
> - you are responsible for sending a response and then finalizing
> the request with ngx_http_finalize_request().
>
> Modules based on the ngx_http_upstream.c (most simple one is
> memcached) are examples of content handlers which return NGX_DONE.
>
> --
> Maxim Dounin
> http://nginx.org/
>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20140602/6843cb84/attachment.html>
More information about the nginx-devel
mailing list