LRU cache for dapps (#2006)

Conflicts:
	dapps/Cargo.toml
	dapps/src/lib.rs
This commit is contained in:
Tomasz Drwięga
2016-08-30 14:04:52 +02:00
committed by Arkadiy Paronyan
parent 6da60afaba
commit 6f321d9849
10 changed files with 214 additions and 39 deletions

View File

@@ -18,7 +18,8 @@
use std::{fs, fmt};
use std::path::PathBuf;
use std::sync::mpsc;
use std::sync::{mpsc, Arc};
use std::sync::atomic::AtomicBool;
use std::time::{Instant, Duration};
use hyper::{header, server, Decoder, Encoder, Next, Method, Control, Client};
@@ -38,19 +39,20 @@ enum FetchState {
Error(ContentHandler),
InProgress {
deadline: Instant,
receiver: mpsc::Receiver<FetchResult>
receiver: mpsc::Receiver<FetchResult>,
},
Done(Manifest),
}
pub trait DappHandler {
pub trait ContentValidator {
type Error: fmt::Debug;
fn validate_and_install(&self, app: PathBuf) -> Result<Manifest, Self::Error>;
fn done(&self, Option<&Manifest>);
}
pub struct AppFetcherHandler<H: DappHandler> {
pub struct ContentFetcherHandler<H: ContentValidator> {
abort: Arc<AtomicBool>,
control: Option<Control>,
status: FetchState,
client: Option<Client<Fetch>>,
@@ -58,7 +60,7 @@ pub struct AppFetcherHandler<H: DappHandler> {
dapp: H,
}
impl<H: DappHandler> Drop for AppFetcherHandler<H> {
impl<H: ContentValidator> Drop for ContentFetcherHandler<H> {
fn drop(&mut self) {
let manifest = match self.status {
FetchState::Done(ref manifest) => Some(manifest),
@@ -68,16 +70,18 @@ impl<H: DappHandler> Drop for AppFetcherHandler<H> {
}
}
impl<H: DappHandler> AppFetcherHandler<H> {
impl<H: ContentValidator> ContentFetcherHandler<H> {
pub fn new(
app: GithubApp,
abort: Arc<AtomicBool>,
control: Control,
using_dapps_domains: bool,
handler: H) -> Self {
let client = Client::new().expect("Failed to create a Client");
AppFetcherHandler {
ContentFetcherHandler {
abort: abort,
control: Some(control),
client: Some(client),
status: FetchState::NotStarted(app),
@@ -94,12 +98,12 @@ impl<H: DappHandler> AppFetcherHandler<H> {
// TODO [todr] https support
fn fetch_app(client: &mut Client<Fetch>, app: &GithubApp, control: Control) -> Result<mpsc::Receiver<FetchResult>, String> {
fn fetch_app(client: &mut Client<Fetch>, app: &GithubApp, abort: Arc<AtomicBool>, control: Control) -> Result<mpsc::Receiver<FetchResult>, String> {
let url = try!(app.url().parse().map_err(|e| format!("{:?}", e)));
trace!(target: "dapps", "Fetching from: {:?}", url);
let (tx, rx) = mpsc::channel();
let res = client.request(url, Fetch::new(tx, Box::new(move || {
let res = client.request(url, Fetch::new(tx, abort, Box::new(move || {
trace!(target: "dapps", "Fetching finished.");
// Ignoring control errors
let _ = control.ready(Next::read());
@@ -111,7 +115,7 @@ impl<H: DappHandler> AppFetcherHandler<H> {
}
}
impl<H: DappHandler> server::Handler<HttpStream> for AppFetcherHandler<H> {
impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<H> {
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
let status = if let FetchState::NotStarted(ref app) = self.status {
Some(match *request.method() {
@@ -120,7 +124,7 @@ impl<H: DappHandler> server::Handler<HttpStream> for AppFetcherHandler<H> {
trace!(target: "dapps", "Fetching dapp: {:?}", app);
let control = self.control.take().expect("on_request is called only once, thus control is always Some");
let client = self.client.as_mut().expect("on_request is called before client is closed.");
let fetch = Self::fetch_app(client, app, control);
let fetch = Self::fetch_app(client, app, self.abort.clone(), control);
match fetch {
Ok(receiver) => FetchState::InProgress {
deadline: Instant::now() + Duration::from_secs(FETCH_TIMEOUT),