From 9b5032e62bca132041f55d66e62ba3d5799a4427 Mon Sep 17 00:00:00 2001 From: Kyle Browning Date: Wed, 21 Aug 2024 07:33:04 -0700 Subject: [PATCH] Updating project for strict concurrency and Swift 6 (#207) --- .github/workflows/swift.yml | 12 +++--- Package.swift | 12 ++++-- Sources/APNS/APNSClient.swift | 22 ++--------- Sources/APNSCore/APNSClient.swift | 1 + Sources/APNSExample/Program.swift | 38 ++++++++++++++----- .../APNSURLSession/APNSUrlSessionClient.swift | 5 +++ Tests/APNSTests/APNSClientTests.swift | 4 +- 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index cb4c4f62..cf02ac7f 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -4,22 +4,22 @@ on: jobs: focal: container: - image: swift:5.7-focal + image: swiftlang/swift:nightly-6.0-focal runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - run: swift test --enable-test-discovery + - run: swift test thread: container: - image: swift:5.7-focal + image: swiftlang/swift:nightly-6.0-focal runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - run: swift test --enable-test-discovery --sanitize=thread + - run: swift test --sanitize=thread address: container: - image: swift:5.7-focal + image: swiftlang/swift:nightly-6.0-focal runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - run: ASAN_OPTIONS=detect_leaks=0 swift test --enable-test-discovery --sanitize=address + - run: ASAN_OPTIONS=detect_leaks=0 swift test --sanitize=address diff --git a/Package.swift b/Package.swift index 27acfe6e..c09ab920 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.7 +// swift-tools-version:6.0 import PackageDescription let package = Package( @@ -31,13 +31,16 @@ let package = Package( dependencies: [ .target(name: "APNSCore"), .target(name: "APNS"), - ]), + .product(name: "Logging", package: "swift-log"), + ] + ), .testTarget( name: "APNSTests", dependencies: [ .target(name: "APNSCore"), .target(name: "APNS"), - ]), + ] + ), .target( name: "APNSCore", dependencies: [ @@ -70,5 +73,6 @@ let package = Package( .target(name: "APNSCore"), ] ), - ] + ], + swiftLanguageVersions: [.v6] ) diff --git a/Sources/APNS/APNSClient.swift b/Sources/APNS/APNSClient.swift index f6c8c2bc..e277e334 100644 --- a/Sources/APNS/APNSClient.swift +++ b/Sources/APNS/APNSClient.swift @@ -14,7 +14,6 @@ import APNSCore import AsyncHTTPClient -import Dispatch import struct Foundation.Date import struct Foundation.UUID import NIOConcurrencyHelpers @@ -114,24 +113,9 @@ public final class APNSClient Void) { - self.httpClient.shutdown(callback) - } - - /// Shuts down the client and `EventLoopGroup` if it was created by the client. - public func syncShutdown() throws { - try self.httpClient.syncShutdown() + /// Shuts down the client gracefully. + public func shutdown() async throws { + try await self.httpClient.shutdown() } } diff --git a/Sources/APNSCore/APNSClient.swift b/Sources/APNSCore/APNSClient.swift index 8c1b5a2e..ee11f37f 100644 --- a/Sources/APNSCore/APNSClient.swift +++ b/Sources/APNSCore/APNSClient.swift @@ -14,4 +14,5 @@ public protocol APNSClientProtocol { func send(_ request: APNSRequest) async throws -> APNSResponse + func shutdown() async throws } diff --git a/Sources/APNSExample/Program.swift b/Sources/APNSExample/Program.swift index f3da2a77..bc5dc09e 100644 --- a/Sources/APNSExample/Program.swift +++ b/Sources/APNSExample/Program.swift @@ -14,8 +14,11 @@ import APNSCore import APNS +import Logging import Foundation +let logger = Logger(label: "APNSwiftExample") + @available(macOS 11.0, *) @main struct Main { @@ -30,7 +33,9 @@ struct Main { static let keyIdentifier = "" static let teamIdentifier = "" + static func main() async throws { + let client = APNSClient( configuration: .init( authenticationMethod: .jwt( @@ -45,15 +50,21 @@ struct Main { requestEncoder: JSONEncoder() ) - try await Self.sendSimpleAlert(with: client) - try await Self.sendLocalizedAlert(with: client) - try await Self.sendThreadedAlert(with: client) - try await Self.sendCustomCategoryAlert(with: client) - try await Self.sendMutableContentAlert(with: client) - try await Self.sendBackground(with: client) - try await Self.sendVoIP(with: client) - try await Self.sendFileProvider(with: client) - try await Self.sendPushToTalk(with: client) + do { + try await Self.sendSimpleAlert(with: client) + try await Self.sendLocalizedAlert(with: client) + try await Self.sendThreadedAlert(with: client) + try await Self.sendCustomCategoryAlert(with: client) + try await Self.sendMutableContentAlert(with: client) + try await Self.sendBackground(with: client) + try await Self.sendVoIP(with: client) + try await Self.sendFileProvider(with: client) + try await Self.sendPushToTalk(with: client) + } catch { + logger.warning("error sending push: \(error)") + } + + try? await client.shutdown() } } @@ -77,6 +88,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent simple alert notification") } static func sendLocalizedAlert(with client: some APNSClientProtocol) async throws { @@ -95,6 +107,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent alert localized notification") } static func sendThreadedAlert(with client: some APNSClientProtocol) async throws { @@ -114,6 +127,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent threaded alert") } static func sendCustomCategoryAlert(with client: some APNSClientProtocol) async throws { @@ -133,6 +147,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent custom category alert") } static func sendMutableContentAlert(with client: some APNSClientProtocol) async throws { @@ -152,6 +167,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent mutable content alert") } } @@ -168,6 +184,7 @@ extension Main { ), deviceToken: self.deviceToken ) + logger.info("successfully sent background notification") } } @@ -185,6 +202,7 @@ extension Main { ), deviceToken: self.pushKitDeviceToken ) + logger.info("successfully sent VoIP notification") } } @@ -201,6 +219,7 @@ extension Main { ), deviceToken: self.fileProviderDeviceToken ) + logger.info("successfully sent FileProvider notification") } } @@ -219,5 +238,6 @@ extension Main { ), deviceToken: self.ephemeralPushToken ) + logger.info("successfully sent Push to Talk notification") } } diff --git a/Sources/APNSURLSession/APNSUrlSessionClient.swift b/Sources/APNSURLSession/APNSUrlSessionClient.swift index ea0c0eac..c70c6edd 100644 --- a/Sources/APNSURLSession/APNSUrlSessionClient.swift +++ b/Sources/APNSURLSession/APNSUrlSessionClient.swift @@ -7,6 +7,7 @@ enum APNSUrlSessionClientError: Error { } public struct APNSURLSessionClient: APNSClientProtocol { + private let configuration: APNSURLSessionClientConfiguration let encoder = JSONEncoder() @@ -61,6 +62,10 @@ public struct APNSURLSessionClient: APNSClientProtocol { return APNSResponse(apnsID: apnsID, apnsUniqueID: apnsUniqueID) } } + + public func shutdown() async throws { + // no op + } } #endif diff --git a/Tests/APNSTests/APNSClientTests.swift b/Tests/APNSTests/APNSClientTests.swift index e639179d..d04679ca 100644 --- a/Tests/APNSTests/APNSClientTests.swift +++ b/Tests/APNSTests/APNSClientTests.swift @@ -18,9 +18,9 @@ import Crypto import XCTest final class APNSClientTests: XCTestCase { - func testShutdown() throws { + func testShutdown() async throws { let client = self.makeClient() - try client.syncShutdown() + try await client.shutdown() } // MARK: - Helper methods