M Cargo.lock => Cargo.lock +1 -1
@@ 1964,7 1964,7 @@ dependencies = [
[[package]]
name = "russet"
-version = "0.12.1"
+version = "0.12.2"
dependencies = [
"argon2",
"atom_syndication",
M Cargo.toml => Cargo.toml +1 -1
@@ 1,6 1,6 @@
[package]
name = "russet"
-version = "0.12.1"
+version = "0.12.2"
edition = "2021"
license = "AGPL-3.0"
M src/domain/feeds.rs => src/domain/feeds.rs +31 -8
@@ 1,23 1,23 @@
use crate::domain::model::Feed;
use crate::domain::RussetDomainService;
-use crate::Result;
+use crate::{ Err, Result };
use crate::model::{ EntryId, FeedId, UserId };
use crate::persistence::model::{ Entry, Feed as PersistenceFeed };
use crate::persistence::{ RussetEntryPersistenceLayer, RussetFeedPersistenceLayer };
use crate::feed::model::Feed as ReaderFeed;
use reqwest::Url;
use std::collections::HashSet;
+use std::error::Error;
+use std::fmt::Display;
use ulid::Ulid;
impl <Persistence> RussetDomainService<Persistence>
where Persistence: RussetEntryPersistenceLayer + RussetFeedPersistenceLayer {
/// Update the stored entries for all feeds known to the persistence layer
- ///
- /// TODO: There could be multiple errors, and this will swallow all but one
- /// of them.
- pub async fn update_feeds(&self) -> Result<()> {
- let fetch_index = self.persistence.get_and_increment_fetch_index().await?;
+ pub async fn update_feeds(&self) -> std::result::Result<(), Vec<Err>> {
+ let fetch_index = self.persistence.get_and_increment_fetch_index().await
+ .map_err(|err| vec![err])?;
let feeds = self.persistence
.get_feeds()
.await
@@ 27,10 27,33 @@ where Persistence: RussetEntryPersistenceLayer + RussetFeedPersistenceLayer {
let mut errors = vec![];
for feed in feeds {
if let Err(e) = self.update_feed(&feed, fetch_index).await {
- errors.push(Err(e))
+ #[derive(Debug)]
+ struct FeedUpdateError {
+ description: String,
+ source: Err,
+ }
+ impl Display for FeedUpdateError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str(self.description.as_str())
+ }
+ }
+ impl Error for FeedUpdateError {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ Some(self.source.as_ref())
+ }
+ }
+
+ errors.push(Box::new(FeedUpdateError {
+ description: format!("Error updating feed {} ({:?})", feed.title, feed.id),
+ source: e,
+ } ).into() )
}
}
- errors.into_iter().next().unwrap_or(Ok(()))
+ if errors.is_empty() {
+ Ok(())
+ } else {
+ Err(errors)
+ }
}
/// Given a URL, ensure the feed is stored in the persistence layer.
M src/server.rs => src/server.rs +4 -2
@@ 23,8 23,10 @@ where Persistence: RussetPersistenceLayer {
tokio::spawn(async move {
loop {
info!("Updating feeds");
- if let Err(e) = update_service.update_feeds().await {
- error!(error = e.as_ref(), "Error updating feeds");
+ if let Err(errs) = update_service.update_feeds().await {
+ for err in errs {
+ error!(error = err);
+ }
}
tokio::time::sleep(check_interval).await;
}