deal with not-modified responses

This commit is contained in:
Robin Appelman 2024-12-26 01:16:44 +01:00
commit c325eaba62
4 changed files with 33 additions and 15 deletions

View file

@ -4,6 +4,7 @@ version = "0.2.0"
authors = ["Robin Appelman <robin@icewind.nl>"]
edition = "2018"
rust-version = "1.71.1"
repository = "https://github.com/icewind1991/rss-webhook-trigger"
license = "MIT"
[dependencies]

View file

@ -84,8 +84,8 @@ pub struct FetchPlan {
}
impl FetchPlan {
pub fn elapsed(&self) -> bool {
Instant::now() > self.time
pub fn is_elapsed(&self) -> bool {
Instant::now() >= self.time
}
}

View file

@ -1,6 +1,6 @@
use crate::error::HubError;
use crate::fetcher::{CacheHeaders, FetchResponse};
use reqwest::Client;
use reqwest::{Client, StatusCode};
use reqwest::header::{HeaderValue, USER_AGENT};
use serde::Deserialize;
use time::OffsetDateTime;
@ -15,10 +15,10 @@ pub async fn tags(
cache_headers: &CacheHeaders,
) -> FetchResponse<Vec<HubTag>, HubError> {
let result = client
.get(format!(
.get(dbg!(format!(
"https://hub.docker.com/v2/repositories/{}/{}/tags",
user, repo
))
)))
.headers(cache_headers.headers())
.header(USER_AGENT, HeaderValue::from_static(FETCHER_USER_AGENT))
.send()
@ -28,6 +28,9 @@ pub async fn tags(
.map_err(HubError::Network)
.check_status_code(HubError::ClientError, HubError::ServerError)
.map(|response| async {
if response.status() == StatusCode::NOT_MODIFIED {
return Ok(Vec::new());
}
response
.text()
.await

View file

@ -7,7 +7,7 @@ use crate::config::{Config, FeedConfig};
use crate::error::{FetchError, FetchFeedError, HubError, ParseFeedError};
use crate::fetcher::{next_fetch, CacheHeaders, FetchPlan, FetchResponse};
use main_error::MainResult;
use reqwest::{Client, Response};
use reqwest::{Client, Response, StatusCode};
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::future::ready;
@ -106,7 +106,10 @@ impl FeedFetcher {
}
pub fn should_update(&self, feed: &str) -> bool {
self.fetch_plans.get(feed).filter(|plan| FetchPlan::elapsed(plan)).is_some()
match self.fetch_plans.get(feed) {
Some(plan) => plan.is_elapsed(),
None => true,
}
}
#[instrument(skip(self))]
@ -130,7 +133,7 @@ impl FeedFetcher {
};
Ok(match (self.cache.get_mut(feed), new_key) {
(Some(cached), Some(new_key)) => {
(Some(cached), Some(Some(new_key))) => {
debug!(cached, new_key, "checked existing feed");
if new_key != *cached {
*cached = new_key;
@ -139,13 +142,17 @@ impl FeedFetcher {
false
}
}
(None, Some(new_key)) => {
(None, Some(Some(new_key))) => {
debug!(feed, "new feed");
self.cache.insert(feed.into(), new_key);
// don't trigger the actions on start
false
}
(_, Some(None)) => {
debug!("not modified response");
false
}
(_, None) => {
warn!("rate limited by server");
false
@ -158,18 +165,21 @@ impl FeedFetcher {
&self,
feed: &str,
cache_headers: &CacheHeaders,
) -> FetchResponse<u64, FetchError> {
) -> FetchResponse<Option<u64>, FetchError> {
if let Some(hub) = feed.strip_prefix("docker-hub://") {
if let Some((user, repo)) = hub.split_once('/') {
hub::tags(&self.client, user, repo, cache_headers)
.await
.map(|tags| {
if tags.is_empty() {
return ready(None);
}
let mut hasher = DefaultHasher::new();
for tag in tags {
tag.id.hash(&mut hasher);
tag.last_updated.hash(&mut hasher);
}
ready(hasher.finish())
ready(Some(hasher.finish()))
}).await
.map_err(FetchError::Hub)
} else {
@ -190,7 +200,7 @@ impl FeedFetcher {
&self,
feed: &str,
cache_headers: &CacheHeaders,
) -> FetchResponse<u64, FetchFeedError> {
) -> FetchResponse<Option<u64>, FetchFeedError> {
let response = self
.client
.get(feed)
@ -209,7 +219,11 @@ impl FeedFetcher {
}
}
async fn parse_rss_response(response: Response) -> Result<u64, FetchFeedError> {
async fn parse_rss_response(response: Response) -> Result<Option<u64>, FetchFeedError> {
if response.status() == StatusCode::NOT_MODIFIED {
return Ok(None);
}
let content = response.text().await?;
let channel = Feed::from_str(&content).map_err(ParseFeedError::Parse)?;
@ -235,5 +249,5 @@ async fn parse_rss_response(response: Response) -> Result<u64, FetchFeedError> {
}
}
Ok(hasher.finish())
Ok(Some(hasher.finish()))
}