Skip to content

Commit f5ebaba

Browse files
authored
Improve threading (#51)
* Improve threading * Drop patch in codecov for now
1 parent 806e026 commit f5ebaba

File tree

13 files changed

+670
-450
lines changed

13 files changed

+670
-450
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ coverage:
55
status:
66
patch:
77
default:
8-
target: auto
8+
target: 67
99
changes: false
1010
project:
1111
default:

Sources/ParseSwift/API/API+Commands.swift

Lines changed: 32 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ internal extension API {
5050

5151
// MARK: Synchronous Execution
5252
func executeStream(options: API.Options,
53+
callbackQueue: DispatchQueue,
5354
childObjects: [String: PointerType]? = nil,
5455
childFiles: [UUID: ParseFile]? = nil,
5556
uploadProgress: ((URLSessionTask, Int64, Int64, Int64) -> Void)? = nil,
@@ -61,6 +62,7 @@ internal extension API {
6162
let task = URLSession.parse.uploadTask(withStreamedRequest: urlRequest)
6263
ParseConfiguration.sessionDelegate.uploadDelegates[task] = uploadProgress
6364
ParseConfiguration.sessionDelegate.streamDelegates[task] = stream
65+
ParseConfiguration.sessionDelegate.taskCallbackQueues[task] = callbackQueue
6466
task.resume()
6567
return
6668
}
@@ -70,6 +72,7 @@ internal extension API {
7072
}
7173

7274
func execute(options: API.Options,
75+
callbackQueue: DispatchQueue,
7376
childObjects: [String: PointerType]? = nil,
7477
childFiles: [UUID: ParseFile]? = nil,
7578
uploadProgress: ((URLSessionTask, Int64, Int64, Int64) -> Void)? = nil,
@@ -78,7 +81,7 @@ internal extension API {
7881
let group = DispatchGroup()
7982
group.enter()
8083
self.executeAsync(options: options,
81-
callbackQueue: nil,
84+
callbackQueue: callbackQueue,
8285
childObjects: childObjects,
8386
childFiles: childFiles,
8487
uploadProgress: uploadProgress,
@@ -97,7 +100,8 @@ internal extension API {
97100

98101
// MARK: Asynchronous Execution
99102
// swiftlint:disable:next function_body_length cyclomatic_complexity
100-
func executeAsync(options: API.Options, callbackQueue: DispatchQueue?,
103+
func executeAsync(options: API.Options,
104+
callbackQueue: DispatchQueue,
101105
childObjects: [String: PointerType]? = nil,
102106
childFiles: [UUID: ParseFile]? = nil,
103107
uploadProgress: ((URLSessionTask, Int64, Int64, Int64) -> Void)? = nil,
@@ -114,18 +118,9 @@ internal extension API {
114118
switch result {
115119

116120
case .success(let decoded):
117-
if let callbackQueue = callbackQueue {
118-
callbackQueue.async { completion(.success(decoded)) }
119-
} else {
120-
completion(.success(decoded))
121-
}
122-
121+
completion(.success(decoded))
123122
case .failure(let error):
124-
if let callbackQueue = callbackQueue {
125-
callbackQueue.async { completion(.failure(error)) }
126-
} else {
127-
completion(.failure(error))
128-
}
123+
completion(.failure(error))
129124
}
130125
}
131126
case .failure(let error):
@@ -140,26 +135,20 @@ internal extension API {
140135

141136
case .success(let urlRequest):
142137

143-
URLSession.parse.uploadTask(with: urlRequest,
144-
from: uploadData,
145-
from: uploadFile,
146-
progress: uploadProgress,
147-
mapper: mapper) { result in
138+
URLSession
139+
.parse
140+
.uploadTask(callbackQueue: callbackQueue,
141+
with: urlRequest,
142+
from: uploadData,
143+
from: uploadFile,
144+
progress: uploadProgress,
145+
mapper: mapper) { result in
148146
switch result {
149147

150148
case .success(let decoded):
151-
if let callbackQueue = callbackQueue {
152-
callbackQueue.async { completion(.success(decoded)) }
153-
} else {
154-
completion(.success(decoded))
155-
}
156-
149+
completion(.success(decoded))
157150
case .failure(let error):
158-
if let callbackQueue = callbackQueue {
159-
callbackQueue.async { completion(.failure(error)) }
160-
} else {
161-
completion(.failure(error))
162-
}
151+
completion(.failure(error))
163152
}
164153
}
165154
case .failure(let error):
@@ -173,24 +162,18 @@ internal extension API {
173162
childFiles: childFiles) {
174163

175164
case .success(let urlRequest):
176-
URLSession.parse.downloadTask(with: urlRequest,
177-
progress: downloadProgress,
178-
mapper: mapper) { result in
165+
URLSession
166+
.parse
167+
.downloadTask(callbackQueue: callbackQueue,
168+
with: urlRequest,
169+
progress: downloadProgress,
170+
mapper: mapper) { result in
179171
switch result {
180172

181173
case .success(let decoded):
182-
if let callbackQueue = callbackQueue {
183-
callbackQueue.async { completion(.success(decoded)) }
184-
} else {
185-
completion(.success(decoded))
186-
}
187-
174+
completion(.success(decoded))
188175
case .failure(let error):
189-
if let callbackQueue = callbackQueue {
190-
callbackQueue.async { completion(.failure(error)) }
191-
} else {
192-
completion(.failure(error))
193-
}
176+
completion(.failure(error))
194177
}
195178
}
196179
case .failure(let error):
@@ -202,18 +185,9 @@ internal extension API {
202185
switch result {
203186

204187
case .success(let decoded):
205-
if let callbackQueue = callbackQueue {
206-
callbackQueue.async { completion(.success(decoded)) }
207-
} else {
208-
completion(.success(decoded))
209-
}
210-
188+
completion(.success(decoded))
211189
case .failure(let error):
212-
if let callbackQueue = callbackQueue {
213-
callbackQueue.async { completion(.failure(error)) }
214-
} else {
215-
completion(.failure(error))
216-
}
190+
completion(.failure(error))
217191
}
218192
}
219193
} else {
@@ -596,8 +570,7 @@ internal extension API {
596570
var responseResult: Result<U, ParseError>?
597571
let group = DispatchGroup()
598572
group.enter()
599-
self.executeAsync(options: options,
600-
callbackQueue: nil) { result in
573+
self.executeAsync(options: options) { result in
601574
responseResult = result
602575
group.leave()
603576
}
@@ -611,7 +584,7 @@ internal extension API {
611584
}
612585

613586
// MARK: Asynchronous Execution
614-
func executeAsync(options: API.Options, callbackQueue: DispatchQueue?,
587+
func executeAsync(options: API.Options,
615588
completion: @escaping(Result<U, ParseError>) -> Void) {
616589

617590
switch self.prepareURLRequest(options: options) {
@@ -620,18 +593,9 @@ internal extension API {
620593
switch result {
621594

622595
case .success(let decoded):
623-
if let callbackQueue = callbackQueue {
624-
callbackQueue.async { completion(.success(decoded)) }
625-
} else {
626-
completion(.success(decoded))
627-
}
628-
596+
completion(.success(decoded))
629597
case .failure(let error):
630-
if let callbackQueue = callbackQueue {
631-
callbackQueue.async { completion(.failure(error)) }
632-
} else {
633-
completion(.failure(error))
634-
}
598+
completion(.failure(error))
635599
}
636600
}
637601
case .failure(let error):

Sources/ParseSwift/API/ParseURLSessionDelegate.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
2020
var downloadDelegates = [URLSessionDownloadTask: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void)]()
2121
var uploadDelegates = [URLSessionTask: ((URLSessionTask, Int64, Int64, Int64) -> Void)]()
2222
var streamDelegates = [URLSessionTask: InputStream]()
23+
var taskCallbackQueues = [URLSessionTask: DispatchQueue]()
2324

2425
init (callbackQueue: DispatchQueue,
2526
authentication: ((URLAuthenticationChallenge,
@@ -35,7 +36,9 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
3536
completionHandler: @escaping (URLSession.AuthChallengeDisposition,
3637
URLCredential?) -> Void) {
3738
if let authentication = authentication {
38-
authentication(challenge, completionHandler)
39+
callbackQueue.async {
40+
authentication(challenge, completionHandler)
41+
}
3942
} else {
4043
completionHandler(.performDefaultHandling, nil)
4144
}
@@ -46,8 +49,10 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
4649
didSendBodyData bytesSent: Int64,
4750
totalBytesSent: Int64,
4851
totalBytesExpectedToSend: Int64) {
49-
if let callBack = uploadDelegates[task] {
50-
callbackQueue.async {
52+
if let callBack = uploadDelegates[task],
53+
let queue = taskCallbackQueues[task] {
54+
55+
queue.async {
5156
callBack(task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
5257

5358
if totalBytesSent == totalBytesExpectedToSend {
@@ -63,8 +68,9 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
6368
totalBytesWritten: Int64,
6469
totalBytesExpectedToWrite: Int64) {
6570

66-
if let callBack = downloadDelegates[downloadTask] {
67-
callbackQueue.async {
71+
if let callBack = downloadDelegates[downloadTask],
72+
let queue = taskCallbackQueues[downloadTask] {
73+
queue.async {
6874
callBack(downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
6975
if totalBytesWritten == totalBytesExpectedToWrite {
7076
self.downloadDelegates.removeValue(forKey: downloadTask)
@@ -77,6 +83,7 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
7783
downloadTask: URLSessionDownloadTask,
7884
didFinishDownloadingTo location: URL) {
7985
downloadDelegates.removeValue(forKey: downloadTask)
86+
taskCallbackQueues.removeValue(forKey: downloadTask)
8087
}
8188

8289
func urlSession(_ session: URLSession,
@@ -86,4 +93,10 @@ class ParseURLSessionDelegate: NSObject, URLSessionDelegate, URLSessionDataDeleg
8693
completionHandler(stream)
8794
}
8895
}
96+
97+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
98+
uploadDelegates.removeValue(forKey: task)
99+
streamDelegates.removeValue(forKey: task)
100+
taskCallbackQueues.removeValue(forKey: task)
101+
}
89102
}

Sources/ParseSwift/API/URLSession+extensions.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ extension URLSession {
101101

102102
extension URLSession {
103103
internal func uploadTask<U>( // swiftlint:disable:this function_parameter_count
104+
callbackQueue: DispatchQueue,
104105
with request: URLRequest,
105106
from data: Data?,
106107
from file: URL?,
@@ -126,11 +127,13 @@ extension URLSession {
126127
}
127128
if let task = task {
128129
ParseConfiguration.sessionDelegate.uploadDelegates[task] = progress
130+
ParseConfiguration.sessionDelegate.taskCallbackQueues[task] = callbackQueue
129131
task.resume()
130132
}
131133
}
132134

133135
internal func downloadTask<U>(
136+
callbackQueue: DispatchQueue,
134137
with request: URLRequest,
135138
progress: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?,
136139
mapper: @escaping (Data) throws -> U,
@@ -142,6 +145,7 @@ extension URLSession {
142145
responseError: responseError, mapper: mapper))
143146
}
144147
ParseConfiguration.sessionDelegate.downloadDelegates[task] = progress
148+
ParseConfiguration.sessionDelegate.taskCallbackQueues[task] = callbackQueue
145149
task.resume()
146150
}
147151

Sources/ParseSwift/LiveQuery/LiveQuerySocket.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ final class LiveQuerySocket: NSObject {
2727
func closeAll() {
2828
delegates.forEach { (_, client) -> Void in
2929
client.close(useDedicatedQueue: false)
30-
authenticationDelegate = nil
3130
}
31+
authenticationDelegate = nil
3232
}
3333
}
3434

0 commit comments

Comments
 (0)