mirror of
https://codeberg.org/icewind/rss-webhook-trigger.git
synced 2026-06-03 18:04:09 +02:00
deal with not-modified responses
This commit is contained in:
parent
f8b59df362
commit
c325eaba62
4 changed files with 33 additions and 15 deletions
|
|
@ -4,6 +4,7 @@ version = "0.2.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
rust-version = "1.71.1"
|
rust-version = "1.71.1"
|
||||||
|
repository = "https://github.com/icewind1991/rss-webhook-trigger"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@ pub struct FetchPlan {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchPlan {
|
impl FetchPlan {
|
||||||
pub fn elapsed(&self) -> bool {
|
pub fn is_elapsed(&self) -> bool {
|
||||||
Instant::now() > self.time
|
Instant::now() >= self.time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::HubError;
|
use crate::error::HubError;
|
||||||
use crate::fetcher::{CacheHeaders, FetchResponse};
|
use crate::fetcher::{CacheHeaders, FetchResponse};
|
||||||
use reqwest::Client;
|
use reqwest::{Client, StatusCode};
|
||||||
use reqwest::header::{HeaderValue, USER_AGENT};
|
use reqwest::header::{HeaderValue, USER_AGENT};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
@ -15,10 +15,10 @@ pub async fn tags(
|
||||||
cache_headers: &CacheHeaders,
|
cache_headers: &CacheHeaders,
|
||||||
) -> FetchResponse<Vec<HubTag>, HubError> {
|
) -> FetchResponse<Vec<HubTag>, HubError> {
|
||||||
let result = client
|
let result = client
|
||||||
.get(format!(
|
.get(dbg!(format!(
|
||||||
"https://hub.docker.com/v2/repositories/{}/{}/tags",
|
"https://hub.docker.com/v2/repositories/{}/{}/tags",
|
||||||
user, repo
|
user, repo
|
||||||
))
|
)))
|
||||||
.headers(cache_headers.headers())
|
.headers(cache_headers.headers())
|
||||||
.header(USER_AGENT, HeaderValue::from_static(FETCHER_USER_AGENT))
|
.header(USER_AGENT, HeaderValue::from_static(FETCHER_USER_AGENT))
|
||||||
.send()
|
.send()
|
||||||
|
|
@ -28,6 +28,9 @@ pub async fn tags(
|
||||||
.map_err(HubError::Network)
|
.map_err(HubError::Network)
|
||||||
.check_status_code(HubError::ClientError, HubError::ServerError)
|
.check_status_code(HubError::ClientError, HubError::ServerError)
|
||||||
.map(|response| async {
|
.map(|response| async {
|
||||||
|
if response.status() == StatusCode::NOT_MODIFIED {
|
||||||
|
return Ok(Vec::new());
|
||||||
|
}
|
||||||
response
|
response
|
||||||
.text()
|
.text()
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
34
src/main.rs
34
src/main.rs
|
|
@ -7,7 +7,7 @@ use crate::config::{Config, FeedConfig};
|
||||||
use crate::error::{FetchError, FetchFeedError, HubError, ParseFeedError};
|
use crate::error::{FetchError, FetchFeedError, HubError, ParseFeedError};
|
||||||
use crate::fetcher::{next_fetch, CacheHeaders, FetchPlan, FetchResponse};
|
use crate::fetcher::{next_fetch, CacheHeaders, FetchPlan, FetchResponse};
|
||||||
use main_error::MainResult;
|
use main_error::MainResult;
|
||||||
use reqwest::{Client, Response};
|
use reqwest::{Client, Response, StatusCode};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::future::ready;
|
use std::future::ready;
|
||||||
|
|
@ -21,7 +21,7 @@ use tokio::signal::ctrl_c;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use tracing::{debug, error, info, instrument, warn};
|
use tracing::{debug, error, info, instrument, warn};
|
||||||
|
|
||||||
const FETCHER_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"), "(", env!("CARGO_PKG_REPOSITORY"), ")");
|
const FETCHER_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"), " (", env!("CARGO_PKG_REPOSITORY"), ")");
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> MainResult {
|
async fn main() -> MainResult {
|
||||||
|
|
@ -106,7 +106,10 @@ impl FeedFetcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn should_update(&self, feed: &str) -> bool {
|
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))]
|
#[instrument(skip(self))]
|
||||||
|
|
@ -130,7 +133,7 @@ impl FeedFetcher {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(match (self.cache.get_mut(feed), new_key) {
|
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");
|
debug!(cached, new_key, "checked existing feed");
|
||||||
if new_key != *cached {
|
if new_key != *cached {
|
||||||
*cached = new_key;
|
*cached = new_key;
|
||||||
|
|
@ -139,13 +142,17 @@ impl FeedFetcher {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(None, Some(new_key)) => {
|
(None, Some(Some(new_key))) => {
|
||||||
debug!(feed, "new feed");
|
debug!(feed, "new feed");
|
||||||
self.cache.insert(feed.into(), new_key);
|
self.cache.insert(feed.into(), new_key);
|
||||||
|
|
||||||
// don't trigger the actions on start
|
// don't trigger the actions on start
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
(_, Some(None)) => {
|
||||||
|
debug!("not modified response");
|
||||||
|
false
|
||||||
|
}
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
warn!("rate limited by server");
|
warn!("rate limited by server");
|
||||||
false
|
false
|
||||||
|
|
@ -158,18 +165,21 @@ impl FeedFetcher {
|
||||||
&self,
|
&self,
|
||||||
feed: &str,
|
feed: &str,
|
||||||
cache_headers: &CacheHeaders,
|
cache_headers: &CacheHeaders,
|
||||||
) -> FetchResponse<u64, FetchError> {
|
) -> FetchResponse<Option<u64>, FetchError> {
|
||||||
if let Some(hub) = feed.strip_prefix("docker-hub://") {
|
if let Some(hub) = feed.strip_prefix("docker-hub://") {
|
||||||
if let Some((user, repo)) = hub.split_once('/') {
|
if let Some((user, repo)) = hub.split_once('/') {
|
||||||
hub::tags(&self.client, user, repo, cache_headers)
|
hub::tags(&self.client, user, repo, cache_headers)
|
||||||
.await
|
.await
|
||||||
.map(|tags| {
|
.map(|tags| {
|
||||||
|
if tags.is_empty() {
|
||||||
|
return ready(None);
|
||||||
|
}
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
tag.id.hash(&mut hasher);
|
tag.id.hash(&mut hasher);
|
||||||
tag.last_updated.hash(&mut hasher);
|
tag.last_updated.hash(&mut hasher);
|
||||||
}
|
}
|
||||||
ready(hasher.finish())
|
ready(Some(hasher.finish()))
|
||||||
}).await
|
}).await
|
||||||
.map_err(FetchError::Hub)
|
.map_err(FetchError::Hub)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -190,7 +200,7 @@ impl FeedFetcher {
|
||||||
&self,
|
&self,
|
||||||
feed: &str,
|
feed: &str,
|
||||||
cache_headers: &CacheHeaders,
|
cache_headers: &CacheHeaders,
|
||||||
) -> FetchResponse<u64, FetchFeedError> {
|
) -> FetchResponse<Option<u64>, FetchFeedError> {
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.get(feed)
|
.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 content = response.text().await?;
|
||||||
let channel = Feed::from_str(&content).map_err(ParseFeedError::Parse)?;
|
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()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue