Skip to content

Optimize Token Refresh with Conditional Queuing and Typed Error Mapping

Choose a tag to compare

@krishnavarma1 krishnavarma1 released this 21 Oct 22:54
· 2 commits to master since this release
352b5eb

Introduction:

This PR enhances AtomNetworking by optimizing bearer token refresh handling. It introduces conditional serialization of network calls - bypassing the queue when no refresh is needed for better performance - while maintaining strict FIFO ordering and deduplication during refresh scenarios.

Motivation:

Previously, all network operations were serialized through RequestableQueueManager, even when the access token was valid. This caused unnecessary delays in high-throughput scenarios. Additionally, error propagation from generic Error to typed AtomError was verbose and repetitive.

The goal is to:

  • Only serialize calls when token refresh is needed or in progress.
  • Enqueue calls during refresh and execute them immediately after completion.
  • Preserve FIFO order and race safety during refresh.

Proposed Solution:

Conditional Serialization in Service**:

  • Added needsSerialization() to SessionActor to check both .requiresRefresh and isRefreshing.
  • Introduced awaitOrEnqueue(_:) in Service to:
    • Bypass the queue and execute directly if no refresh needed.
    • Enqueue if refresh is required or ongoing.

Code Changes

SessionActor+Authorization.swift

/// Determines whether the access token should be refreshed based on the service configuration.
///
/// This asynchronous function checks the authentication method in the service configuration. It only proceeds if the method is a
/// bearer token with a writable component.
///
/// - Returns: A `Bool` value indicating if the access token needs refreshing. Returns `true` if refresh is required; otherwise, `false`.
func needsSerialization() async -> Bool {
    guard case let .bearer(_, _, writable) = serviceConfiguration.authenticationMethod else {
        return false
    }

    return writable.tokenCredential.requiresRefresh || isRefreshing
}

Service+ConditionalQueuing.swift

/// Executes or enqueues an asynchronous task based on whether the access token requires refreshing.
///
/// This function creates a task to check if the session's access token needs to be refreshed using `sessionActor.shouldRefreshAccessToken()`. If a
/// refresh is required, the provided task is enqueued in the `requestableQueueManager` for later execution. If no refresh is needed, the task is
/// executed immediately within the detached task context.
///
/// This mechanism ensures that tasks dependent on a valid access token are properly sequenced without blocking the caller.
///
/// - Parameter task: An escaping, sendable asynchronous closure that performs the desired operation. The closure takes no parameters and returns `Void`.
func awaitOrEnqueue(_ task: @escaping @Sendable () async -> Void) {
    Task {
        if await sessionActor.shouldRefreshAccessToken() {
            requestableQueueManager.enqueue(task)
        } else {
            await task()
        }
    }
}

Additional Info:

  • Optimize access token refresh with conditional queuing.
  • Updated documentation.

Source Compatibility:

Please check the box to indicate the impact of this proposal on source compatibility.

  • This change is additive and does not impact existing source code.
  • This change breaks existing source code.