Skip to main content

TokenManager

Struct TokenManager 

Source
pub struct TokenManager {
    pub token_data: Arc<Mutex<Option<TokenData>>>,
    pub retry_client: RetryClient,
    /* private fields */
}
Expand description

Core token manager with proactive refresh and secure storage

Fields§

§token_data: Arc<Mutex<Option<TokenData>>>§retry_client: RetryClient

Implementations§

Source§

impl TokenManager

Source

pub async fn get_global_instance() -> Result<Arc<Self>, Error>

Gets the global singleton instance of TokenManager

This ensures all ApiClient instances share the same token storage, preventing multiple token acquisition attempts in concurrent tests.

§Errors

Returns an error if the TokenManager cannot be initialized

Source

pub async fn new() -> Result<Self, Error>

Creates a new TokenManager with default configuration

§Errors

Returns an error if the base URL cannot be obtained from environment variables

Source

pub async fn with_config(config: RetryConfig) -> Result<Self, Error>

Creates a new TokenManager with the specified retry configuration

§Errors

Returns an error if the base URL cannot be obtained from environment variables

Source

pub async fn with_config_and_base_url( config: RetryConfig, base_url: Url, ) -> Result<Self, Error>

Creates a new TokenManager with the specified configuration and base URL (for testing)

§Errors

This method is infallible but returns Result for API consistency

Source

pub fn with_mock_token( config: RetryConfig, base_url: Url, mock_token: String, ) -> Result<Self, Error>

Creates a new TokenManager with a pre-set mock token (for testing)

§Errors

This method is infallible but returns Result for API consistency

Source

pub async fn get_token(&self) -> Result<String, Error>

Gets a valid authentication token with proactive refresh logic

This method implements thread-safe token management logic:

  1. Check if a valid token exists and is not expiring soon (within 5 minutes)
  2. If token needs refresh/obtain, acquire semaphore to prevent concurrent operations
  3. Double-check token state after acquiring semaphore (another thread may have updated it)
  4. Perform atomic token update operations
  5. Return the valid token
§Thread Safety

This method is fully thread-safe and prevents race conditions by:

  • Using a semaphore to ensure only one token operation at a time
  • Double-checking token state after acquiring the semaphore
  • Performing atomic token updates within the critical section
§Errors

Returns a TokenError if token acquisition or refresh fails after all retries

Source

pub async fn obtain_token(&self) -> Result<String, Error>

Obtains a new authentication token using environment credentials with retry logic

This method:

  1. Reads credentials from environment variables
  2. Makes a token request with retry logic
  3. Stores the new token with 24-hour expiry
  4. Returns the token string
§Thread Safety

This method acquires the token operation semaphore to ensure thread-safe operation. For internal use within already-synchronized contexts, use obtain_token_internal().

§Errors

Returns an error if:

  • Environment variables are missing
  • All retry attempts fail
  • Response parsing fails
Source

pub async fn refresh_token(&self) -> Result<String, Error>

Refreshes the current authentication token with fallback to obtain on failure

This method:

  1. Uses the existing token to request a refresh
  2. Updates the stored token data on success
  3. Falls back to obtaining a new token if refresh fails
§Thread Safety

This method acquires the token operation semaphore to ensure thread-safe operation. For internal use within already-synchronized contexts, use refresh_token_internal().

§Errors

Returns an error if both refresh and obtain operations fail

Source

pub async fn get_token_info(&self) -> Result<Option<TokenInfo>, Error>

Gets current token information for debugging and monitoring

Returns detailed information about the current token including:

  • Expiry time and remaining duration
  • Token age since acquisition
  • Expiry status flags
§Returns

Some(TokenInfo) if a token exists, None if no token is stored

§Errors

Returns an error if token information retrieval fails

Source

pub async fn clear_token(&self) -> Result<(), Error>

Clears the stored token (useful for testing scenarios)

This method removes the current token from storage, forcing the next get_token() call to obtain a fresh token.

§Errors

Returns an error if token clearing fails

Source

pub async fn force_refresh(&self) -> Result<String, Error>

Forces a token refresh regardless of current token status

This method bypasses the normal proactive refresh logic and immediately attempts to refresh the current token. If no token exists or refresh fails, it falls back to obtaining a new token.

§Thread Safety

This method is fully thread-safe and uses the same semaphore-based synchronization as other token operations to prevent race conditions.

§Errors

Returns an error if both refresh and obtain operations fail

Source

pub async fn force_cleanup_token_files() -> Result<(), Error>

Forces cleanup of token persistence files (useful for testing) This method removes token files regardless of persistence settings

§Errors

Returns an error if:

  • File system permissions prevent deletion of the token file
  • I/O errors occur during file deletion operations
  • The token file is locked by another process
Source

pub async fn reset_global_instance() -> Result<(), Error>

Resets the global TokenManager singleton (useful for testing)

This method clears the global singleton instance, forcing the next call to get_global_instance() to create a fresh TokenManager. Primarily intended for test scenarios where a clean state is needed.

§Errors

Returns an error if:

  • Token clearing operations fail during the reset process
  • File system errors occur when clearing persistent token data
  • The global instance is in an invalid state that prevents cleanup

Trait Implementations§

Source§

impl Debug for TokenManager

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more