Skip to content

Commit 6f6c812

Browse files
authored
Merge pull request #96 from futuredapp/feature/async-cancellation
Add cancellation support to async methods
2 parents 5116f4c + d42bd01 commit 6f6c812

1 file changed

Lines changed: 75 additions & 42 deletions

File tree

Sources/FTAPIKit/URLServer+Async.swift

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import Foundation
2+
#if os(Linux)
3+
import FoundationNetworking
4+
#endif
25

36
// This extension is duplicated to support Xcode 13.0 and Xcode 13.1,
47
// where backported concurrency is not available.
@@ -15,15 +18,20 @@ public extension URLServer {
1518
/// - Throws: Throws in case that result is .failure
1619
/// - Returns: Void on success
1720
func call(endpoint: Endpoint) async throws {
18-
return try await withCheckedThrowingContinuation { continuation in
19-
call(endpoint: endpoint) { result in
20-
switch result {
21-
case .success:
22-
continuation.resume()
23-
case .failure(let error):
24-
continuation.resume(throwing: error)
21+
var task: URLSessionTask?
22+
return try await withTaskCancellationHandler {
23+
try await withCheckedThrowingContinuation { continuation in
24+
task = call(endpoint: endpoint) { result in
25+
switch result {
26+
case .success:
27+
continuation.resume()
28+
case .failure(let error):
29+
continuation.resume(throwing: error)
30+
}
2531
}
2632
}
33+
} onCancel: { [task] in
34+
task?.cancel()
2735
}
2836
}
2937

@@ -35,15 +43,20 @@ public extension URLServer {
3543
/// - Throws: Throws in case that result is .failure
3644
/// - Returns: Plain data returned with the HTTP Response
3745
func call(data endpoint: Endpoint) async throws -> Data {
38-
return try await withCheckedThrowingContinuation { continuation in
39-
call(data: endpoint) { result in
40-
switch result {
41-
case .success(let data):
42-
continuation.resume(returning: data)
43-
case .failure(let error):
44-
continuation.resume(throwing: error)
46+
var task: URLSessionTask?
47+
return try await withTaskCancellationHandler {
48+
try await withCheckedThrowingContinuation { continuation in
49+
task = call(data: endpoint) { result in
50+
switch result {
51+
case .success(let data):
52+
continuation.resume(returning: data)
53+
case .failure(let error):
54+
continuation.resume(throwing: error)
55+
}
4556
}
4657
}
58+
} onCancel: { [task] in
59+
task?.cancel()
4760
}
4861
}
4962

@@ -55,15 +68,20 @@ public extension URLServer {
5568
/// - Throws: Throws in case that result is .failure
5669
/// - Returns: Instance of the required type
5770
func call<EP: ResponseEndpoint>(response endpoint: EP) async throws -> EP.Response {
58-
return try await withCheckedThrowingContinuation { continuation in
59-
call(response: endpoint) { result in
60-
switch result {
61-
case .success(let response):
62-
continuation.resume(returning: response)
63-
case .failure(let error):
64-
continuation.resume(throwing: error)
71+
var task: URLSessionTask?
72+
return try await withTaskCancellationHandler {
73+
try await withCheckedThrowingContinuation { continuation in
74+
task = call(response: endpoint) { result in
75+
switch result {
76+
case .success(let response):
77+
continuation.resume(returning: response)
78+
case .failure(let error):
79+
continuation.resume(throwing: error)
80+
}
6581
}
6682
}
83+
} onCancel: { [task] in
84+
task?.cancel()
6785
}
6886
}
6987
}
@@ -80,15 +98,20 @@ public extension URLServer {
8098
/// - Throws: Throws in case that result is .failure
8199
/// - Returns: Void on success
82100
func call(endpoint: Endpoint) async throws {
83-
return try await withCheckedThrowingContinuation { continuation in
84-
call(endpoint: endpoint) { result in
85-
switch result {
86-
case .success:
87-
continuation.resume()
88-
case .failure(let error):
89-
continuation.resume(throwing: error)
101+
var task: URLSessionTask?
102+
return try await withTaskCancellationHandler {
103+
try await withCheckedThrowingContinuation { continuation in
104+
task = call(endpoint: endpoint) { result in
105+
switch result {
106+
case .success:
107+
continuation.resume()
108+
case .failure(let error):
109+
continuation.resume(throwing: error)
110+
}
90111
}
91112
}
113+
} onCancel: { [task] in
114+
task?.cancel()
92115
}
93116
}
94117

@@ -100,15 +123,20 @@ public extension URLServer {
100123
/// - Throws: Throws in case that result is .failure
101124
/// - Returns: Plain data returned with the HTTP Response
102125
func call(data endpoint: Endpoint) async throws -> Data {
103-
return try await withCheckedThrowingContinuation { continuation in
104-
call(data: endpoint) { result in
105-
switch result {
106-
case .success(let data):
107-
continuation.resume(returning: data)
108-
case .failure(let error):
109-
continuation.resume(throwing: error)
126+
var task: URLSessionTask?
127+
return try await withTaskCancellationHandler {
128+
try await withCheckedThrowingContinuation { continuation in
129+
task = call(data: endpoint) { result in
130+
switch result {
131+
case .success(let data):
132+
continuation.resume(returning: data)
133+
case .failure(let error):
134+
continuation.resume(throwing: error)
135+
}
110136
}
111137
}
138+
} onCancel: { [task] in
139+
task?.cancel()
112140
}
113141
}
114142

@@ -120,15 +148,20 @@ public extension URLServer {
120148
/// - Throws: Throws in case that result is .failure
121149
/// - Returns: Instance of the required type
122150
func call<EP: ResponseEndpoint>(response endpoint: EP) async throws -> EP.Response {
123-
return try await withCheckedThrowingContinuation { continuation in
124-
call(response: endpoint) { result in
125-
switch result {
126-
case .success(let response):
127-
continuation.resume(returning: response)
128-
case .failure(let error):
129-
continuation.resume(throwing: error)
151+
var task: URLSessionTask?
152+
return try await withTaskCancellationHandler {
153+
try await withCheckedThrowingContinuation { continuation in
154+
task = call(response: endpoint) { result in
155+
switch result {
156+
case .success(let response):
157+
continuation.resume(returning: response)
158+
case .failure(let error):
159+
continuation.resume(throwing: error)
160+
}
130161
}
131162
}
163+
} onCancel: { [task] in
164+
task?.cancel()
132165
}
133166
}
134167
}

0 commit comments

Comments
 (0)