Created
December 27, 2023 14:44
-
-
Save kean/9fb9813ede243eeae9601d90207f884b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
actor SomeManager { | |
private var tasks: [String: DataTask] = [:] | |
private func data(for request: URLRequest) async throws -> Data { | |
let requestKey = request.urlRequest?.url?.absoluteString ?? "" | |
let task = tasks[requestKey] ?? DataTask(task: Task { | |
try await self._data(for: request, key: requestKey) | |
}) | |
let subscriptionID = UUID() | |
task.subscriptions.insert(subscriptionID) | |
tasks[requestKey] = task | |
return try await withTaskCancellationHandler { | |
try await task.task.value | |
} onCancel: { | |
Task { | |
await self.unsubscribe(subscriptionID, key: requestKey) | |
} | |
} | |
} | |
private func unsubscribe(_ subscriptionID: UUID, key: String) { | |
guard let task = tasks[key], | |
task.subscriptions.remove(subscriptionID) != nil, | |
task.subscriptions.isEmpty else { | |
return | |
} | |
task.task.cancel() | |
tasks[key] = nil | |
} | |
private func _data(for request: URLRequest, key: String) async throws -> Data { | |
defer { tasks[key] = nil } | |
let (data, response) = try await session.data(for: request) | |
try validate(response: response) | |
return data | |
} | |
private final class DataTask { | |
var subscriptions = Set<UUID>() | |
var isCancelled = false | |
var task: Task<Data, Error> | |
init(subscriptions: Set<UUID> = Set<UUID>(), task: Task<Data, Error>) { | |
self.subscriptions = subscriptions | |
self.isCancelled = isCancelled | |
self.task = task | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment