From d5adbb1383daff414c1e6479608a66d5ca5a5dc8 Mon Sep 17 00:00:00 2001 From: Bob Gardner Date: Mon, 9 Mar 2020 23:47:47 -0400 Subject: [PATCH] Fix pagination, add retry --- app/pocket_cleaner/src/lib.rs | 7 +++-- app/pocket_cleaner/src/pocket.rs | 47 ++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/app/pocket_cleaner/src/lib.rs b/app/pocket_cleaner/src/lib.rs index 4e49033..22d3ee9 100644 --- a/app/pocket_cleaner/src/lib.rs +++ b/app/pocket_cleaner/src/lib.rs @@ -18,7 +18,7 @@ pub mod pocket; pub mod trends; pub mod view; -const ITEMS_PER_PAGE: i32 = 500; +const ITEMS_PER_PAGE: u32 = 100; pub struct SavedItemMediator<'a> { pocket: &'a UserPocketManager, @@ -64,8 +64,9 @@ impl<'a> SavedItemMediator<'a> { .collect(); self.saved_item_store.upsert_items(&store_items)?; log::debug!("Synced {} items to DB (page {})", store_items.len(), page); - offset += store_items.len() as i32; - if store_items.is_empty() { + let num_stored_items = store_items.len() as u32; + offset += num_stored_items; + if num_stored_items < ITEMS_PER_PAGE { break since; } }; diff --git a/app/pocket_cleaner/src/pocket.rs b/app/pocket_cleaner/src/pocket.rs index f5b7e3a..382dbe6 100644 --- a/app/pocket_cleaner/src/pocket.rs +++ b/app/pocket_cleaner/src/pocket.rs @@ -62,16 +62,14 @@ impl UserPocketManager { PocketRetrieveItemList::Map(items) => { Ok(items.values().cloned().map(PocketItem::from).collect()) } - PocketRetrieveItemList::List(_) => Err(PocketCleanerError::Unknown( - "Invalid response from Pocket: received list instead of object".into(), - )), + PocketRetrieveItemList::List(_) => Ok(Vec::new()), } } pub async fn get_items_paginated( &self, - count: i32, - offset: i32, + count: u32, + offset: u32, since: Option, ) -> Result { let client = Client::default(); @@ -90,11 +88,7 @@ impl UserPocketManager { .cloned() .map(PocketItem::from) .collect::>(), - PocketRetrieveItemList::List(_) => { - return Err(PocketCleanerError::Unknown( - "Invalid response from Pocket: received list instead of object".into(), - )) - } + PocketRetrieveItemList::List(_) => Vec::new(), }; Ok(PocketPage { items, @@ -139,8 +133,8 @@ struct PocketRetrieveItemRequest { user_access_token: String, search: Option, since: Option, - count: Option, - offset: Option, + count: Option, + offset: Option, } #[derive(Deserialize, PartialEq, Eq, Hash, Clone, Debug)] @@ -201,11 +195,30 @@ async fn send_pocket_retrieve_request( req: &PocketRetrieveItemRequest, ) -> Result { let url = build_pocket_retrieve_url(req)?; - let mut response = client - .get(url) - .send() - .await - .map_err(|e| PocketCleanerError::Unknown(e.to_string()))?; + + let mut num_attempts = 0; + let mut response = loop { + if num_attempts == 3 { + return Err(PocketCleanerError::Unknown(format!( + "failed to connect to or receive a response from Pocket after {} attempts", + num_attempts + ))); + } + let response = client.get(&url).send().await; + num_attempts += 1; + match response { + Ok(resp) => break resp, + Err(actix_web::client::SendRequestError::Connect(_)) + | Err(actix_web::client::SendRequestError::Timeout) => continue, + Err(e) => { + return Err(PocketCleanerError::Unknown(format!( + "failed to send 'pocket retrieve' request: {}", + e + ))) + } + } + }; + let body = response .body() .await