Below is my simple Axum server code:
use std::num::NonZeroUsize;
use std::sync::{Arc, Mutex};
use axum::response::IntoResponse;
use axum::routing::get;
use axum::{Extension, Router};
use bytes::Bytes;
use lru::LruCache;
type Cache = Arc<Mutex<LruCache<u64, Bytes>>>;
async fn generate(Extension(cache): Extension<Cache>) -> impl IntoResponse {
let key: u64 = ...;
let mut g = cache.lock().unwrap();
let data = match g.get(&key) {
Some(v) => {
println!("Match cache {}", key);
v.to_owned()
}
None => {
println!("Retrieve url");
match reqwest::get("https://www.rust-lang.org/").await {
Ok(response) => match response.bytes().await {
Ok(body) => {
g.put(key, body.clone());
body
}
Err(_) => Bytes::new(),
},
Err(_) => Bytes::new(),
}
}
};
...
}
#[tokio::main]
async fn main() {
let cache: Cache = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(100).unwrap())));
let app = Router::new()
.route("/image/:spec/:url", get(generate))
.layer(Extension(cache));
...
}
But I'm getting this error:
error[E0277]: the trait bound `fn(Extension<Arc<std::sync::Mutex<LruCache<u64, bytes::Bytes>>>>) -> impl Future<Output = impl IntoResponse> {generate}: Handler<_, _>` is not satisfied
--> src/main.rs:42:41
|
42 | .route("/image/:spec/:url", get(generate))
| --- ^^^^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(Extension<Arc<std::sync::Mutex<LruCache<u64, bytes::Bytes>>>>) -> impl Future<Output = impl IntoResponse> {generate}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Handler<T, S>`:
<Layered<L, H, T, S> as Handler<T, S>>
<MethodRouter<S> as Handler<(), S>>
I spent a long time but didn't figure it out, I think the problem is here:
let mut g = cache.lock().unwrap();
because if I changed it to let mut g: HashMap<u64, Bytes> = HashMap::new();
, the error will be gone. What is the issue here? How can I use my cache?
I needed to change my cache to use tokio::sync::Mutex
instead of std::sync::Mutex
:
The lock guard for the standard library Mutex
is not Send
. When held over an .await
point, that prevents the Future
generated by the async function from implementing Send
, which is required by axum. Tokio's Mutex
does not have this problem.
See also: