Skip to content

Commit 5e805ee

Browse files
d4m014MegaRedHandpablodeymo
authored
handle same port values for API and metrics endpoints (#345)
## 🗒️ Description merged both `start_metrics_server` and `start_api_server` functions into one `start_rpc_server` receiving `RpcConfig` struct: ``` pub struct RpcConfig { pub http_address: IpAddr, pub api_port: u16, pub metrics_port: u16, } ``` while in that single function, handling whether to merge both API and metrics routers into a single endpoint if specified ports (API and metrics) are the same, or just start two separate servers as before if different ports were chosen. ## What Changed - `crates/net/rpc/src/lib.rs`: new struct `RpcConfig`, `start_metrics_server` and `start_api_server` replaced with a single `start_rpc_server`. - `bin/ethlambda/src/main.rs`: import `RpcConfig` and update callers. ## Related Issues / PRs - Closes #329 --------- Co-authored-by: Tomás Grüner <47506558+MegaRedHand@users.noreply.github.com> Co-authored-by: Pablo Deymonnaz <pdeymon@fi.uba.ar>
1 parent 533f785 commit 5e805ee

2 files changed

Lines changed: 50 additions & 41 deletions

File tree

bin/ethlambda/src/main.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use tracing::{error, info, warn};
3434
use tracing_subscriber::{EnvFilter, Layer, Registry, layer::SubscriberExt};
3535

3636
use ethlambda_blockchain::BlockChain;
37+
use ethlambda_rpc::RpcConfig;
3738
use ethlambda_storage::{StorageBackend, Store, backend::RocksDBBackend};
3839

3940
const ASCII_ART: &str = r#"
@@ -108,10 +109,13 @@ async fn main() -> eyre::Result<()> {
108109
ethlambda_blockchain::metrics::set_node_info("ethlambda", version::CLIENT_VERSION);
109110
ethlambda_blockchain::metrics::set_node_start_time();
110111

111-
let api_socket = SocketAddr::new(options.http_address, options.api_port);
112-
let metrics_socket = SocketAddr::new(options.http_address, options.metrics_port);
113112
let node_p2p_key = read_hex_file_bytes(&options.node_key);
114113
let p2p_socket = SocketAddr::new(IpAddr::from([0, 0, 0, 0]), options.gossipsub_port);
114+
let rpc_config = RpcConfig {
115+
http_address: options.http_address,
116+
api_port: options.api_port,
117+
metrics_port: options.metrics_port,
118+
};
115119

116120
println!("{ASCII_ART}");
117121

@@ -226,18 +230,12 @@ async fn main() -> eyre::Result<()> {
226230
.inspect_err(|err| error!(%err, "Failed to send InitBlockChain — actors not wired"))?;
227231

228232
let shutdown_token = CancellationToken::new();
229-
let metrics_shutdown = shutdown_token.clone();
230-
let api_shutdown = shutdown_token.clone();
233+
let rpc_shutdown = shutdown_token.clone();
231234

232-
let metrics_handle = tokio::spawn(async move {
233-
let _ = ethlambda_rpc::start_metrics_server(metrics_socket, metrics_shutdown)
234-
.await
235-
.inspect_err(|err| error!(%err, "Metrics server failed"));
236-
});
237-
let api_handle = tokio::spawn(async move {
238-
let _ = ethlambda_rpc::start_api_server(api_socket, store, aggregator, api_shutdown)
235+
let rpc_handle = tokio::spawn(async move {
236+
let _ = ethlambda_rpc::start_rpc_server(rpc_config, store, aggregator, rpc_shutdown)
239237
.await
240-
.inspect_err(|err| error!(%err, "API server failed"));
238+
.inspect_err(|err| error!(%err, "RPC server failed"));
241239
});
242240

243241
info!("Node initialized");
@@ -270,8 +268,7 @@ async fn main() -> eyre::Result<()> {
270268

271269
blockchain_ref.join().await;
272270
p2p_ref.join().await;
273-
let _ = api_handle.await;
274-
let _ = metrics_handle.await;
271+
let _ = rpc_handle.await;
275272

276273
info!("Shutdown complete");
277274

crates/net/rpc/src/lib.rs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::net::SocketAddr;
1+
use std::net::{IpAddr, SocketAddr};
22

33
use axum::{
44
Extension, Json, Router, http::HeaderValue, http::header, response::IntoResponse, routing::get,
@@ -17,47 +17,59 @@ mod fork_choice;
1717
mod heap_profiling;
1818
pub mod metrics;
1919

20-
pub async fn start_api_server(
21-
address: SocketAddr,
20+
#[derive(Debug, Clone)]
21+
pub struct RpcConfig {
22+
pub http_address: IpAddr,
23+
pub api_port: u16,
24+
pub metrics_port: u16,
25+
}
26+
27+
pub async fn start_rpc_server(
28+
config: RpcConfig,
2229
store: Store,
2330
aggregator: AggregatorController,
2431
shutdown: CancellationToken,
2532
) -> Result<(), std::io::Error> {
2633
let api_router = build_api_router(store).layer(Extension(aggregator));
27-
28-
let listener = tokio::net::TcpListener::bind(address).await?;
29-
axum::serve(listener, api_router)
30-
.with_graceful_shutdown(async move {
31-
shutdown.cancelled().await;
32-
})
33-
.await?;
34-
35-
Ok(())
36-
}
37-
38-
pub async fn start_metrics_server(
39-
address: SocketAddr,
40-
shutdown: CancellationToken,
41-
) -> Result<(), std::io::Error> {
4234
let metrics_router = metrics::start_prometheus_metrics_api();
4335
let debug_router = build_debug_router();
4436

45-
let app = Router::new().merge(metrics_router).merge(debug_router);
46-
47-
let listener = tokio::net::TcpListener::bind(address).await?;
48-
axum::serve(listener, app)
49-
.with_graceful_shutdown(async move {
50-
shutdown.cancelled().await;
51-
})
52-
.await?;
37+
if config.api_port == config.metrics_port {
38+
let app = Router::new()
39+
.merge(api_router)
40+
.merge(metrics_router)
41+
.merge(debug_router);
42+
let addr = SocketAddr::new(config.http_address, config.api_port);
43+
let listener = tokio::net::TcpListener::bind(addr).await?;
44+
axum::serve(listener, app)
45+
.with_graceful_shutdown(async move {
46+
shutdown.cancelled().await;
47+
})
48+
.await?;
49+
} else {
50+
let api_addr = SocketAddr::new(config.http_address, config.api_port);
51+
let metrics_addr = SocketAddr::new(config.http_address, config.metrics_port);
52+
let api_listener = tokio::net::TcpListener::bind(api_addr).await?;
53+
let metrics_listener = tokio::net::TcpListener::bind(metrics_addr).await?;
54+
let metrics_app = Router::new().merge(metrics_router).merge(debug_router);
55+
let metrics_shutdown = shutdown.clone();
56+
tokio::try_join!(
57+
axum::serve(api_listener, api_router).with_graceful_shutdown(async move {
58+
shutdown.cancelled().await;
59+
}),
60+
axum::serve(metrics_listener, metrics_app).with_graceful_shutdown(async move {
61+
metrics_shutdown.cancelled().await;
62+
}),
63+
)?;
64+
}
5365

5466
Ok(())
5567
}
5668

5769
/// Build the API router with the given store.
5870
///
5971
/// The aggregator controller is threaded in via `Extension` by the caller
60-
/// (see `start_api_server`) so existing store-backed handlers don't need to
72+
/// (see `start_rpc_server`) so existing store-backed handlers don't need to
6173
/// know about it and admin handlers extract it independently.
6274
fn build_api_router(store: Store) -> Router {
6375
Router::new()

0 commit comments

Comments
 (0)