[FR]: Add cancellation support to Storage async/await APIs
Description
There are many functions on FirebaseStorage with callback parameter for async operations. These functions return an object to cancel the operations. Such as StorageReference.getData(maxSize: Int64, completion: @escaping (Result<Data, Error>) -> Void) -> StorageDownloadTask.
These functions also has a wrapper function which support Swfit Concurrency.
However, these wrapper functions simply use withCheckedThrowingContinuation without any cancellation feature. It would be better that these functions also utilize withTaskCancellationHandler feature.
class Holder<T> {
var value: T?
}
public extension StorageReference {
// This is the current Firebase implementation
func dataNotCancellable(maxSize: Int64) async throws -> Data {
return try await withCheckedThrowingContinuation { continuation in
_ = self.getData(maxSize: maxSize) { result in
continuation.resume(with: result)
}
}
}
// This is the proposed implementation
func dataCancallable(maxSize: Int64) async throws -> Data {
let holder: Holder<StorageDownloadTask> = .init()
return try await withTaskCancellationHandler(operation: {
try await withCheckedThrowingContinuation { continuation in
holder.value = self.getData(maxSize: maxSize) { result in
continuation.resume(with: result)
}
}
}, onCancel: {
holder.value?.cancel()
})
}
}
API Proposal
No response
Firebase Product(s)
Storage
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
@fthdgn Thanks! At first glance, this looks like a great suggestion to me. We'll take a deeper look and likely add to an upcoming release. In the meantime, we'd be happy to review a PR that flushes it out further.
Any additional suggestions about how to use and test the cancellation feature on the Swift Concurrency variation of the Storage APIs?
How does cancellation get exposed to the API client? Without including the StorageDownloadTask in the API it's not clear how cancellation can ever happen.