Avoid stalls in GIF downloader.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 5a6e739115
commit b3e39e6584

@ -509,11 +509,9 @@ extension URLSessionTask {
assetRequestQueue.append(assetRequest) assetRequestQueue.append(assetRequest)
// Process the queue (which may start this request) // Process the queue (which may start this request)
// asynchronously so that the caller has time to store // asynchronously so that the caller has time to store
// a reference to the asset request returned by this // a reference to the asset request returned by this
// method before its success/failure handler is called. // method before its success/failure handler is called.
DispatchQueue.main.async { processRequestQueueAsync()
self.processRequestQueue()
}
return assetRequest return assetRequest
} }
@ -545,7 +543,7 @@ extension URLSessionTask {
self.assetRequestDidSucceed(assetRequest: assetRequest, asset: asset) self.assetRequestDidSucceed(assetRequest: assetRequest, asset: asset)
} }
} else { } else {
self.processRequestQueue() self.processRequestQueueSync()
} }
} }
} }
@ -562,7 +560,6 @@ extension URLSessionTask {
// TODO: If we wanted to implement segment retry, we'll need to add // TODO: If we wanted to implement segment retry, we'll need to add
// a segmentRequestDidFail() method. // a segmentRequestDidFail() method.
private func segmentRequestDidFail(assetRequest: GiphyAssetRequest, assetSegment: GiphyAssetSegment) { private func segmentRequestDidFail(assetRequest: GiphyAssetRequest, assetSegment: GiphyAssetSegment) {
DispatchQueue.main.async { DispatchQueue.main.async {
assetSegment.state = .failed assetSegment.state = .failed
assetRequest.state = .failed assetRequest.state = .failed
@ -587,13 +584,21 @@ extension URLSessionTask {
} }
assetRequestQueue = assetRequestQueue.filter { $0 != assetRequest } assetRequestQueue = assetRequestQueue.filter { $0 != assetRequest }
processRequestQueue() // Process the queue async to ensure that state in the downloader
// classes is consistent before we try to start a new request.
processRequestQueueAsync()
}
private func processRequestQueueAsync() {
DispatchQueue.main.async {
self.processRequestQueueSync()
}
} }
// * Start a segment request or content length request if possible. // * Start a segment request or content length request if possible.
// * Complete/cancel asset requests if possible. // * Complete/cancel asset requests if possible.
// //
private func processRequestQueue() { private func processRequestQueueSync() {
AssertIsOnMainThread() AssertIsOnMainThread()
guard let assetRequest = popNextAssetRequest() else { guard let assetRequest = popNextAssetRequest() else {
@ -608,7 +613,7 @@ extension URLSessionTask {
// If app is not active, fail the asset request. // If app is not active, fail the asset request.
assetRequest.state = .failed assetRequest.state = .failed
assetRequestDidFail(assetRequest:assetRequest) assetRequestDidFail(assetRequest:assetRequest)
processRequestQueue() processRequestQueueSync()
return return
} }
@ -630,11 +635,11 @@ extension URLSessionTask {
request.httpMethod = "HEAD" request.httpMethod = "HEAD"
request.httpShouldUsePipelining = true request.httpShouldUsePipelining = true
let task = giphyDownloadSession.dataTask(with:request, completionHandler: { [weak self] data, response, error -> Void in let task = giphyDownloadSession.dataTask(with:request, completionHandler: { data, response, error -> Void in
if let data = data, data.count > 0 { if let data = data, data.count > 0 {
owsFail("\(self?.TAG) HEAD request has unexpected body: \(data.count).") owsFail("\(self.TAG) HEAD request has unexpected body: \(data.count).")
} }
self?.handleAssetSizeResponse(assetRequest:assetRequest, response:response, error:error) self.handleAssetSizeResponse(assetRequest:assetRequest, response:response, error:error)
}) })
assetRequest.contentLengthTask = task assetRequest.contentLengthTask = task
task.resume() task.resume()
@ -659,7 +664,7 @@ extension URLSessionTask {
} }
// Recurse; we may be able to start multiple downloads. // Recurse; we may be able to start multiple downloads.
processRequestQueue() processRequestQueueSync()
} }
private func handleAssetSizeResponse(assetRequest: GiphyAssetRequest, response: URLResponse?, error: Error?) { private func handleAssetSizeResponse(assetRequest: GiphyAssetRequest, response: URLResponse?, error: Error?) {
@ -696,7 +701,7 @@ extension URLSessionTask {
DispatchQueue.main.async { DispatchQueue.main.async {
assetRequest.contentLength = contentLength assetRequest.contentLength = contentLength
assetRequest.state = .active assetRequest.state = .active
self.processRequestQueue() self.processRequestQueueSync()
} }
} }

Loading…
Cancel
Save