add permanent ban support (to handle unresolvable torrent errors / todo)

This commit is contained in:
yggverse 2025-08-18 17:38:49 +03:00
parent 0332ec0788
commit e77b3bb5ad
2 changed files with 45 additions and 18 deletions

View file

@ -8,7 +8,7 @@ pub struct Item {
} }
pub struct Ban { pub struct Ban {
index: HashMap<Id20, DateTime<Local>>, index: HashMap<Id20, Option<DateTime<Local>>>,
timeout: Duration, timeout: Duration,
} }
@ -20,7 +20,7 @@ impl Ban {
} }
} }
pub fn get(&self, key: &Id20) -> Option<&DateTime<Local>> { pub fn get(&self, key: &Id20) -> Option<&Option<DateTime<Local>>> {
self.index.get(key) self.index.get(key)
} }
@ -31,8 +31,10 @@ impl Ban {
/// * return removed `Item` details /// * return removed `Item` details
pub fn update(&mut self, time: DateTime<Local>) -> Vec<Item> { pub fn update(&mut self, time: DateTime<Local>) -> Vec<Item> {
let mut b = Vec::with_capacity(self.index.len()); let mut b = Vec::with_capacity(self.index.len());
self.index.retain(|i, &mut expires| { self.index.retain(|i, &mut e| {
if time > expires { if let Some(expires) = e
&& time > expires
{
b.push(Item { b.push(Item {
expires, expires,
info_hash: i.as_string(), info_hash: i.as_string(),
@ -45,13 +47,23 @@ impl Ban {
b b
} }
/// * return expiration time /// Add torrent to the ban list
pub fn add(&mut self, key: Id20) -> DateTime<Local> { ///
let t = self /// If the `is_permanent` option is `true` - ban permanently,
.index /// or **automatically** count optimal ban time based on the current index max time and timeout offset value.
.values() ///
.max() /// * return expiration time or `None` if the ban is permanent
.map_or(Local::now(), |t| *t + self.timeout); pub fn add(&mut self, key: Id20, is_permanent: bool) -> Option<DateTime<Local>> {
let t = if is_permanent {
None
} else {
Some(
self.index
.values()
.max()
.map_or(Local::now(), |t| t.unwrap_or(Local::now()) + self.timeout),
)
};
assert!(self.index.insert(key, t).is_none()); assert!(self.index.insert(key, t).is_none());
t t
} }

View file

@ -92,7 +92,13 @@ async fn main() -> Result<()> {
continue; continue;
} }
if let Some(t) = ban.get(&i) { if let Some(t) = ban.get(&i) {
log::debug!("torrent `{h}` is banned until {t}, skip for this queue."); log::debug!(
"torrent `{h}` banned {}, skip for this queue.",
match t {
Some(v) => format!("until {v}"),
None => "permanently".into(),
}
);
continue; continue;
} }
log::debug!("index `{h}`..."); log::debug!("index `{h}`...");
@ -184,8 +190,11 @@ async fn main() -> Result<()> {
.await .await
{ {
log::info!( log::info!(
"skip awaiting the completion of preload `{h}` data (`{e}`), ban until {}.", "skip awaiting the completion of preload `{h}` data (`{e}`), ban {}.",
ban.add(i) match ban.add(i, false) {
Some(t) => format!("until {t}"),
None => "permanently".into(), // @TODO feature, do not unwrap
}
); );
session session
.delete(librqbit::api::TorrentIdOrHash::Id(id), false) .delete(librqbit::api::TorrentIdOrHash::Id(id), false)
@ -207,13 +216,19 @@ async fn main() -> Result<()> {
} }
Ok(_) => panic!(), Ok(_) => panic!(),
Err(e) => log::warn!( Err(e) => log::warn!(
"failed to resolve torrent `{h}`: `{e}`, ban until {}.", "failed to resolve torrent `{h}`: `{e}`, ban {}.",
ban.add(i) match ban.add(i, false) {
Some(t) => format!("until {t}"),
None => "permanently".into(), // @TODO feature, do not unwrap
}
), ),
}, },
Err(e) => log::info!( Err(e) => log::info!(
"skip awaiting the completion of adding torrent `{h}` data (`{e}`), ban until {}.", "skip awaiting the completion of adding torrent `{h}` data (`{e}`), ban {}.",
ban.add(i) match ban.add(i, false) {
Some(t) => format!("until {t}"),
None => "permanently".into(), // @TODO feature, do not unwrap
}
), ),
} }
} }