Skip to main content

nym_bandwidth_controller/requests/
mod.rs

1// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    error::BandwidthControllerError, ticketbooks::AvailableTicketbooks, traits::CredentialFetcher,
6    CredentialPublicDataFetcher, EcashTicketRequest, PreparedCredential,
7    PreparedCredentialMetadata,
8};
9use nym_credentials_interface::TicketType;
10use std::sync::Arc;
11
12pub use sender::BandwidthControllerRequestSender;
13use tokio::sync::oneshot;
14
15mod sender;
16
17#[derive(strum::Display)]
18pub enum BandwidthControllerRequest {
19    EcashTicket(ReturnSender<Option<PreparedCredential>>, EcashTicketRequest),
20
21    UpgradeModeToken(ReturnSender<Option<String>>),
22
23    AttemptRevertSpending(ReturnSender<bool>, PreparedCredentialMetadata),
24
25    /// Sets (or clears, with `None`) the credential fetcher; a new one triggers an immediate restock.
26    SetCredentialFetcher(ReturnSender<()>, Option<Arc<dyn CredentialFetcher>>),
27    /// Sets (or clears, with `None`) the global-data fetcher.
28    SetPublicDataFetcher(
29        ReturnSender<()>,
30        Option<Arc<dyn CredentialPublicDataFetcher>>,
31    ),
32    /// Cancels in-flight fetches, drops the fetcher, clears all stored credentials, and fails every
33    /// parked readiness waiter.
34    Reset(ReturnSender<()>),
35    /// Removes the stored emergency (upgrade-mode) credentials only, leaving ticketbooks intact.
36    ClearEmergencyCredentials(ReturnSender<()>),
37    /// Returns the currently stored ticketbooks (also logs a stock summary).
38    GetAvailableTicketbooks(ReturnSender<AvailableTicketbooks>),
39
40    /// Checks the given ticket types and kicks off a background restock for any running low or
41    /// about to expire. Resolves once the check has been scheduled, not once the fetches finish.
42    ///
43    /// Not to be used lightly: the automatic triggers (ticket handout, timer, fetcher install)
44    /// already keep every type stocked. This is a manual safety valve, not a routine call.
45    RestockTicketbooks(ReturnSender<()>, Vec<TicketType>),
46
47    /// Resolves once every required ticket type is usable (stocked or covered by upgrade mode),
48    /// or fails if a required type is neither stocked nor being fetched.
49    WaitForTicketbooks(ReturnSender<()>, Vec<TicketType>),
50}
51
52#[derive(Debug)]
53pub struct ReturnSender<T> {
54    sender: oneshot::Sender<Result<T, BandwidthControllerError>>,
55}
56
57impl<T> ReturnSender<T>
58where
59    T: std::fmt::Debug,
60{
61    pub fn new() -> (Self, oneshot::Receiver<Result<T, BandwidthControllerError>>) {
62        let (sender, receiver) = oneshot::channel();
63        (Self { sender }, receiver)
64    }
65
66    pub fn send(self, response: Result<T, BandwidthControllerError>)
67    where
68        T: Send,
69    {
70        self.sender
71            .send(response)
72            .inspect_err(|_| {
73                tracing::warn!("Failed to send response, receiver is gone already");
74            })
75            .ok();
76    }
77}