From 98e027b9666e556d87932bddc711707cd39468a0 Mon Sep 17 00:00:00 2001 From: Bryan Stitt Date: Wed, 29 Jun 2022 18:22:53 +0000 Subject: [PATCH] status codes on health --- TODO.md | 1 - web3-proxy/src/connections.rs | 4 ++++ web3-proxy/src/frontend/http.rs | 9 +++++++++ web3-proxy/src/frontend/mod.rs | 4 +++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 823c8ef1..0c986394 100644 --- a/TODO.md +++ b/TODO.md @@ -30,7 +30,6 @@ - even after removing a bunch of the locks, the deadlock still happens. i can't reliably reproduce. i just let it run for awhile and it happens. - running gdb shows the thread at tokio tungstenite thread is spinning near 100% cpu and none of the rest of the program is proceeding - fixed by https://github.com/gakonst/ethers-rs/pull/1287 -- [ ] quick requests/second timer until we have real stats - [ ] rpc errors propagate too far. one subscription failing ends the app. isolate the providers more - [ ] if web3 proxy gets an http error back, retry another node - [ ] endpoint for health checks. if no synced servers, give a 502 error diff --git a/web3-proxy/src/connections.rs b/web3-proxy/src/connections.rs index ab36deca..1ceb444b 100644 --- a/web3-proxy/src/connections.rs +++ b/web3-proxy/src/connections.rs @@ -315,6 +315,10 @@ impl Web3Connections { *self.synced_connections.load().get_head_block_hash() } + pub fn has_synced_rpcs(&self) -> bool { + self.synced_connections.load().inner.len() > 0 + } + /// Send the same request to all the handles. Returning the most common success or most common error. #[instrument(skip_all)] pub async fn try_send_parallel_requests( diff --git a/web3-proxy/src/frontend/http.rs b/web3-proxy/src/frontend/http.rs index 98ff1eae..5e2c50ee 100644 --- a/web3-proxy/src/frontend/http.rs +++ b/web3-proxy/src/frontend/http.rs @@ -11,6 +11,15 @@ pub async fn index() -> impl IntoResponse { "Hello, World!" } +/// Health check page for load balancers to use +pub async fn health(app: Extension>) -> impl IntoResponse { + if app.get_balanced_rpcs().has_synced_rpcs() { + (StatusCode::OK, "OK") + } else { + (StatusCode::SERVICE_UNAVAILABLE, ":(") + } +} + /// Very basic status page pub async fn status(app: Extension>) -> impl IntoResponse { // TODO: what else should we include? uptime? prometheus? diff --git a/web3-proxy/src/frontend/mod.rs b/web3-proxy/src/frontend/mod.rs index b461a4e4..2e91310a 100644 --- a/web3-proxy/src/frontend/mod.rs +++ b/web3-proxy/src/frontend/mod.rs @@ -21,8 +21,10 @@ pub async fn run(port: u16, proxy_app: Arc) -> anyhow::Result<()> .route("/", post(http_proxy::proxy_web3_rpc)) // `websocket /` goes to `proxy_web3_ws` .route("/", get(ws_proxy::websocket_handler)) - // `GET /index.html` goes to `index` (todo, somehow combine this with http_proxy::proxy_web3_rpc) + // `GET /index.html` goes to `index` .route("/index.html", get(http::index)) + // `GET /health` goes to `health` + .route("/health", get(http::health)) // `GET /status` goes to `status` .route("/status", get(http::status)) .layer(Extension(proxy_app));