Objective: The AppState carries a transmitter (TX) that is supposed to forward any HTTP Post (to /beats
) to a new task spawned in async main()
. TX, can send any generic P implementing the HandlePulse
trait.
Error: Following is compiler diagnostics:
rustc: the trait bound `fn(State<Arc<AppState<_>>>, Json<_>) -> impl Future<Output = Result<Json<_>, std::io::Error>> {root::<_>}: Handler<_, _>` is not satisfied
Consider using `#[axum::debug_handler]` to improve the error message
the following other types implement trait `Handler<T, S>`:
`Layered<L, H, T, S>` implements `Handler<T, S>`
`MethodRouter<S>` implements `Handler<(), S>`
debug_handler
cannot be used here as it doesn't support generics (yet).
Kindly pour in the insights.
Erroneous code:
use axum::{extract::State, routing::post, Json, Router};
use serde::{Deserialize, Serialize};
use std::{io, sync::Arc};
use tokio::sync::broadcast;
#[derive(Deserialize, Serialize, Clone, Debug)]
struct Pulse {
payload: String,
}
struct AppState<P> {
TX: Arc<broadcast::Sender<P>>,
}
trait HandlePulse {
fn process_event(&self) -> Result<(), io::Error>;
}
impl<P> AppState<P>
where
P: HandlePulse + Clone,
{
fn new() -> Self {
let (TX, _) = broadcast::channel(112);
let shared_state = Self {
TX: Arc::new(TX.clone()),
};
shared_state
}
}
impl HandlePulse for Pulse {
fn process_event(&self) -> Result<(), io::Error> {
dbg!(self.clone().payload);
Ok(())
}
}
#[tokio::main]
async fn main() {
let app_state: Arc<AppState<Pulse>> = Arc::new(AppState::new());
// tokio::spawn a task and use trait implementation to handle message.
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
let app = Router::new()
.route("/beats", post(root)) // ERROR HAPPENS HERE.
.with_state(app_state);
axum::serve(listener, app).await.unwrap();
}
async fn root<P>(
State(state): State<Arc<AppState<P>>>,
Json(payload): Json<P>,
) -> Result<Json<P>, io::Error>
where
P: HandlePulse + Clone + Send + Sync + 'static,
{
if let Err(e) = state.TX.send(payload.clone()) {
eprintln!("Error while sending: {:?}", e.to_string());
}
// transmitting logic.
Ok(Json(payload))
}
Thank you for your support.