Skip to content

Request Management

Husnain Ali edited this page Sep 27, 2026 · 3 revisions

Request Management

Covers cancellation, deduplication, reachability, and the concurrency limit.

Request cancellation

// 1. Task cancellation cascades to the URLSession task.
let task = Task { try await client.request(GetProfile()) }
task.cancel()

// 2. Cancel by ID from anywhere.
let id = RequestID()
Task { try await client.request(GetFeed(), id: id) }
await client.cancel(id)

// 3. Cancel everything in flight.
await client.cancelAll()

A cancelled request throws NetworkError.cancelled. cancelAll() also stops a background stale-while-revalidate refresh started by Caching, and a request cancelled while waiting for a concurrency-queue slot leaves the queue immediately, without taking a slot or running.

Request deduplication

When enabled, concurrent identical GET / HEAD requests share one in-flight network call.

Request A ─┐
Request B ─┼──► one URLSession request ──► response fanned out to A, B, C
Request C ─┘
config.enableDeduplication = true               // global
// or per endpoint:
struct GetConfig: Endpoint {
    typealias Response = AppConfig
    var path: String { "/config" }
    var deduplicate: Bool? { true }
}

Deduplication keys on method + URL + a fingerprint of the Authorization value, so requests made with different accounts never share a result. It never applies to non-idempotent methods or anything user-specific.

Network reachability

let monitor = PathNetworkMonitor()
var config = NetworkConfiguration(baseURL: "https://api.example.com")
config.networkMonitor = monitor

for await status in await monitor.statusUpdates() {
    switch status {
    case .satisfied(let interface):   // .wifi / .cellular / .wiredEthernet / .other
        print("online via \(interface)")
    case .unsatisfied, .requiresConnection:
        print("offline")
    }
}

for await _ in await monitor.connectionRestored() {
    // fires each time connectivity returns after a drop
}

NetworkStatusBroadcaster fans one NWPathMonitor out to many AsyncStream consumers, delivered in the order the system reported them. In tests, inject MockNetworkMonitor and call send(.unsatisfied) / send(.satisfied(.wifi)).

Concurrency limit

maxConcurrentRequests (default 6, matching the URLSession per-host limit) bounds in-flight work; extra requests queue by Endpoint.priority. See Platform Notes Thread Safety and Performance for the performance notes.

Clone this wiki locally