diff --git a/sources/frontend.c b/sources/frontend.c index 54562b85..b54287d9 100644 --- a/sources/frontend.c +++ b/sources/frontend.c @@ -185,20 +185,11 @@ od_frontend_attach(od_client_t *client, char *context, kiwi_params_t *route_para rc = od_backend_connect(server, context, route_params); if (rc == -1) { /* if pool timeout is enabled we can retry */ - uint32_t timeout = route->rule->pool_timeout; - bool can_retry = timeout > 0 && + bool can_retry = route->rule->pool_timeout > 0 && od_frontend_error_is_too_many_connections(client); if (can_retry){ - od_route_lock(route); - /* we should prepare reconnection and continue */ - od_router_close(router, client); - /* enqueue client (pending -> queue) */ - od_client_pool_set(&route->client_pool, client, OD_CLIENT_QUEUE); - od_route_unlock(route); - if (timeout == 0) - timeout = UINT32_MAX; - /* Wait until someone will pu connection back to pool */ - rc = od_route_wait(route, timeout); + /* Wait until someone will put connection back to pool */ + rc = od_router_wait_retry(route, client); if (rc == -1) { od_error(&instance->logger, "router", client, NULL, "server pool wait timed out after receiving 'too many connections', closing"); diff --git a/sources/router.c b/sources/router.c index b50592b4..19f3f986 100644 --- a/sources/router.c +++ b/sources/router.c @@ -317,6 +317,34 @@ od_router_unroute(od_router_t *router, od_client_t *client) od_route_unlock(route); } +od_router_status_t +od_router_wait_retry(od_router_t *router, od_client_t *client) +{ + od_route_t *route = client->route; + od_server_t *server = client->server; + + od_backend_close_connection(server); + + od_route_lock(route); + uint32_t timeout = route->rule->pool_timeout; + /* we should prepare reconnection and continue */ + + od_server_pool_set(&route->server_pool, server, OD_SERVER_UNDEF); + client->server = NULL; + server->client = NULL; + server->route = NULL; + + /* enqueue client (pending -> queue) */ + od_client_pool_set(&route->client_pool, client, OD_CLIENT_QUEUE); + od_route_unlock(route); + + assert(server->io.io == NULL); + od_server_free(server); + + /* Wait until someone will pu connection back to pool */ + return od_route_wait(route, timeout); +} + od_router_status_t od_router_attach(od_router_t *router, od_config_t *config, od_client_t *client) { diff --git a/sources/router.h b/sources/router.h index 7cc9ff5b..257c4c11 100644 --- a/sources/router.h +++ b/sources/router.h @@ -53,6 +53,9 @@ od_router_route(od_router_t*, od_config_t*, od_client_t*); void od_router_unroute(od_router_t*, od_client_t*); +od_router_status_t +od_router_wait_retry(od_router_t *router, od_client_t *client); + od_router_status_t od_router_attach(od_router_t*, od_config_t*, od_client_t*);