Caching the ServerInformation for CLI
This commit is contained in:
parent
4003dfe246
commit
a1d3c64765
|
@ -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");
|
||||
}
|
||||
|
|
105
cli/src/utils.rs
105
cli/src/utils.rs
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue