Skip to content

Commit

Permalink
chore: add protocol to unite url session specific invalidation functi…
Browse files Browse the repository at this point in the history
…onality
  • Loading branch information
gajddo00 committed Feb 3, 2025
1 parent b445b06 commit 856d1fc
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 27 deletions.
27 changes: 19 additions & 8 deletions Sources/Networking/Core/APIManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ open class APIManager: APIManaging, Retryable {
private let responseProcessors: [ResponseProcessing]
private let errorProcessors: [ErrorProcessing]
private let sessionId: String
private var _responseProvider: ResponseProviding
private var responseProvider: ResponseProviding
private var _urlSessionIsInvalidated: Bool = false

internal var retryCounter = Counter()

Expand All @@ -69,7 +70,7 @@ open class APIManager: APIManaging, Retryable {
sessionId = Date().ISO8601Format()
}

self._responseProvider = urlSession
self.responseProvider = urlSession
self.requestAdapters = requestAdapters
self.responseProcessors = responseProcessors
self.errorProcessors = errorProcessors
Expand All @@ -89,7 +90,7 @@ open class APIManager: APIManaging, Retryable {
} else {
sessionId = Date().ISO8601Format()
}
self._responseProvider = responseProvider
self.responseProvider = responseProvider
self.requestAdapters = requestAdapters
self.responseProcessors = responseProcessors
self.errorProcessors = errorProcessors
Expand All @@ -103,15 +104,25 @@ open class APIManager: APIManaging, Retryable {
}
}

// MARK: Response provider
// MARK: URL Session Invalidation

public extension APIManager {
var responseProvider: ResponseProviding {
_responseProvider
var urlSessionIsInvalidated: Bool {
_urlSessionIsInvalidated
}

func setResponseProvider(_ provider: ResponseProviding) {
self._responseProvider = provider
var urlSession: URLSession? {
responseProvider as? URLSession
}

func setUrlSession(_ urlSession: URLSession) {
responseProvider = urlSession
}

func invalidateUrlSession() async {
await urlSession?.allTasks.forEach { $0.cancel() }
urlSession?.invalidateAndCancel()
_urlSessionIsInvalidated = true
}
}

Expand Down
10 changes: 2 additions & 8 deletions Sources/Networking/Core/APIManaging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
// MARK: - Defines API managing

/// A definition of an API layer with methods for handling API requests.
public protocol APIManaging {
public protocol APIManaging: URLSessionInvalidatable {
/// A default `JSONDecoder` used for all requests.
var defaultDecoder: JSONDecoder { get }

Expand All @@ -33,13 +33,7 @@ public protocol APIManaging {
_ endpoint: Requestable,
decoder: JSONDecoder,
retryConfiguration: RetryConfiguration?
) async throws -> DecodableResponse

/// Invalidates and response provider to gracefully clear out all its tasks.
var responseProvider: ResponseProviding { get }

/// Replaces the response provider instance used by APIManager.
func setResponseProvider(_ provider: ResponseProviding)
) async throws -> DecodableResponse
}

// MARK: - Provide request with default json decoder, retry configuration
Expand Down
11 changes: 0 additions & 11 deletions Sources/Networking/Core/ResponseProviding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,11 @@ import Foundation
public protocol ResponseProviding {
/// Creates a ``Response`` for a given `URLRequest`.
func response(for request: URLRequest) async throws -> Response

/// Invalidates and response provider to gracefully clear out all its tasks.
func invalidate() async
}

extension URLSession: ResponseProviding {
/// Creates a ``Response`` for a given `URLRequest` by firing a network request.
public func response(for request: URLRequest) async throws -> Response {
try await data(for: request)
}

/// Invalidates and response provider to gracefully clear out all its tasks.
/// Warning: URLSession can no longer be used after it's been invalidated and any usage
/// will lead to a crash.
public func invalidate() async {
await allTasks.forEach { $0.cancel() }
invalidateAndCancel()
}
}
19 changes: 19 additions & 0 deletions Sources/Networking/Core/URLSessionInvalidatable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation

/// Adds capability for `URLSession` to be invalidated and recreated.
public protocol URLSessionInvalidatable {
/// Invalidates urlSession to gracefully clear out all its tasks.
var urlSession: URLSession? { get }

/// Returns `true` if session has been invalidate and is no longer suitable for usage.
/// Any other usage of this urlSession will lead to runtime error.
var urlSessionIsInvalidated: Bool { get }

/// Replaces the urlSession instance used by APIManager.
func setUrlSession(_ urlSession: URLSession)

/// Invalidates the current urlSession.
/// Warning: urlSession must be recreated before further usage
/// otherwise runtime error is encountered as accessing invalidated session is illegal.
func invalidateUrlSession() async
}

0 comments on commit 856d1fc

Please sign in to comment.