Use a thread pool
This commit is contained in:
parent
f4447a2648
commit
3ccf7daff6
|
@ -325,10 +325,12 @@ dependencies = [
|
||||||
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"workerpool 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1468,6 +1470,14 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "workerpool"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ws2_32-sys"
|
name = "ws2_32-sys"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1637,4 +1647,5 @@ dependencies = [
|
||||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
"checksum workerpool 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f49756646617bde19ff95b370cfa5c0f7ead17a90c90d7cb62dc31dfaa8c625"
|
||||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
|
|
|
@ -15,3 +15,5 @@ serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
reqwest = "0.9"
|
reqwest = "0.9"
|
||||||
|
workerpool = "1.1.1"
|
||||||
|
lazy_static = "1.2"
|
84
src/api.rs
84
src/api.rs
|
@ -1,4 +1,88 @@
|
||||||
use serde_derive::*;
|
use serde_derive::*;
|
||||||
|
use lazy_static::*;
|
||||||
|
use workerpool::Worker;
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
sync::{
|
||||||
|
Arc,
|
||||||
|
mpsc::{channel, Receiver},
|
||||||
|
Mutex, MutexGuard
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref API: Arc<Mutex<Option<RequestContext>>>
|
||||||
|
= Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
|
static ref JOBS: workerpool::Pool<Req>
|
||||||
|
= workerpool::Pool::new(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(req: reqwest::RequestBuilder) -> Receiver<reqwest::Response> {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
JOBS.execute_to(tx, req);
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RequestContext {
|
||||||
|
token: String,
|
||||||
|
instance: String,
|
||||||
|
client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestContext {
|
||||||
|
pub fn new(instance: String) -> Self {
|
||||||
|
RequestContext {
|
||||||
|
token: String::new(),
|
||||||
|
instance: instance.clone(),
|
||||||
|
client: reqwest::Client::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auth(&mut self, token: String) {
|
||||||
|
self.token = token.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<S: AsRef<str>>(&self, url: S) -> reqwest::RequestBuilder {
|
||||||
|
self.client
|
||||||
|
.get(&format!("https://{}{}", self.instance, url.as_ref()))
|
||||||
|
.header(reqwest::header::AUTHORIZATION, format!("JWT {}", self.token))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Warning: no authentication, since it is only used for login
|
||||||
|
pub fn post<S: AsRef<str>>(&self, url: S) -> reqwest::RequestBuilder {
|
||||||
|
self.client
|
||||||
|
.post(&format!("https://{}{}", self.instance, url.as_ref()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Req;
|
||||||
|
|
||||||
|
impl Worker for Req {
|
||||||
|
type Input = reqwest::RequestBuilder;
|
||||||
|
type Output = reqwest::Response;
|
||||||
|
|
||||||
|
fn execute(&mut self, req: Self::Input) -> Self::Output {
|
||||||
|
req.send().expect("Error while sending request")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ApiResult<T> {
|
||||||
|
Ok(T),
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Into<Result<T, ()>> for ApiResult<T> {
|
||||||
|
fn into(self) -> Result<T, ()> {
|
||||||
|
match self {
|
||||||
|
ApiResult::Ok(t) => Ok(t),
|
||||||
|
ApiResult::Err => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct LoginData {
|
pub struct LoginData {
|
||||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -25,6 +25,21 @@ macro_rules! clone {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! wait {
|
||||||
|
($exp:expr => | $res:ident | $then:block) => {
|
||||||
|
let rx = $exp;
|
||||||
|
gtk::idle_add(move || {
|
||||||
|
match rx.try_recv() {
|
||||||
|
Err(_) => glib::Continue(true),
|
||||||
|
Ok(mut $res) => {
|
||||||
|
$then;
|
||||||
|
glib::Continue(false)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ use gtk::*;
|
||||||
use std::{
|
use std::{
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
ops::Deref
|
||||||
};
|
};
|
||||||
use crate::{State, api, ui::title};
|
use crate::{State, api::*, ui::title};
|
||||||
|
|
||||||
|
|
||||||
pub fn render(state: State) -> gtk::Box {
|
pub fn render(state: State) -> gtk::Box {
|
||||||
let cont = gtk::Box::new(Orientation::Vertical, 24);
|
let cont = gtk::Box::new(Orientation::Vertical, 24);
|
||||||
|
@ -27,27 +27,26 @@ pub fn render(state: State) -> gtk::Box {
|
||||||
instance, username, password
|
instance, username, password
|
||||||
)));
|
)));
|
||||||
login_bt.connect_clicked(clone!(state, widgets => move |_| {
|
login_bt.connect_clicked(clone!(state, widgets => move |_| {
|
||||||
state.borrow_mut().instance = widgets.borrow().0.get_text();
|
let mut api_ctx = crate::api::API.lock().expect("1");
|
||||||
state.borrow_mut().username = widgets.borrow().1.get_text();
|
*api_ctx = Some(RequestContext::new(
|
||||||
state.borrow_mut().password = widgets.borrow().2.get_text();
|
widgets.borrow().0.get_text().unwrap()
|
||||||
|
));
|
||||||
|
|
||||||
let res: api::LoginInfo = reqwest::Client::new()
|
let state = state.clone();
|
||||||
.post(&format!("https://{}/api/v1/token/", state.borrow().instance.clone().unwrap()))
|
wait!(execute(api_ctx.as_ref().unwrap().post("/api/v1/token/").json(&LoginData {
|
||||||
.json(&api::LoginData {
|
username: widgets.borrow().1.get_text().clone().unwrap(),
|
||||||
username: state.borrow().username.clone().unwrap(),
|
password: widgets.borrow().2.get_text().clone().unwrap(),
|
||||||
password: state.borrow().password.clone().unwrap(),
|
})) => |res| {
|
||||||
})
|
let res: Result<_, _> = res.json::<ApiResult<LoginInfo>>().unwrap().into();
|
||||||
.send()
|
|
||||||
.unwrap()
|
|
||||||
.json()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
state.borrow_mut().token = Some(res.token);
|
if let Some(ref mut api) = *crate::api::API.lock().expect("3") {
|
||||||
let main_page = crate::ui::main_page::render(state.clone());
|
api.auth(res.unwrap().token.clone());
|
||||||
main_page.show_all();
|
}
|
||||||
state.borrow_mut().stack.add_named(&main_page, "main");
|
|
||||||
state.borrow_mut().stack.set_visible_child(&main_page);
|
state.borrow_mut().stack.add_named(&crate::ui::main_page::render(state.clone()), "main");
|
||||||
|
state.borrow_mut().stack.set_visible_child_name("main");
|
||||||
state.borrow_mut().stack.show_all();
|
state.borrow_mut().stack.show_all();
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
cont.add(&title);
|
cont.add(&title);
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub fn render(state: State) -> gtk::Box {
|
||||||
cont.set_margin_end(96);
|
cont.set_margin_end(96);
|
||||||
|
|
||||||
let avatar_path = dirs::cache_dir().unwrap().join("funkload-avatar.png");
|
let avatar_path = dirs::cache_dir().unwrap().join("funkload-avatar.png");
|
||||||
let user: api::UserInfo = reqwest::Client::new()
|
/*let user: api::UserInfo = reqwest::Client::new()
|
||||||
.get(&format!("https://{}/api/v1/users/users/me/", state.borrow().instance.clone().unwrap()))
|
.get(&format!("https://{}/api/v1/users/users/me/", state.borrow().instance.clone().unwrap()))
|
||||||
.header(reqwest::header::AUTHORIZATION, format!("JWT {}", state.borrow().token.clone().unwrap_or_default()))
|
.header(reqwest::header::AUTHORIZATION, format!("JWT {}", state.borrow().token.clone().unwrap_or_default()))
|
||||||
.send()
|
.send()
|
||||||
|
@ -75,7 +75,7 @@ pub fn render(state: State) -> gtk::Box {
|
||||||
cont.add(&avatar);
|
cont.add(&avatar);
|
||||||
let lbl = Label::new(format!("Welcome {}.", user.username).as_ref());
|
let lbl = Label::new(format!("Welcome {}.", user.username).as_ref());
|
||||||
lbl.get_style_context().map(|c| c.add_class("h1"));
|
lbl.get_style_context().map(|c| c.add_class("h1"));
|
||||||
cont.add(&lbl);
|
cont.add(&lbl);*/
|
||||||
|
|
||||||
let search = SearchEntry::new();
|
let search = SearchEntry::new();
|
||||||
search.set_placeholder_text("Search");
|
search.set_placeholder_text("Search");
|
||||||
|
|
Loading…
Reference in New Issue