Allow DirStatus objects to have different timeout floors

This will help when we give Guards a DirStatus as well.
This commit is contained in:
Nick Mathewson 2022-04-04 10:33:26 -04:00
parent 57608f9609
commit 52c7a0e26a
2 changed files with 24 additions and 21 deletions

View File

@ -19,21 +19,16 @@ pub(crate) struct DirStatus {
retry_at: Option<Instant>,
}
/// Least amount of time we'll wait before retrying a fallback cache.
//
// TODO: we may want to make this configurable to a smaller value for chutney networks.
const FALLBACK_RETRY_FLOOR: Duration = Duration::from_secs(150);
impl Default for DirStatus {
fn default() -> Self {
impl DirStatus {
/// Construct a new DirStatus object with a given lower-bound for delays
/// after failure.
pub(crate) fn new(delay_floor: Duration) -> Self {
DirStatus {
delay: RetryDelay::from_duration(FALLBACK_RETRY_FLOOR),
delay: RetryDelay::from_duration(delay_floor),
retry_at: None,
}
}
}
impl DirStatus {
/// Return true if this `Status` is usable at the time `now`.
pub(crate) fn usable_at(&self, now: Instant) -> bool {
match self.retry_at {
@ -56,7 +51,7 @@ impl DirStatus {
/// directory.
pub(crate) fn note_success(&mut self) {
self.retry_at = None;
self.delay = RetryDelay::from_duration(FALLBACK_RETRY_FLOOR);
self.delay.reset();
}
/// Record that the associated fallback directory has failed.
@ -75,28 +70,31 @@ mod test {
fn status_basics() {
let now = Instant::now();
let mut status = DirStatus::default();
/// floor to use for testing.
const FLOOR: Duration = Duration::from_secs(99);
let mut status = DirStatus::new(FLOOR);
// newly created status is usable.
assert!(status.usable_at(now));
// no longer usable after a failure.
status.note_failure(now);
assert_eq!(status.next_retriable().unwrap(), now + FALLBACK_RETRY_FLOOR);
assert_eq!(status.next_retriable().unwrap(), now + FLOOR);
assert!(!status.usable_at(now));
// Not enough time has passed.
assert!(!status.usable_at(now + FALLBACK_RETRY_FLOOR / 2));
assert!(!status.usable_at(now + FLOOR / 2));
// Enough time has passed.
assert!(status.usable_at(now + FALLBACK_RETRY_FLOOR));
assert!(status.usable_at(now + FLOOR));
// Mark as failed again; the timeout will (probably) be longer.
status.note_failure(now + FALLBACK_RETRY_FLOOR);
assert!(status.next_retriable().unwrap() >= now + FALLBACK_RETRY_FLOOR * 2);
assert!(!status.usable_at(now + FALLBACK_RETRY_FLOOR));
status.note_failure(now + FLOOR);
assert!(status.next_retriable().unwrap() >= now + FLOOR * 2);
assert!(!status.usable_at(now + FLOOR));
// Mark as succeeded; it should be usable immediately.
status.note_success();
assert!(status.usable_at(now + FALLBACK_RETRY_FLOOR));
assert!(status.usable_at(now + FLOOR));
}
}

View File

@ -1,7 +1,7 @@
//! Declare the [`FallbackState`] type, which is used to store a set of FallbackDir.
use rand::seq::IteratorRandom;
use std::time::Instant;
use std::time::{Duration, Instant};
use super::{DirStatus, FallbackDir};
use crate::{ids::FallbackId, PickGuardError};
@ -70,10 +70,15 @@ pub(super) struct Entry {
pub(super) status: DirStatus,
}
/// Least amount of time we'll wait before retrying a fallback cache.
//
// TODO: we may want to make this configurable to a smaller value for chutney networks.
const FALLBACK_RETRY_FLOOR: Duration = Duration::from_secs(150);
impl From<FallbackDir> for Entry {
fn from(fallback: FallbackDir) -> Self {
let fallback = fallback.as_guard();
let status = DirStatus::default();
let status = DirStatus::new(FALLBACK_RETRY_FLOOR);
Entry { fallback, status }
}
}