From f3c59e0f3f42d272e9a0c77605b02646eec1d500 Mon Sep 17 00:00:00 2001 From: Christoph Hagen Date: Wed, 1 Nov 2023 11:52:04 +0100 Subject: [PATCH] Remove uses of Task --- Sources/App/Management/SQLiteDatabase.swift | 12 ++++---- Sources/App/Management/TableManagement.swift | 18 ++++------- Sources/App/configure.swift | 32 ++++++++++++++------ Sources/App/routes.swift | 6 ++-- Sources/Run/main.swift | 7 +---- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/Sources/App/Management/SQLiteDatabase.swift b/Sources/App/Management/SQLiteDatabase.swift index 179376a..95b49c9 100644 --- a/Sources/App/Management/SQLiteDatabase.swift +++ b/Sources/App/Management/SQLiteDatabase.swift @@ -207,18 +207,18 @@ final class SQLiteDatabase { playerNameForToken[token] != nil } - func startSession(socket: WebSocket, sessionToken token: SessionToken) -> Bool { + func startSession(socket: WebSocket, sessionToken token: SessionToken) async -> Bool { guard let player = playerNameForToken[token] else { return false } - return tables.connect(player: player, using: socket) + return await tables.connect(player: player, using: socket) } - func endSession(forSessionToken sessionToken: SessionToken) { + func endSession(forSessionToken sessionToken: SessionToken) async { guard let player = endExistingSession(forSessionToken: sessionToken) else { return } - tables.disconnect(player: player) + await tables.disconnect(player: player) } private func endExistingSession(forSessionToken token: SessionToken) -> PlayerName? { @@ -320,7 +320,7 @@ final class SQLiteDatabase { return try await tables.play(card: card, player: player, in: database) } - func disconnectAllSockets() { - tables.disconnectAllSockets() + func disconnectAllSockets() async { + await tables.disconnectAllSockets() } } diff --git a/Sources/App/Management/TableManagement.swift b/Sources/App/Management/TableManagement.swift index 760c6ca..6e7ce64 100644 --- a/Sources/App/Management/TableManagement.swift +++ b/Sources/App/Management/TableManagement.swift @@ -172,25 +172,21 @@ final class TableManagement { try await player.update(on: database) } - func connect(player: PlayerName, using socket: WebSocket) -> Bool { + func connect(player: PlayerName, using socket: WebSocket) async -> Bool { guard let table = currentTable(for: player) else { return false } let result = table.connect(player: player, using: socket) - Task { - await logConnectedPlayerCount() - } + await logConnectedPlayerCount() return result } - func disconnect(player: PlayerName) { + func disconnect(player: PlayerName) async { guard let table = currentTable(for: player) else { return } table.disconnect(player: player) - Task { - await logConnectedPlayerCount() - } + await logConnectedPlayerCount() } func performAction(player: PlayerName, action: PlayerAction) -> PlayerActionResult { @@ -257,10 +253,8 @@ final class TableManagement { return .success } - func disconnectAllSockets() { + func disconnectAllSockets() async { tables.values.forEach { $0.disconnectAllPlayers() } - Task { - await logConnectedPlayerCount() - } + await logConnectedPlayerCount() } } diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index 6d9e3e4..80a867a 100644 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -7,17 +7,27 @@ import ClairvoyantVapor var server: SQLiteDatabase! private var provider: VaporMetricProvider! = nil -private let scheduler = EventLoopScheduler() private var status: Metric! +private let scheduler = EventLoopScheduler() +private var configurationError: Error? = nil -private func update(status newStatus: ServerStatus) { +public func configure(_ app: Application) throws { + let semaphore = DispatchSemaphore(value: 0) scheduler.schedule { - _ = try? await status.update(newStatus) + do { + try await configureAsync(app) + } catch { + configurationError = error + } + semaphore.signal() + } + semaphore.wait() + if let configurationError { + throw configurationError } } -// configures your application -public func configure(_ app: Application) async throws { +private func configureAsync(_ app: Application) async throws { let storageFolder = URL(fileURLWithPath: app.directory.resourcesDirectory) let logFolder = storageFolder.appendingPathComponent("logs") @@ -31,7 +41,7 @@ public func configure(_ app: Application) async throws { name: "Status", description: "The main status of the server") - update(status: .initializing) + _ = try? await status.update(.initializing) let configPath = URL(fileURLWithPath: app.directory.resourcesDirectory) .appendingPathComponent("config.json") @@ -40,7 +50,7 @@ public func configure(_ app: Application) async throws { do { configuration = try Configuration(loadFromUrl: configPath) } catch { - update(status: .initializationFailure) + _ = try? await status.update(.initializationFailure) await monitor.log("Failed to read configuration: \(error)") // Note: If configuration can't be loaded, then the server will run on the wrong port // and access to metrics is impossible, since no tokens are loaded @@ -69,7 +79,7 @@ public func configure(_ app: Application) async throws { try await app.autoMigrate() } catch { await monitor.log("Failed to migrate database: \(error)") - update(status: .initializationFailure) + _ = try? await status.update(.initializationFailure) return } @@ -82,7 +92,9 @@ public func configure(_ app: Application) async throws { // Gracefully shut down by closing potentially open socket DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + .seconds(5)) { _ = app.server.onShutdown.always { _ in - server.disconnectAllSockets() + scheduler.schedule { + await server.disconnectAllSockets() + } } } @@ -94,7 +106,7 @@ public func configure(_ app: Application) async throws { provider.asyncScheduler = scheduler provider.registerRoutes(app) - update(status: .nominal) + _ = try? await status.update(.nominal) } func log(_ message: String) { diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index a3f34db..dfa80d3 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -199,7 +199,7 @@ func logoutPlayer(_ app: Application) { app.post("player", "logout") { request -> HTTPResponseStatus in let token = try request.header(.token) - server.endSession(forSessionToken: token) + await server.endSession(forSessionToken: token) return .ok } } @@ -239,8 +239,8 @@ func getTableForPlayer(_ app: Application) { func openWebsocket(_ app: Application) { app.webSocket("session", "start") { req, socket in socket.onText { socket, text in - guard server.startSession(socket: socket, sessionToken: text) else { - _ = socket.close() + guard await server.startSession(socket: socket, sessionToken: text) else { + try? await socket.close() return } } diff --git a/Sources/Run/main.swift b/Sources/Run/main.swift index 20872cc..6d8dae7 100644 --- a/Sources/Run/main.swift +++ b/Sources/Run/main.swift @@ -6,10 +6,5 @@ try LoggingSystem.bootstrap(from: &env) let app = Application(env) defer { app.shutdown() } -private let semaphore = DispatchSemaphore(value: 0) -Task { - try await configure(app) - semaphore.signal() -} -semaphore.wait() +try configure(app) try app.run()