But this doesn't seem to work in Swift 5.7 as the app terminates and the compiler gives this warning:
Instance method 'run' is unavailable from asynchronous contexts; run cannot be used from async contexts.; this is an error in Swift 6
I was able to find a hack workaround using CheckedContinuation...
static func main() async throws {
// setup app
#if swift(>=5.7)
// FIXME: Find a better workaround than this
var strongDone: CheckedContinuation<Void, Never>?
await withCheckedContinuation({ (done: CheckedContinuation<Void, Never>) in
strongDone = done
})
print(String(describing: strongDone)) // avoids `Variable 'strongDone' was written to, but never read`
#else
RunLoop.main.run()
#endif
}
But that doesn't seem like the right thing to do.
I think an alternative would be to get rid of the async from main() and throw any async tasks in a Task.
Is that the correct approach? Or is there a replacement to RunLoop.main.run() when in an async context (i.e. await <app termination>)?
By using an UnsafeContinuation you don't need to store it since CheckedContinuation will crash your app if the continuation is deinitialized before resumed. So you could implement a park function which never resumes
func park() async -> Never {
await withUnsafeContinuation { _ in }
}
and then you can suspend the task basically forever
I think this is a good opportunity to substantially reconsider the way this code is written in order to take advantage of structured concurrency.
Ideally you'd write your daemon as an object that operates on a Task tree. The root Task is responsible for defining the lifetime of the daemon itself, and is listening for new work (however you consume it). It them spawns child tasks to handle instances of the work. We have something of an example in the SwiftNIO repository, though we haven't entirely finalised the pattern.
The advantage of this is that your daemon can now rely on all the guarantees of structured concurrency, including ensuring that task lifetimes are well bounded and that errors propagate as you want them to.