ngx_int_t hustdb_ha_start_del(
    ngx_bool_t support_post_only,
    ngx_bool_t key_in_body,
    ngx_bool_t has_tb,
    ngx_bool_t check_body_len,
    ngx_str_t * backend_uri,
    ngx_http_request_t *r)
{
    if (key_in_body)
    {
        return hustdb_ha_start_post(support_post_only, key_in_body, has_tb, check_body_len, backend_uri, r);
    }

    ngx_http_hustdb_ha_write_ctx_t * ctx = __create_write_ctx(r);
    if (!ctx)
    {
        return NGX_ERROR;
    }
    ctx->base.base.backend_uri = backend_uri;
    write_ctx_t tmp;
    if (!__set_write_context(NULL, has_tb, r, &tmp))
    {
        return NGX_ERROR;
    }
    __copy_data(&tmp, ctx);

    return ngx_http_gen_subrequest(
               ctx->base.base.backend_uri,
               r,
               ctx->base.peer->peer,
               &ctx->base.base,
               hustdb_ha_on_subrequest_complete);
}
static ngx_int_t __first_loop(hustdb_ha_check_parameter_t check_parameter, ngx_str_t * backend_uri, ngx_http_request_t *r)
{
    if (!check_parameter(backend_uri, r))
    {
        return NGX_ERROR;
    }

    ngx_http_upstream_rr_peers_t * peers = ngx_http_get_backends();
    if (!peers || !peers->peer)
    {
        return NGX_ERROR;
    }

    hustdb_ha_loop_ctx_t * ctx = ngx_palloc(r->pool, sizeof(hustdb_ha_loop_ctx_t));
    if (!ctx)
    {
        return NGX_ERROR;
    }
    memset(ctx, 0, sizeof(hustdb_ha_loop_ctx_t));
    ngx_http_set_addon_module_ctx(r, ctx);

    ctx->peer = ngx_http_first_peer(peers->peer);

    return ngx_http_gen_subrequest(backend_uri, r, ctx->peer,
        &ctx->base, ngx_http_post_subrequest_handler);
}
static void __post_handler(ngx_http_request_t *r)
{
    --r->main->count;

    ngx_http_hustdb_ha_write_ctx_t * ctx = ngx_http_get_addon_module_ctx(r);

    ngx_bool_t rc = true;
    if (ctx->key_in_body)
    {
        if (!__init_write_ctx_by_body(r, ctx))
        {
            rc = false;
        }
    }
    else
    {
        if (ctx->check_body_len)
        {
            rc = hustdb_ha_check_body(r);
        }
    }

    if (!rc)
    {
        hustdb_ha_send_response(NGX_HTTP_NOT_FOUND, NULL, NULL, r);
        return;
    }

    ngx_http_gen_subrequest(
        ctx->base.base.backend_uri,
        r,
        ctx->base.peer->peer,
        &ctx->base.base,
        hustdb_ha_on_subrequest_complete);
}
static void __post_body_handler(ngx_http_request_t * r)
{
    hustmq_ha_put_ctx_t * ctx = ngx_http_get_addon_module_ctx(r);
    --r->main->count;
    ngx_http_gen_subrequest(ctx->base.backend_uri, r, NULL,
        &ctx->base, ngx_http_post_subrequest_handler);
}
static void __post_body_handler(ngx_http_request_t *r)
{
    --r->main->count;

    ngx_http_hustdb_ha_write_ctx_t * ctx = ngx_http_get_addon_module_ctx(r);

    ctx->base.key = hustdb_ha_get_key(r);
    if (!ctx->base.key)
    {
        hustdb_ha_send_response(NGX_HTTP_NOT_FOUND, NULL, NULL, r);
        return;
    }

    ngx_http_gen_subrequest(
        ctx->base.base.backend_uri,
        r,
        ctx->base.peer->peer,
        &ctx->base.base,
        hustdb_ha_on_subrequest_complete);
}
static void __post_handler(ngx_http_request_t *r)
{
    --r->main->count;
    hustdb_ha_ctx_t * ctx = ngx_http_get_addon_module_ctx(r);

    ngx_http_subrequest_peer_t * peer = __get_readable_peer(ctx->key_in_body, r);
    if (!peer)
    {
        hustdb_ha_send_response(NGX_HTTP_NOT_FOUND, NULL, NULL, r);
    }
    else
    {
        ctx->peer = peer;

        ngx_http_gen_subrequest(
            ctx->base.backend_uri,
            r,
            peer->peer,
            &ctx->base,
            hustdb_ha_on_subrequest_complete);
    }
}
static ngx_int_t __start_read(ngx_str_t * backend_uri, ngx_http_request_t *r)
{
	ngx_http_subrequest_peer_t * peer = __get_peer_by_args(r);
	if (!peer)
	{
		return NGX_ERROR;
	}

	hustdb_ha_ctx_t * ctx = __create_ctx(r);
	if (!ctx)
	{
		return NGX_ERROR;
	}

	ctx->peer = peer;
	return ngx_http_gen_subrequest(
	        backend_uri,
			r,
			peer->peer,
			&ctx->base,
			hustdb_ha_on_subrequest_complete);
}
static ngx_int_t __post_peer(ngx_str_t * backend_uri, ngx_http_request_t *r)
{
    ngx_http_upstream_rr_peer_t * peer = hustdb_ha_get_peer(r);
    if (!peer)
    {
        return NGX_ERROR;
    }

    hustdb_ha_peer_ctx_t * ctx = ngx_palloc(r->pool, sizeof(hustdb_ha_peer_ctx_t));
    if (!ctx)
    {
        return NGX_ERROR;
    }
    memset(ctx, 0, sizeof(hustdb_ha_peer_ctx_t));
    ngx_http_set_addon_module_ctx(r, ctx);


    ngx_str_t key = ngx_string(PEER_KEY);
    ctx->base.args = ngx_http_remove_param(&r->args, &key, r->pool);

    return ngx_http_gen_subrequest(backend_uri, r, peer,
        &ctx->base, __on_subrequest_complete);
}