use std::collections::HashMap;
use nym_credentials_interface::TicketType;
use crate::{
error::BandwidthControllerError, requests::ReturnSender, traits::CredentialFetcherError,
};
#[derive(Clone, Debug)]
pub(crate) enum ReadinessStatus {
Ready,
InFlight,
Unavailable,
FetchFailed(String),
}
impl ReadinessStatus {
fn severity(&self) -> u8 {
match self {
ReadinessStatus::Ready => 0,
ReadinessStatus::InFlight => 1,
ReadinessStatus::Unavailable => 2,
ReadinessStatus::FetchFailed(_) => 3,
}
}
}
#[derive(Debug)]
pub(crate) struct FetchFailure {
pub(crate) ticket_type: TicketType,
pub(crate) error: CredentialFetcherError,
}
#[derive(Debug)]
pub(crate) struct ReadinessSnapshot {
pub(crate) upgrade_mode: bool,
pub(crate) tickets_readiness: HashMap<TicketType, ReadinessStatus>,
}
impl ReadinessSnapshot {
fn evaluate_readiness(&self, required: &[TicketType]) -> ReadinessStatus {
if self.upgrade_mode {
return ReadinessStatus::Ready;
}
required
.iter()
.map(|typ| {
self.tickets_readiness
.get(typ)
.cloned()
.unwrap_or(ReadinessStatus::Unavailable)
})
.max_by_key(|status| status.severity())
.unwrap_or(ReadinessStatus::Ready)
}
}
#[derive(Debug)]
pub(crate) struct ReadinessRequest {
pub(crate) return_sender: ReturnSender<()>,
pub(crate) ticket_types: Vec<TicketType>,
}
impl ReadinessRequest {
pub(crate) fn try_resolve(self, readiness_snapshot: &ReadinessSnapshot) -> Option<Self> {
match readiness_snapshot.evaluate_readiness(&self.ticket_types) {
ReadinessStatus::Ready => {
self.return_sender.send(Ok(()));
None
}
ReadinessStatus::InFlight => Some(self),
ReadinessStatus::Unavailable => {
self.return_sender
.send(Err(BandwidthControllerError::TicketbooksUnavailable));
None
}
ReadinessStatus::FetchFailed(reason) => {
self.return_sender
.send(Err(BandwidthControllerError::TicketbookFetchFailed {
reason,
}));
None
}
}
}
pub(crate) fn cancel(self) {
self.return_sender
.send(Err(BandwidthControllerError::TicketbooksUnavailable));
}
}