Skip to content

Architecture and Core Concepts

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

Architecture and Core Concepts

Architecture

NetworkClient  (composition root, the only type you construct)
│
├── RequestBuilder ......... Endpoint + environment -> URLRequest (path params, query, headers, body)
├── InterceptorChain ....... request interceptors -> ... -> response interceptors
│     └── TracingInterceptor  (always first: X-Request-ID / X-Correlation-ID)
├── TokenManager (actor) ... single-flight 401 refresh, request queueing, proactive refresh
│     └── TokenStorage ...... InMemoryTokenStorage | KeychainTokenStorage | your own
├── RequestQueue (actor) ... concurrency limit + priority ordering, pause / resume
├── RequestRegistry (actor)  cancel-by-id bookkeeping
├── RequestDeduplicator ....  collapse concurrent identical GETs
├── RetryPolicy ............ backoff + jitter + Retry-After, idempotency-aware
├── ResponseCache .......... MemoryCacheStore | DiskCacheStore, ETag / 304 / SWR
├── NetworkTransport ....... URLSessionTransport (default) | MockNetworkTransport (tests)
│     └── ServerTrustEvaluator  certificate / public-key pinning via the URLSession delegate
├── OfflineRequestQueue .... persisted queue, replays FIFO on reconnect
├── NetworkLogger .......... ConsoleNetworkLogger over os.Logger, values run through Redactor
└── NetworkMetrics ......... InMemoryMetrics (counts, histogram, p95) | NoopMetrics

Each collaborator is a protocol. NetworkClient builds the default concrete graph from your NetworkConfiguration; every seam accepts an override for testing. See Testing and Mocking for how that pays off, and Documentation/Concurrency.md in the repo for the full concurrency breakdown.

Core concepts

Type Role
NetworkClient The façade you call. Holds the configuration and the component graph. Sendable, share one instance.
NetworkConfiguration Everything that shapes requests: environment, decoders, auth strategy, token storage, retry, interceptors, pinning, cache, concurrency, logger, metrics. A value type.
NetworkEnvironment One deployment target: kind, baseURL, defaultHeaders, timeout, logLevel.
Endpoint A protocol describing one API operation and its Response type.
HTTPMethod .get / .post / .put / .patch / .delete / .head / .options / .trace / .custom(String).
HTTPHeaders Case-insensitive header map, ExpressibleByDictionaryLiteral.
RequestBody .json(Encodable) / .data / .string / .formURLEncoded / .multipart(MultipartFormData).
QueryParameters Typed query values (.string, .int, .bool, arrays).
NetworkError The single error type crossing the public boundary.
ProgressEvent completed / total bytes, plus fraction: Double?.
RequestID A Sendable, Codable handle for cancellation and offline replay.

Thread safety

  • NetworkClient is Sendable. Construct one and share it.
  • Shared mutable state lives in actors: TokenManager, RequestQueue, RequestRegistry, RequestDeduplicator, the cache stores, InMemoryMetrics, OfflineRequestQueue.
  • The concurrent 401 case is handled by TokenManager's single-flight refresh; there is an explicit deadlock test for "full queue plus expired token".
  • The only @unchecked Sendable types are the three URLSession delegate shims (whose callbacks are not async) and the test doubles; each guards a few lines with a lock and a comment.
  • SwiftUI NetworkResource / Paged are @MainActor.
  • The whole test suite runs green under ThreadSanitizer in CI.

More on this, plus performance notes and platform quirks, in Platform Notes Thread Safety and Performance.

Clone this wiki locally