app.get("runner", ":version", "health") { (req) -> EventLoopFuture<Response> in let promise = req.eventLoop.makePromise(of: Response.self) let process = Process() process.executableURL = URL(fileURLWithPath: "/usr/bin/env") process.terminationHandler = { (process) in let status: HTTPResponseStatus = process.terminationStatus == 0 ? .ok : .internalServerError HealthCheckResponse(status: status) .encodeResponse( status: status, headers: HTTPHeaders([("Cache-Control", "no-store")]), for: req ) .cascade(to: promise) } process.launch() return promise.futureResult }
非同期に呼ばれるCallbackクロージャが普通のクロージャで、その中でさらに非同期処理を呼んでいるというコードがあって、コールバックの中でawaitできない、と思ったけど非同期処理の前でいったん値を返して再度awaitする、っていうのでいけた。 合ってるかな?app.get("runner", ":version", "health") { (req) -> Response in guard let version = req.parameters.get("version") else { throw Abort(.badRequest) } let process = Process() process.executableURL = URL(fileURLWithPath: "/usr/bin/env") let status: HTTPResponseStatus = await withCheckedContinuation { (continuation) in process.terminationHandler = { (process) in let status: HTTPResponseStatus = process.terminationStatus == 0 ? .ok : .internalServerError continuation.resume(returning: status) } process.launch() } return try await HealthCheckResponse(status: status) .encodeResponse( status: status, headers: HTTPHeaders([("Cache-Control", "no-store")]), for: req ) }
こうなった。 encodeResponse
がさらに呼んでいる非同期関数で、それは最初のawaitを抜けた後に呼ぶ、というふうに分解してうまくいった、ということ。