Caching the ServerInformation for CLI

This commit is contained in:
Mahesh Bansod 2021-11-07 20:27:38 +05:30
parent 4003dfe246
commit a1d3c64765
4 changed files with 154 additions and 20 deletions

View File

@ -15,7 +15,7 @@ async fn main() {
let args = Cli::from_args();
let config = load_config();
let sv = init_client(&config).await;
let (sv, mut cached) = init_all(&config).await;
if let Some(cmd) = args.commands {
match cmd {
@ -234,8 +234,10 @@ async fn main() {
}
}
// sv.save_session(&config.sessions_file)
// .expect("Couldn't save the session");
// todo: maybe save these again ONLY if modified
cached
.save(&config.cached_stuff_path)
.expect("Couldn't save cached stuff");
std::fs::write(&config.session_file, sv.session.serialize()).unwrap();
save_config(&config).expect("Couldn't save the config");
}

View File

@ -1,15 +1,18 @@
use rpassword::read_password;
use serde::{Deserialize, Serialize};
use std::io::{stdin, stdout, Write};
use std::time::{Duration, SystemTime};
use crate::error::MyFriendlyError;
use socialvoid::session::SessionHolder;
use socialvoid_types::ServerInformation;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Config {
pub session_file: String,
pub base_path: String,
pub config_path: String,
pub cached_stuff_path: String,
}
pub fn load_config() -> Config {
@ -33,6 +36,7 @@ pub fn load_config() -> Config {
},
Err(_err) => Config {
session_file: format!("{}/session", base_path),
cached_stuff_path: format!("{}/cached_stuff", base_path),
base_path,
config_path,
},
@ -65,14 +69,54 @@ pub fn prompt_password(prompt: &str) -> String {
read_password().expect("Couldn't read the password")
}
pub async fn init_client(config: &Config) -> socialvoid::Client {
match std::fs::read(&config.session_file) {
Ok(bytes) => match socialvoid::new(SessionHolder::deserialize(bytes)).await {
Ok(client) => client,
Err(_) => panic!(
pub async fn init_all(config: &Config) -> (socialvoid::Client, CachedStuff) {
//TODO: only send errors from here and let the main.rs handle situations for panics
//load cached stuff
let mut cached: CachedStuff = match std::fs::read_to_string(&config.cached_stuff_path) {
Ok(cached_stuff_str) => {
serde_json::from_str(&cached_stuff_str).unwrap_or_else(|_| CachedStuff::default())
}
Err(_err) => CachedStuff::default(),
};
if let Ok(cache_last_updated) = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH + Duration::from_secs(cached.last_updated_on))
{
if cache_last_updated.as_secs() > cached.update_after {
cached.update().await;
match cached.save(&config.cached_stuff_path) {
Ok(_) => {}
Err(err) => println!("Error while saving cache.\n{}", err),
}
}
} else {
cached.update().await;
match cached.save(&config.cached_stuff_path) {
Ok(_) => {}
Err(err) => println!("Error while saving cache.\n{}", err),
}
}
//load sessions
let client = match std::fs::read(&config.session_file) {
Ok(bytes) => {
match socialvoid::new(
SessionHolder::deserialize(bytes),
cached.rpc_url.clone(),
cached
.server_info
.as_ref()
.map(|server_info| server_info.cdn_server.clone()),
)
.await
{
Ok(client) => client,
Err(_) => panic!(
"The session file may be corrupt. try deleting it to have a new session created."
),
},
),
}
}
Err(err) => {
println!(
"There was a problem while reading the session file.\n{}",
@ -89,5 +133,52 @@ pub async fn init_client(config: &Config) -> socialvoid::Client {
),
}
}
};
(client, cached)
}
#[derive(Serialize, Deserialize)]
pub struct CachedStuff {
/// unix timestamp when cache updated last time
last_updated_on: u64,
/// update cache if `update_after` seconds have passed after updating
/// it the last time (since `last_updated_on`).
update_after: u64,
pub rpc_url: Option<String>, //only updated by the user
pub server_info: Option<ServerInformation>,
}
impl Default for CachedStuff {
fn default() -> Self {
Self {
last_updated_on: 0,
update_after: 86400, // 1 day
rpc_url: Some("http://socialvoid.qlg1.com:5601/".to_string()),
server_info: None,
}
}
}
impl CachedStuff {
async fn update(&mut self) {
let sv = socialvoid::new_with_host(self.rpc_url.clone());
if let Ok(server_info) = sv.help.get_server_information().await {
self.server_info = Some(server_info);
self.last_updated_on = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
} else {
println!("There was a problem while updating the cache.");
}
}
pub fn save(&self, path: &str) -> Result<(), std::io::Error> {
std::fs::write(path, serde_json::to_string(&self).unwrap())?;
Ok(())
}
}

View File

@ -63,12 +63,49 @@ async fn make_cdn_client_from(
))
}
/// Create a client with user defined session
/// Creates a new client with the given rpc url, default cdn url and no sessions
pub fn new_with_host(rpc_url: Option<String>) -> Client {
let rpc_client = if let Some(rpc_url) = rpc_url {
Arc::new(socialvoid_rawclient::with_host(&rpc_url))
} else {
Arc::new(socialvoid_rawclient::new())
};
let cdn_client = Arc::new(socialvoid_rawclient::CdnClient::new());
let client_info = Arc::new(ClientInfo::generate());
let session_holder = Arc::new(Mutex::new(SessionHolder::new(Arc::clone(&client_info))));
let (session, network, account, timeline, help) = init_methods(
Arc::clone(&rpc_client),
Arc::clone(&cdn_client),
Arc::clone(&session_holder),
);
Client {
session,
cdn_client,
help,
timeline,
network,
account,
}
}
/// Create a client with user defined session, (optional)rpc server url and (optional)cdn server url
/// And CDN as given in the server information
/// TODO: maybe verify the session and return an error if session is invalid
pub async fn new(session: SessionHolder) -> Result<Client, SocialvoidError> {
let rpc_client = Arc::new(socialvoid_rawclient::new());
let cdn_client = Arc::new(make_cdn_client_from(Arc::clone(&rpc_client)).await?);
pub async fn new(
session: SessionHolder,
rpc_url: Option<String>,
cdn_url: Option<String>,
) -> Result<Client, SocialvoidError> {
let rpc_client = if let Some(rpc_url) = rpc_url {
Arc::new(socialvoid_rawclient::with_host(&rpc_url))
} else {
Arc::new(socialvoid_rawclient::new())
};
let cdn_client = if let Some(cdn_url) = cdn_url {
Arc::new(socialvoid_rawclient::CdnClient::with_cdn_url(cdn_url))
} else {
Arc::new(make_cdn_client_from(Arc::clone(&rpc_client)).await?)
};
let session_holder = Arc::new(Mutex::new(session));
let (session, network, account, timeline, help) = init_methods(
Arc::clone(&rpc_client),

View File

@ -37,10 +37,10 @@ impl Client {
) -> Result<T, RpcError> {
let request = RawRequest::new(Some(generate_id()), method.to_string(), Some(params));
// dbg!(
// "Request: {}",
// serde_json::to_string_pretty(&request).unwrap()
// );
println!(
"Request: {}",
serde_json::to_string_pretty(&request).unwrap()
);
//TODO: maybe check the response better as well??
let resp: serde_json::Value = self
@ -52,7 +52,11 @@ impl Client {
.json()
.await?;
// dbg!("{}", serde_json::to_string_pretty(&resp).unwrap());
println!(
"Response to `{}`: {}",
method,
serde_json::to_string_pretty(&resp).unwrap()
);
let resp: RawResponse<T> = serde_json::value::from_value(resp).unwrap();
resp.result()
}
@ -116,7 +120,7 @@ impl std::convert::From<reqwest::Error> for RpcError {
fn from(error: reqwest::Error) -> Self {
RpcError {
code: -1,
message: Some(format!("Reqwest error: {}", error)),
message: Some(format!("Reqwest error: {:?}", error)),
data: None,
}
}