How to use async/await w/ docker

I have a simple swift script that I wrote and created a docker image containing this script. The script makes a network call using URLSession and operates on the data to determine success/failure of the script. I wanted to try out migrating this to using async/await, so I changed the base image of my dockerfile to swiftlang/swift:nightly-5.5-bionic, however when running my swiftc command as part of the docker build, I am getting the output below:

#8 1.211 main.swift:43:32: error: type of expression is ambiguous without more context
#8 1.211     let (data, response) = try await URLSession.shared.data(with: request)
#8 1.211                            ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I am not sure what I am doing wrong, but maybe there are more steps to enable concurrency features. Any help would be really appreciated.

Thanks!

1 Like

swift-corelibs-foundation does not currently provide the async/await APIs that are available in the version of Foundation in the Xcode 13 beta.

Thank you. Is there a thread or discussion I can follow to track the progress of those APIs being included in swift-corelibs-foundation?

Not that I'm aware of: @millenomi is the best person to speak to this.

1 Like

There isn't much I can say at this specific time, other than that we definitely know the desire is there from the community for these API to be available.

Thanks @millenomi. I think if the desire is to have Swift be a serious contender on non-Apple platforms, async/await APIs are critical across the board.

1 Like

@millenomi is there any update on the availability of these APIs?

We're working on its prerequisites. (Thank you, @David_Smith.)

3 Likes

Awesome! I will keep my eye out on that PR and the other progress there. Thanks so much.

Hey @millenomi just wondering if there were any updates. I have been paying attention to the PR, but other than occasional test requests, there's not much activity.

@brendankirchner It's not ideal, but here's the shim I made myself to get me going on Linux:

#if canImport(FoundationNetworking)
// The async APIs aren't available on FoundationNetworking, so I'll define my own.
extension URLSession {
    func data(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) {
        return try await withUnsafeThrowingContinuation { continuation in
            let sessionDataTask = self.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
                switch (data, response, error) {
                case (      nil,           nil, let error?): continuation.resume(throwing: error)
                case (let data?, let response?,        nil): continuation.resume(returning: (data, response))
                default: fatalError("The data and response should be non-nil if there's no error!")
                }
            }

            sessionDataTask.resume()
        }

    }
}
#endif

This worked excellently. I can't believe I didn't think to do something like this. Thank you!

1 Like

This doesn't have the same semantics as Darwin, because Darwin ensures task cancellation trickles down into canceling the connection, which isn't occurring here.