Implementing a non-blocking delay between request and response

Tronman nginx-forum at nginx.us
Thu Jan 14 22:26:44 MSK 2010


Hi there,

I'm trying to figure out how to implement a non blocking delay between when a request comes into a module, and when it is responded too.

For example, consider a blocking delay:


static ngx_int_t
ngx_http_my_module_handler(ngx_http_request_t *r)
{
	r->headers_out.status = NGX_HTTP_OK
	r->header_only = 1;
	r->headers_out.content_length_n = 0;

	ngx_sleep(10);

	rc = ngx_http_send_header(r);	
	ngx_http_finalize_request(r, rc);
	return NGX_DONE;
}


Which would allow a client to connect, wait for 10 seconds, and then send the response. That's the behaviour I want, but such a wait as implemented here is blocking, that is, while the first request is waiting to be served, all the other requests are blocked until it completed. I want to make it non blocking so that while one is being processed (and waiting), others can come into the system and be handled (which may themselves wait, or may not).

So after some research, I found out about nginx timers, and it seems I should be able to set a timer/event hander to implement the wait and be non-blocking:


static void ngx_http_my_module_delay_handler(ngx_event_t *ev);

static ngx_int_t
ngx_http_my_module_handler(ngx_http_request_t *r)
{
	r->headers_out.status = NGX_HTTP_OK
	r->header_only = 1;
	r->headers_out.content_length_n = 0;

	ngx_event_t *wakeupFromSleep;
	wakeupFromSleep = ngx_pcalloc(r->pool, sizeof(ngx_event_t));

	if (wakeupFromSleep == NULL)
		ngx_log_stderr(0, "Wakeupfromsleep null");

	wakeupFromSleep->handler = ngx_http_my_module_delay_handler;
	wakeupFromSleep->data = r;
	ngx_log_stderr(0, "Sleeping for 30 seconds");
	ngx_add_timer(wakeupFromSleep, 30);

	return NGX_DONE;
}

static void
ngx_http_my_module_delay_handler(ngx_event_t *ev)
{
	int rc;
	ngx_http_request_t *r = ev->data;
	ngx_log_stderr(0, "Done waiting. Sending response.");

	rc = ngx_http_send_header(r);	
	ngx_http_finalize_request(r, rc);
	ngx_del_timer(ev);
}


Unfortunately, when I connect (say with telnet), and send my request, the connection immediately closes instead of waiting. In addition, I never see the "Done waiting. Sending response." message, indicating to me that the event isn't waking up.

My guess as to why the connection is closing immediately has to do with my returning NGX_DONE in ngx_http_my_module_handler, but I can't figure out what else to return that would allow it not to close, and wait for the timer. I can't figure out why the timer event isn't raising, though I suspect it has to do with the connection immediately returning. I think it's just something I'm missing in the setup, but I'm not sure (My view of how timers should work like this could also be flawed).

Any advice you have would be helpful! Thanks.

Posted at Nginx Forum: http://forum.nginx.org/read.php?2,41283,41283#msg-41283




More information about the nginx mailing list