Associate messages with their sender, fetching senders if necessary

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo
2021-08-25 14:20:03 -06:00
co-authored by Max Brunsfeld
parent 77c7fa53da
commit 8f86fa1ccd
7 changed files with 207 additions and 44 deletions
+59
View File
@@ -0,0 +1,59 @@
use crate::rpc::Client;
use anyhow::{anyhow, Result};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc};
use zrpc::proto;
pub use proto::User;
pub struct UserStore {
users: Mutex<HashMap<u64, Arc<User>>>,
rpc: Arc<Client>,
}
impl UserStore {
pub fn new(rpc: Arc<Client>) -> Self {
Self {
users: Default::default(),
rpc,
}
}
pub async fn load_users(&self, mut user_ids: Vec<u64>) -> Result<()> {
{
let users = self.users.lock();
user_ids.retain(|id| !users.contains_key(id));
}
if !user_ids.is_empty() {
let response = self.rpc.request(proto::GetUsers { user_ids }).await?;
let mut users = self.users.lock();
for user in response.users {
users.insert(user.id, Arc::new(user));
}
}
Ok(())
}
pub async fn get_user(&self, user_id: u64) -> Result<Arc<User>> {
if let Some(user) = self.users.lock().get(&user_id).cloned() {
return Ok(user);
}
let response = self
.rpc
.request(proto::GetUsers {
user_ids: vec![user_id],
})
.await?;
if let Some(user) = response.users.into_iter().next() {
let user = Arc::new(user);
self.users.lock().insert(user_id, user.clone());
Ok(user)
} else {
Err(anyhow!("server responded with no users"))
}
}
}