1use crate::rpc::Client;
2use anyhow::{anyhow, Result};
3use parking_lot::Mutex;
4use std::{collections::HashMap, sync::Arc};
5use zrpc::proto;
6
7pub use proto::User;
8
9pub struct UserStore {
10 users: Mutex<HashMap<u64, Arc<User>>>,
11 rpc: Arc<Client>,
12}
13
14impl UserStore {
15 pub fn new(rpc: Arc<Client>) -> Self {
16 Self {
17 users: Default::default(),
18 rpc,
19 }
20 }
21
22 pub async fn load_users(&self, mut user_ids: Vec<u64>) -> Result<()> {
23 {
24 let users = self.users.lock();
25 user_ids.retain(|id| !users.contains_key(id));
26 }
27
28 if !user_ids.is_empty() {
29 let response = self.rpc.request(proto::GetUsers { user_ids }).await?;
30 let mut users = self.users.lock();
31 for user in response.users {
32 users.insert(user.id, Arc::new(user));
33 }
34 }
35
36 Ok(())
37 }
38
39 pub async fn get_user(&self, user_id: u64) -> Result<Arc<User>> {
40 if let Some(user) = self.users.lock().get(&user_id).cloned() {
41 return Ok(user);
42 }
43
44 let response = self
45 .rpc
46 .request(proto::GetUsers {
47 user_ids: vec![user_id],
48 })
49 .await?;
50
51 if let Some(user) = response.users.into_iter().next() {
52 let user = Arc::new(user);
53 self.users.lock().insert(user_id, user.clone());
54 Ok(user)
55 } else {
56 Err(anyhow!("server responded with no users"))
57 }
58 }
59}