+ Websocket setup is almost proper but it completely hangs after we start listening for connections

Of course this is an issue because we can no longer get data from the user
A full rearchitecting may be in order here however its not impossible to modify the current architecture so far

The main issue here is that the cache is doing too much I think

If the termion(main input) task does its thing, and a socket task,
waits around waiting to build a sub task(socket) then we may be able to
pass messages to the socket task to open up sockets when request
This allows us to have shared state via message passing and a main task
can take care of updating the cache.

The renderer can then request data from the cache when it needs to render stuff
This commit is contained in:
shockrah 2021-04-09 22:10:08 -07:00
parent a0b8e82000
commit f92ced1241
3 changed files with 73 additions and 18 deletions

View File

@ -5,7 +5,7 @@ const VOICE_CHANNEL: i32 = 1;
pub const TEXT_CHANNEL: i32 = 2;
// Network Types
#[allow(dead_code)]
#[derive(Debug)]
pub struct Message {
pub id: u64,
pub time: i64,
@ -16,6 +16,20 @@ pub struct Message {
pub username: String,
}
impl Message {
pub fn bogus(s: String) -> Message {
Message {
id: 1,
time: 1,
content: s,
content_type: "text/plain".into(),
channel_id: 1,
userid: 1,
username: "yes".into()
}
}
}
#[derive(Deserialize, Clone)]
pub struct Channel {

View File

@ -12,18 +12,23 @@
*
*/
use crate::api_types::{Channel, Message};
use crate::api_types::Channel;
use crate::net;
use crate::command::Command;
use crate::config::{ConfigFile, ServerConfig};
use tokio_tungstenite::connect_async;
use futures::StreamExt;
use std::collections::HashMap;
use crate::api_types as api;
type ChannelMeta = Channel;
async fn nop() {
}
struct ChannelCache {
pub meta: ChannelMeta,
pub messages: Vec<Message>
pub messages: Vec<api::Message>
}
struct ServerCache {
@ -37,7 +42,7 @@ pub struct Cache {
// url -> Cache
servers: HashMap<String, ServerCache>,
active_server: Option<ServerConfig>,
active_text: Option<ChannelMeta>
active_text: Option<ChannelMeta>,
}
impl ServerCache {
@ -58,18 +63,25 @@ impl Cache {
Cache {
servers,
active_server: None,
active_text: None
active_text: None,
}
}
}
impl Cache {
pub fn find_serv(&self, portion: String) -> Option<(String, u64)> {
let item = self.servers.iter()
.find(|(url, _)| url.contains(portion.as_str()));
if let Some((url, cache)) = item {
Some((url.clone(), cache.meta.user.id))
} else {
None
}
}
pub async fn switch_channel(&mut self, id: u64) -> Command {
if let None = self.active_server {
return Command::Failure("No active server set!".into())
}
// find the channel meta data
let mut msg = String::new();
for (_url, cache) in &self.servers {
if let Some(channel_cache) = cache.channels.get(&id) {
@ -86,22 +98,51 @@ impl Cache {
}
}
pub async fn switch_server(&mut self, host: &str) -> Command {
// TODO: implement some better fuzzy finding for better ergonomics
// Reallt though the ux is still pretty bad here
// Also it greedily matches so if two servers are behind one domain we're kinda fucked
fn new_message(&mut self, msg: api::Message, url: String, chan_id: u64) {
self.servers.get_mut(&url).unwrap()
.channels.get_mut(&chan_id).unwrap()
.messages.push(msg);
}
pub async fn setup_websocket(&mut self, url: String, chan_id: u64) {
use crate::log;
// Ignore inactive server state & NoneType<Jwt>
if let None = self.active_server { return; }
match connect_async(url.clone()).await {
Ok((ws, _)) => {
let (_tx, rx) = ws.split();
let reader = rx.for_each(move |message| {
let msg = message.unwrap().into_text().unwrap();
let msg = api::Message::bogus(msg);
log::file(&msg);
self.new_message(msg, url.clone(), chan_id);
nop()
});
//tokio::spawn(reader);
},
Err(e) => {
log::plain(format!("{}: {}\n", e, url))
}
};
}
pub async fn switch_server(&mut self, host: &str) -> (Command, Option<String>) {
// TODO: clean this func to be less ugly/easier to read
let mut found = false;
let mut err_msg = String::from("Nothing found");
let mut fresh_token: Option<String> = None;
for (url, meta) in self.servers.iter_mut() {
if url.contains(host) {
let id = meta.meta.user.id;
let secret = &meta.meta.user.secret;
found = match net::login(url, id, secret).await {
Ok(jwt) => {
fresh_token = Some(jwt.clone());
meta.meta.user.jwt = Some(jwt);
self.active_server = Some(meta.meta.clone());
// TODO: Setup websocket to server or something idk
net::setup_websocket("adsf").await;
self.active_text = None;
true
},
@ -120,9 +161,9 @@ impl Cache {
}
if found {
Command::Text(format!("logged in - /lc to list to list channels"))
(Command::Text(format!("logged in - /lc to list to list channels")), fresh_token)
} else {
Command::Failure(err_msg)
(Command::Failure(err_msg), None)
}
}

View File

@ -231,7 +231,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
if let Some((url, id)) = app.cache.find_serv(url_portion) {
let (cmd, jwt) = app.cache.switch_server(url.as_str()).await;
let url = net::ws_url(url.as_str(), jwt);
app.cache = app.cache.setup_websocket(url, id).await;
app.cache.setup_websocket(url, id).await;
cmd
} else {
Command::Failure("No server found".into())