From adcc342c9c1674ce88ebaf7f9359bde9665ca3f8 Mon Sep 17 00:00:00 2001 From: David Blajda Date: Wed, 26 Dec 2018 06:17:23 +0000 Subject: :WIP: Allow iteration over endpoints that provide pagination --- src/helix/mod.rs | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/helix/mod.rs b/src/helix/mod.rs index 5c51c22..5daa498 100644 --- a/src/helix/mod.rs +++ b/src/helix/mod.rs @@ -356,7 +356,8 @@ struct RequestRef { } enum RequestState { - Uninitalized, + SetupRequest, + SetupBarriers, WaitAuth(WaiterState), SetupRatelimit, WaitLimit(WaiterState), @@ -369,6 +370,19 @@ pub struct ApiRequest { state: RequestState, attempt: u32, max_attempts: u32, + pagination: Option, +} + +enum IterableApiRequestState { + Start, + PollInner(ApiRequest), + Finished, +} + +pub struct IterableApiRequest { + inner: Arc, + pagination: Option, + state: IterableApiRequestState, } use self::models::PaginationTrait; @@ -394,9 +408,10 @@ impl ApiRequest { method: method, ratelimit: ratelimit, }), - state: RequestState::Uninitalized, + state: RequestState::SetupRequest, attempt: 0, max_attempts: 1, + pagination: None, } } } @@ -492,7 +507,7 @@ use crate::sync::waiter::Waiter; struct WaiterState { polling: bool, - shared_future: Option<(Shared + Send>>)>, + shared_future: Option<(Shared + Send>>)>, waiter: W, barrier: Barrier, } @@ -552,7 +567,7 @@ impl Waiter for AuthWaiter { fn condition(&self) -> Shared + Send>> { - /* If a secret is not provided than just immediately return */ + /* If a secret is not provided then just immediately return */ let secret = self.waiter.secret().unwrap(); let bottom_client = self.waiter.get_bottom_client(); let client = self.waiter.clone(); @@ -613,7 +628,7 @@ macro_rules! retry_ready { Err(e) => { if $s.attempt < $s.max_attempts { $s.attempt += 1; - $s.state = RequestState::Uninitalized; + $s.state = RequestState::SetupBarriers; continue; } else { return Err(e.into()); @@ -622,6 +637,79 @@ macro_rules! retry_ready { }) } +use futures::Stream; + +/* +impl Future for ApiRequest { + type Item = ::Item; + type Error = ::Error; + + fn poll(&mut self) -> Poll { + let stream = self as &mut Stream; + let state = stream.poll(); + + match state { + Err(err) => Err(err), + Ok(maybe_ready) => { + match maybe_ready { + Async::NotReady => Ok(Async::NotReady), + Async::Ready(item) => { + match item { + Some(result) => Ok(Async::Ready(result)), + None => panic!("Request future returned None for first result!") + } + } + } + } + } + } +} +*/ +impl Stream for IterableApiRequest { + type Item = T; + type Error = Error; + + fn poll(&mut self) -> Poll, Self::Error> { + loop { + match &mut self.state { + IterableApiRequestState::Start => { + self.state = + IterableApiRequestState::PollInner( + ApiRequest { + inner: self.inner.clone(), + state: RequestState::SetupRequest, + attempt: 0, + max_attempts: 1, + pagination: None + }); + }, + IterableApiRequestState::PollInner(request) => { + let f = request as &mut Future; + match f.poll() { + Err(err) => { + self.state = IterableApiRequestState::Finished; + return Err(err); + }, + Ok(state) => { + match state { + Async::NotReady => return Ok(Async::NotReady), + Async::Ready(res) => { + //TODO check pagination + self.state = IterableApiRequestState::Finished; + return Ok(Async::Ready(Some(res))); + } + } + } + } + }, + IterableApiRequestState::Finished => { + return Ok(Async::Ready(None)); + } + } + } + } +} + impl Future for ApiRequest { type Item = T; type Error = Error; @@ -629,7 +717,11 @@ impl Future for ApiRequest { fn poll(&mut self) -> Poll { loop { match &mut self.state { - RequestState::Uninitalized => { + RequestState::SetupRequest => { + self.attempt = 0; + self.state = RequestState::SetupBarriers; + } + RequestState::SetupBarriers => { match self.inner.client.inner.as_ref() { ClientType::Auth(inner) => { let waiter = AuthWaiter { @@ -729,7 +821,7 @@ impl Future for ApiRequest { RequestState::PollParse(future) => { let res = retry_ready!(self, future.poll()); return Ok(Async::Ready(res)); - } + }, } } } -- cgit v1.2.3