From 0f1e1f65edcf2f435636b01c6dd100e24828fff1 Mon Sep 17 00:00:00 2001 From: Magnus Hoff Date: Sun, 22 Oct 2017 14:36:05 +0200 Subject: [PATCH] Factor out pagination resolver from ChangesResource and call it ChangesLookup --- src/resources/changes_resource.rs | 78 ++++++++++++++++++++----------- src/resources/mod.rs | 2 +- src/wiki_lookup.rs | 19 ++++---- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/src/resources/changes_resource.rs b/src/resources/changes_resource.rs index 2e3dbfc..35c008a 100644 --- a/src/resources/changes_resource.rs +++ b/src/resources/changes_resource.rs @@ -1,5 +1,5 @@ use futures::{self, Future}; -use futures::future::finished; +use futures::future::{done, finished}; use hyper; use hyper::header::ContentType; use hyper::server::*; @@ -17,39 +17,61 @@ const PAGE_SIZE: i32 = 30; type BoxResource = Box; +#[derive(Clone)] +pub struct ChangesLookup { + state: State, +} + +impl ChangesLookup { + pub fn new(state: State) -> ChangesLookup { + Self { state } + } + + pub fn lookup(&self, query: Option<&str>) -> Box, Error=::web::Error>> { + use super::pagination; + + let state = self.state.clone(); + + Box::new( + done(pagination::from_str(query.unwrap_or("")).map_err(Into::into)) + .and_then(move |pagination| match pagination { + Pagination::After(x) => Box::new( + state.query_article_revision_stubs(move |query| { + use diesel::prelude::*; + use schema::article_revisions::dsl::*; + + query + .limit(PAGE_SIZE as i64 + 1) + .filter(sequence_number.gt(x)) + .order(sequence_number.asc()) + }).and_then(|mut data| { + let extra_element = if data.len() > PAGE_SIZE as usize { + data.pop() + } else { + None + }; + + Ok(Some(match extra_element { + Some(x) => Box::new(TemporaryRedirectResource::new(format!("?before={}", x.sequence_number))) as BoxResource, + None => Box::new(TemporaryRedirectResource::new(format!("_changes"))) as BoxResource, + })) + }) + ) as Box, Error=::web::Error>>, + Pagination::Before(x) => Box::new(finished(Some(Box::new(ChangesResource::new(state, Some(x))) as BoxResource))), + Pagination::None => Box::new(finished(Some(Box::new(ChangesResource::new(state, None)) as BoxResource))), + }) + ) + } +} + pub struct ChangesResource { state: State, before: Option, } impl ChangesResource { - pub fn new(state: State, pagination: Pagination) -> Box> { - match pagination { - Pagination::After(x) => Box::new( - state.query_article_revision_stubs(move |query| { - use diesel::prelude::*; - use schema::article_revisions::dsl::*; - - query - .limit(PAGE_SIZE as i64 + 1) - .filter(sequence_number.gt(x)) - .order(sequence_number.asc()) - }).and_then(|mut data| { - let extra_element = if data.len() > PAGE_SIZE as usize { - data.pop() - } else { - None - }; - - Ok(match extra_element { - Some(x) => Box::new(TemporaryRedirectResource::new(format!("?before={}", x.sequence_number))) as BoxResource, - None => Box::new(TemporaryRedirectResource::new(format!("_changes"))) as BoxResource, - }) - }) - ), - Pagination::Before(x) => Box::new(finished(Box::new(Self { state, before: Some(x) }) as BoxResource)), - Pagination::None => Box::new(finished(Box::new(Self { state, before: None }) as BoxResource)), - } + pub fn new(state: State, before: Option) -> Self { + Self { state, before } } } diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 6a66aa1..8fdf8bd 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -9,7 +9,7 @@ mod temporary_redirect_resource; pub use self::article_redirect_resource::ArticleRedirectResource; pub use self::article_resource::ArticleResource; -pub use self::changes_resource::ChangesResource; +pub use self::changes_resource::{ChangesLookup, ChangesResource}; pub use self::new_article_resource::NewArticleResource; pub use self::sitemap_resource::SitemapResource; pub use self::temporary_redirect_resource::TemporaryRedirectResource; diff --git a/src/wiki_lookup.rs b/src/wiki_lookup.rs index 9574918..a357107 100644 --- a/src/wiki_lookup.rs +++ b/src/wiki_lookup.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::str::Utf8Error; -use futures::{Future, finished, failed, done}; +use futures::{Future, finished, failed}; use futures::future::FutureResult; use percent_encoding::percent_decode; use slug::slugify; @@ -40,7 +40,8 @@ lazy_static! { #[derive(Clone)] pub struct WikiLookup { - state: State + state: State, + changes_lookup: ChangesLookup, } fn split_one(path: &str) -> Result<(Cow, Option<&str>), Utf8Error> { @@ -70,7 +71,9 @@ fn asset_lookup(path: &str) -> FutureResult, Box<::std::erro impl WikiLookup { pub fn new(state: State) -> WikiLookup { - WikiLookup { state } + let changes_lookup = ChangesLookup::new(state.clone()); + + WikiLookup { state, changes_lookup } } fn reserved_lookup(&self, path: &str, query: Option<&str>) -> ::Future { @@ -82,14 +85,8 @@ impl WikiLookup { match (head.as_ref(), tail) { ("_assets", Some(asset)) => Box::new(asset_lookup(asset)), - ("_changes", None) => { - let state = self.state.clone(); - Box::new( - done(pagination::from_str(query.unwrap_or("")).map_err(Into::into)) - .and_then(move |pagination| ChangesResource::new(state, pagination)) - .and_then(|resource| Ok(Some(resource))) - ) - }, + ("_changes", None) => + Box::new(ChangesLookup::new(self.state.clone()).lookup(query)), ("_new", None) => Box::new(finished(Some(Box::new(NewArticleResource::new(self.state.clone(), None)) as BoxResource))), ("_sitemap", None) =>