Hi,
I'm working on micro service for learning purposes with tokio and warp. This micro service relies on other services which makes the response time an issue due to the accumulated latency of all its dependencies. So I wanted to implement a simple cache that will query the dependencies once per day and fill a in-memory cache. I've a stripped down version of that for testing in the rust playground:
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
struct Cache {
cache: tokio::sync::RwLock<std::collections::HashMap<String, String>>,
}
impl Cache {
pub fn new() -> Self {
Cache {
cache: tokio::sync::RwLock::new(std::collections::HashMap::new()),
}
}
pub fn start(self) {
tokio::spawn(async move {
let mut i = 0;
let mut interval = tokio::time::interval(tokio::time::Duration::from_millis(10));
interval.tick().await;
loop {
let rand_string: String =
thread_rng().sample_iter(&Alphanumeric).take(30).collect();
self.cache
.write()
.await
.insert(format!("{}", i), rand_string);
interval.tick().await;
i += 1;
}
});
}
pub async fn get(&self, key: &str) -> Option<String> {
match self.cache.read().await.get(key) {
Some(result) => Some(String::from(result)),
None => None,
}
}
}
async fn use_cache(
cache: std::sync::Arc<Cache>,
) -> tokio::task::JoinHandle<()> {
tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
println!("{:?}", cache.get("1").await);
})
}
#[tokio::main]
async fn main() {
let cache = Cache::new();
let shared_cache = std::sync::Arc::new(cache);
let shared_cache = std::sync::Arc::clone(&shared_cache);
shared_cache.start();
let shared_cache = std::sync::Arc::clone(&shared_cache);
use_cache(shared_cache).await;
}
Checking playground v0.0.1 (/playground)
error[E0507]: cannot move out of an `Arc`
--> src/main.rs:55:5
|
55 | shared_cache.start();
| ^^^^^^^^^^^^ move occurs because value has type `Cache`, which does not implement the `Copy` trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground`
I've tried to make the start
method accept a &self
but then I enter into lifetime issues as I need to specify a &'static
lifetime due to tokio::spawn being also static. And to circumvent that I need to use Box::leak
so cache
is static (unless there is any other way to do that). But I still fall in the same trap . But I guess that would be for another post!
Thanks!