api: fetch addresses from config.
This commit is contained in:
committed by
Mark Sinclair
parent
94ab78606a
commit
4f07343efd
@@ -8,6 +8,7 @@ use utoipa_swagger_ui::SwaggerUi;
|
||||
use crate::http::{api_docs, server::HttpServer, state::AppState};
|
||||
|
||||
pub(crate) mod price;
|
||||
pub(crate) mod watcher;
|
||||
|
||||
pub(crate) struct RouterBuilder {
|
||||
unfinished_router: Router<AppState>,
|
||||
@@ -24,7 +25,8 @@ impl RouterBuilder {
|
||||
"/",
|
||||
axum::routing::get(|| async { Redirect::permanent("/swagger") }),
|
||||
)
|
||||
.nest("/v1", Router::new().nest("/price", price::routes()));
|
||||
.nest("/v1", Router::new().nest("/price", price::routes()))
|
||||
.nest("/v1", Router::new().nest("/watcher", watcher::routes()));
|
||||
|
||||
Self {
|
||||
unfinished_router: router,
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
use axum::Router;
|
||||
use core::net::SocketAddr;
|
||||
use tokio::{net::TcpListener, task::JoinHandle};
|
||||
use tokio_util::sync::{CancellationToken, WaitForCancellationFutureOwned};
|
||||
|
||||
use crate::{
|
||||
db::DbPool,
|
||||
http::{api::RouterBuilder, state::AppState},
|
||||
};
|
||||
|
||||
/// Return handles that allow for graceful shutdown of server + awaiting its
|
||||
/// background tokio task
|
||||
pub(crate) async fn start_http_api(
|
||||
db_pool: DbPool,
|
||||
http_port: u16,
|
||||
nym_http_cache_ttl: u64,
|
||||
) -> anyhow::Result<ShutdownHandles> {
|
||||
let router_builder = RouterBuilder::with_default_routes();
|
||||
|
||||
let state = AppState::new(db_pool, nym_http_cache_ttl);
|
||||
let router = router_builder.with_state(state);
|
||||
|
||||
let bind_addr = format!("0.0.0.0:{}", http_port);
|
||||
let server = router.build_server(bind_addr).await?;
|
||||
|
||||
Ok(start_server(server))
|
||||
}
|
||||
|
||||
fn start_server(server: HttpServer) -> ShutdownHandles {
|
||||
// one copy is stored to trigger a graceful shutdown later
|
||||
let shutdown_button = CancellationToken::new();
|
||||
// other copy is given to server to listen for a shutdown
|
||||
let shutdown_receiver = shutdown_button.clone();
|
||||
let shutdown_receiver = shutdown_receiver.cancelled_owned();
|
||||
|
||||
let server_handle = tokio::spawn(async move { server.run(shutdown_receiver).await });
|
||||
|
||||
ShutdownHandles {
|
||||
server_handle,
|
||||
shutdown_button,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ShutdownHandles {
|
||||
server_handle: JoinHandle<std::io::Result<()>>,
|
||||
shutdown_button: CancellationToken,
|
||||
}
|
||||
|
||||
impl ShutdownHandles {
|
||||
/// Send graceful shutdown signal to server and wait for server task to complete
|
||||
pub(crate) async fn shutdown(self) -> anyhow::Result<()> {
|
||||
self.shutdown_button.cancel();
|
||||
|
||||
match self.server_handle.await {
|
||||
Ok(Ok(_)) => {
|
||||
tracing::info!("HTTP server shut down without errors");
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
tracing::error!("HTTP server terminated with: {err}");
|
||||
anyhow::bail!(err)
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Server task panicked: {err}");
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct HttpServer {
|
||||
router: Router,
|
||||
listener: TcpListener,
|
||||
}
|
||||
|
||||
impl HttpServer {
|
||||
pub(crate) fn new(router: Router, listener: TcpListener) -> Self {
|
||||
Self { router, listener }
|
||||
}
|
||||
|
||||
pub(crate) async fn run(self, receiver: WaitForCancellationFutureOwned) -> std::io::Result<()> {
|
||||
// into_make_service_with_connect_info allows us to see client ip address
|
||||
axum::serve(
|
||||
self.listener,
|
||||
self.router
|
||||
.into_make_service_with_connect_info::<SocketAddr>(),
|
||||
)
|
||||
.with_graceful_shutdown(receiver)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
use crate::config::Config;
|
||||
use crate::http::error::Error;
|
||||
use crate::http::error::HttpResult;
|
||||
use crate::http::state::AppState;
|
||||
use axum::{Json, Router};
|
||||
|
||||
pub(crate) fn routes() -> Router<AppState> {
|
||||
Router::new().route("/addresses", axum::routing::get(get_addresses))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
tag = "Watcher Configuration",
|
||||
get,
|
||||
path = "/v1/watcher/addresses",
|
||||
responses(
|
||||
(status = 200, body = Vec<String>)
|
||||
)
|
||||
)]
|
||||
|
||||
/// Fetch the addresses being watched by the chain watcher
|
||||
async fn get_addresses() -> HttpResult<Json<Vec<String>>> {
|
||||
let config =
|
||||
Config::read_from_toml_file_in_default_location().map_err(|_| Error::internal())?;
|
||||
|
||||
let addresses = config
|
||||
.payment_watcher_config
|
||||
.as_ref()
|
||||
.and_then(|config| {
|
||||
config.watchers.iter().find_map(|watcher| {
|
||||
watcher
|
||||
.watch_for_transfer_recipient_accounts
|
||||
.as_ref()
|
||||
.map(|accounts| {
|
||||
accounts
|
||||
.iter()
|
||||
.map(|account| account.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Json(addresses))
|
||||
}
|
||||
Reference in New Issue
Block a user