Commit 52c7a0e2 authored by Nick Mathewson's avatar Nick Mathewson 🦞
Browse files

Allow DirStatus objects to have different timeout floors

This will help when we give Guards a DirStatus as well.
parent 57608f96
Loading
Loading
Loading
Loading
+17 −19
Original line number Original line Diff line number Diff line
@@ -19,21 +19,16 @@ pub(crate) struct DirStatus {
    retry_at: Option<Instant>,
    retry_at: Option<Instant>,
}
}


/// Least amount of time we'll wait before retrying a fallback cache.
impl DirStatus {
//
    /// Construct a new DirStatus object with a given lower-bound for delays
// TODO: we may want to make this configurable to a smaller value for chutney networks.
    /// after failure.
const FALLBACK_RETRY_FLOOR: Duration = Duration::from_secs(150);
    pub(crate) fn new(delay_floor: Duration) -> Self {

impl Default for DirStatus {
    fn default() -> Self {
        DirStatus {
        DirStatus {
            delay: RetryDelay::from_duration(FALLBACK_RETRY_FLOOR),
            delay: RetryDelay::from_duration(delay_floor),
            retry_at: None,
            retry_at: None,
        }
        }
    }
    }
}


impl DirStatus {
    /// Return true if this `Status` is usable at the time `now`.
    /// Return true if this `Status` is usable at the time `now`.
    pub(crate) fn usable_at(&self, now: Instant) -> bool {
    pub(crate) fn usable_at(&self, now: Instant) -> bool {
        match self.retry_at {
        match self.retry_at {
@@ -56,7 +51,7 @@ impl DirStatus {
    /// directory.
    /// directory.
    pub(crate) fn note_success(&mut self) {
    pub(crate) fn note_success(&mut self) {
        self.retry_at = None;
        self.retry_at = None;
        self.delay = RetryDelay::from_duration(FALLBACK_RETRY_FLOOR);
        self.delay.reset();
    }
    }


    /// Record that the associated fallback directory has failed.
    /// Record that the associated fallback directory has failed.
@@ -75,28 +70,31 @@ mod test {
    fn status_basics() {
    fn status_basics() {
        let now = Instant::now();
        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.
        // newly created status is usable.
        assert!(status.usable_at(now));
        assert!(status.usable_at(now));


        // no longer usable after a failure.
        // no longer usable after a failure.
        status.note_failure(now);
        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));
        assert!(!status.usable_at(now));


        // Not enough time has passed.
        // 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.
        // 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.
        // Mark as failed again; the timeout will (probably) be longer.
        status.note_failure(now + FALLBACK_RETRY_FLOOR);
        status.note_failure(now + FLOOR);
        assert!(status.next_retriable().unwrap() >= now + FALLBACK_RETRY_FLOOR * 2);
        assert!(status.next_retriable().unwrap() >= now + FLOOR * 2);
        assert!(!status.usable_at(now + FALLBACK_RETRY_FLOOR));
        assert!(!status.usable_at(now + FLOOR));


        // Mark as succeeded; it should be usable immediately.
        // Mark as succeeded; it should be usable immediately.
        status.note_success();
        status.note_success();
        assert!(status.usable_at(now + FALLBACK_RETRY_FLOOR));
        assert!(status.usable_at(now + FLOOR));
    }
    }
}
}
+7 −2
Original line number Original line Diff line number Diff line
//! Declare the [`FallbackState`] type, which is used to store a set of FallbackDir.
//! Declare the [`FallbackState`] type, which is used to store a set of FallbackDir.


use rand::seq::IteratorRandom;
use rand::seq::IteratorRandom;
use std::time::Instant;
use std::time::{Duration, Instant};


use super::{DirStatus, FallbackDir};
use super::{DirStatus, FallbackDir};
use crate::{ids::FallbackId, PickGuardError};
use crate::{ids::FallbackId, PickGuardError};
@@ -70,10 +70,15 @@ pub(super) struct Entry {
    pub(super) status: DirStatus,
    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 {
impl From<FallbackDir> for Entry {
    fn from(fallback: FallbackDir) -> Self {
    fn from(fallback: FallbackDir) -> Self {
        let fallback = fallback.as_guard();
        let fallback = fallback.as_guard();
        let status = DirStatus::default();
        let status = DirStatus::new(FALLBACK_RETRY_FLOOR);
        Entry { fallback, status }
        Entry { fallback, status }
    }
    }
}
}