Skip to content

Remove platforms from manifest #203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ import PackageDescription

let package = Package(
name: "swift-service-lifecycle",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.watchOS(.v6),
.tvOS(.v13),
],
products: [
.library(
name: "ServiceLifecycle",
Expand All @@ -30,7 +24,7 @@ let package = Package(
),
.package(
url: "https://github.com/apple/swift-async-algorithms.git",
from: "1.0.0"
from: "1.0.4"
),
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import AsyncAlgorithms

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension AsyncSequence where Self: Sendable, Element: Sendable {
/// Creates an asynchronous sequence that is cancelled once graceful shutdown has triggered.
///
Expand All @@ -24,6 +25,7 @@ extension AsyncSequence where Self: Sendable, Element: Sendable {
}

/// An asynchronous sequence that is cancelled once graceful shutdown has triggered.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public struct AsyncCancelOnGracefulShutdownSequence<Base: AsyncSequence & Sendable>: AsyncSequence, Sendable
where Base.Element: Sendable {
@usableFromInline
Expand Down Expand Up @@ -101,6 +103,7 @@ where Base.Element: Sendable {
/// This is just a helper extension and sequence to allow us to get the `nil` value as an element of the sequence.
/// We need this since merge is only finishing when both upstreams are finished but we need to finish when either is done.
/// In the future, we should move to something in async algorithms if it exists.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension AsyncSequence where Self: Sendable, Element: Sendable {
@inlinable
func mapNil() -> AsyncMapNilSequence<Self> {
Expand All @@ -109,6 +112,7 @@ extension AsyncSequence where Self: Sendable, Element: Sendable {
}

@usableFromInline
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
struct AsyncMapNilSequence<Base: AsyncSequence & Sendable>: AsyncSequence, Sendable where Base.Element: Sendable {
@usableFromInline
enum ElementOrEnd: Sendable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
///
/// - Note: This sequence respects cancellation and thus is `throwing`.
@usableFromInline
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
struct AsyncGracefulShutdownSequence: AsyncSequence, Sendable {
@usableFromInline
typealias Element = CancellationWaiter.Reason
Expand Down
1 change: 1 addition & 0 deletions Sources/ServiceLifecycle/CancellationWaiter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

/// An actor that provides a function to wait on cancellation/graceful shutdown.
@usableFromInline
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
actor CancellationWaiter {
@usableFromInline
enum Reason: Sendable {
Expand Down
12 changes: 12 additions & 0 deletions Sources/ServiceLifecycle/GracefulShutdown.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import ConcurrencyHelpers
/// - handler: The handler which is invoked once graceful shutdown has been triggered.
// Unsafely inheriting the executor is safe to do here since we are not calling any other async method
// except the operation. This makes sure no other executor hops would occur here.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func withGracefulShutdownHandler<T>(
isolation: isolated (any Actor)? = #isolation,
operation: () async throws -> T,
Expand All @@ -58,6 +59,7 @@ public func withGracefulShutdownHandler<T>(
}

@available(*, deprecated, message: "Use the method with the isolation parameter instead.")
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
@_disfavoredOverload
public func withGracefulShutdownHandler<T>(
operation: () async throws -> T,
Expand All @@ -83,6 +85,7 @@ public func withGracefulShutdownHandler<T>(
// Swift versions since the semantics changed.
@_disfavoredOverload
@_unsafeInheritExecutor
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func withGracefulShutdownHandler<T>(
operation: () async throws -> T,
onGracefulShutdown handler: @Sendable @escaping () -> Void
Expand Down Expand Up @@ -127,6 +130,7 @@ public func withGracefulShutdownHandler<T>(
/// - handler: The handler which is invoked once graceful shutdown or task cancellation has been triggered.
// Unsafely inheriting the executor is safe to do here since we are not calling any other async method
// except the operation. This makes sure no other executor hops would occur here.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func withTaskCancellationOrGracefulShutdownHandler<T>(
isolation: isolated (any Actor)? = #isolation,
operation: () async throws -> T,
Expand All @@ -139,6 +143,7 @@ public func withTaskCancellationOrGracefulShutdownHandler<T>(
}
}
@available(*, deprecated, message: "Use the method with the isolation parameter instead.")
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
@_disfavoredOverload
public func withTaskCancellationOrGracefulShutdownHandler<T>(
operation: () async throws -> T,
Expand All @@ -152,6 +157,7 @@ public func withTaskCancellationOrGracefulShutdownHandler<T>(
}
#else
@available(*, deprecated, message: "Use the method with the isolation parameter instead.")
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
@_disfavoredOverload
@_unsafeInheritExecutor
public func withTaskCancellationOrGracefulShutdownHandler<T>(
Expand All @@ -172,6 +178,7 @@ public func withTaskCancellationOrGracefulShutdownHandler<T>(
/// graceful shutdown is triggered then this method will throw a `CancellationError`.
///
/// - Throws: `CancellationError` if the task is cancelled.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func gracefulShutdown() async throws {
switch await AsyncGracefulShutdownSequence().first(where: { _ in true }) {
case .cancelled:
Expand All @@ -193,6 +200,7 @@ enum ValueOrGracefulShutdown<T: Sendable>: Sendable {
/// Cancels the closure when a graceful shutdown was triggered.
///
/// - Parameter operation: The actual operation.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func cancelWhenGracefulShutdown<T: Sendable>(
_ operation: @Sendable @escaping () async throws -> T
) async rethrows -> T {
Expand Down Expand Up @@ -243,12 +251,14 @@ public func cancelWhenGracefulShutdown<T: Sendable>(
// renamed pattern has been shown to cause compiler crashes in 5.x compilers.
@available(*, deprecated, message: "renamed to cancelWhenGracefulShutdown")
#endif
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func cancelOnGracefulShutdown<T: Sendable>(
_ operation: @Sendable @escaping () async throws -> T
) async rethrows -> T? {
return try await cancelWhenGracefulShutdown(operation)
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension Task where Success == Never, Failure == Never {
/// A Boolean value that indicates whether the task is gracefully shutting down
///
Expand All @@ -263,13 +273,15 @@ extension Task where Success == Never, Failure == Never {
}

@_spi(TestKit)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public enum TaskLocals {
@TaskLocal
@_spi(TestKit)
public static var gracefulShutdownManager: GracefulShutdownManager?
}

@_spi(TestKit)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public final class GracefulShutdownManager: @unchecked Sendable {
struct Handler {
/// The id of the handler.
Expand Down
1 change: 1 addition & 0 deletions Sources/ServiceLifecycle/Service.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

/// This is the basic protocol that a service has to implement.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public protocol Service: Sendable {
/// This method is called when the ``ServiceGroup`` is starting all the services.
///
Expand Down
2 changes: 2 additions & 0 deletions Sources/ServiceLifecycle/ServiceGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import UnixSignals
import AsyncAlgorithms

/// A ``ServiceGroup`` is responsible for running a number of services, setting up signal handling and signalling graceful shutdown to the services.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public actor ServiceGroup: Sendable, Service {
/// The internal state of the ``ServiceGroup``.
private enum State {
Expand Down Expand Up @@ -893,6 +894,7 @@ public actor ServiceGroup: Sendable, Service {
}

// This should be removed once we support Swift 5.9+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension AsyncStream {
fileprivate static func makeStream(
of elementType: Element.Type = Element.self,
Expand Down
1 change: 1 addition & 0 deletions Sources/ServiceLifecycle/ServiceGroupConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import UnixSignals
let deprecatedLoggerLabel = "service-lifecycle-deprecated-method-logger"

/// The configuration for the ``ServiceGroup``.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public struct ServiceGroupConfiguration: Sendable {
/// The group's logging configuration.
public struct LoggingConfiguration: Sendable {
Expand Down
2 changes: 2 additions & 0 deletions Sources/ServiceLifecycleTestKit/GracefulShutdown.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
///
/// It is passed to the `operation` closure of the ``testGracefulShutdown(operation:)`` method and allows
/// to trigger the graceful shutdown for testing purposes.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public struct GracefulShutdownTestTrigger: Sendable {
private let gracefulShutdownManager: GracefulShutdownManager

Expand All @@ -35,6 +36,7 @@ public struct GracefulShutdownTestTrigger: Sendable {
///
/// Call the code that you want to test inside the `operation` closure and trigger the graceful shutdown by calling ``GracefulShutdownTestTrigger/triggerGracefulShutdown()``
/// on the ``GracefulShutdownTestTrigger`` that is passed to the `operation` closure.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func testGracefulShutdown<T>(operation: (GracefulShutdownTestTrigger) async throws -> T) async rethrows -> T {
let gracefulShutdownManager = GracefulShutdownManager()
return try await TaskLocals.$gracefulShutdownManager.withValue(gracefulShutdownManager) {
Expand Down
3 changes: 3 additions & 0 deletions Sources/UnixSignals/UnixSignalsSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import ConcurrencyHelpers
///
/// - Important: There can only be a single signal handler for a signal installed. So you should avoid creating multiple handlers
/// for the same signal.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public struct UnixSignalsSequence: AsyncSequence, Sendable {
private static let queue = DispatchQueue(label: "com.service-lifecycle.unix-signals")

Expand Down Expand Up @@ -74,6 +75,7 @@ public struct UnixSignalsSequence: AsyncSequence, Sendable {
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension UnixSignalsSequence {
fileprivate final class Storage: @unchecked Sendable {
private let stateMachine: LockedValueBox<StateMachine>
Expand Down Expand Up @@ -169,6 +171,7 @@ extension UnixSignalsSequence {
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension UnixSignalsSequence {
fileprivate struct StateMachine {
private enum State {
Expand Down
5 changes: 5 additions & 0 deletions Tests/ServiceLifecycleTests/GracefulShutdownTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ServiceLifecycle
import ServiceLifecycleTestKit
import XCTest

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
final class GracefulShutdownTests: XCTestCase {
func testWithGracefulShutdownHandler() async {
var cont: AsyncStream<Void>.Continuation!
Expand Down Expand Up @@ -255,6 +256,7 @@ final class GracefulShutdownTests: XCTestCase {
}
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
func testWaitForGracefulShutdown() async throws {
try await testGracefulShutdown { gracefulShutdownTestTrigger in
try await withThrowingTaskGroup(of: Void.self) { group in
Expand All @@ -274,6 +276,7 @@ final class GracefulShutdownTests: XCTestCase {
}
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
func testWaitForGracefulShutdown_WhenAlreadyShutdown() async throws {
try await testGracefulShutdown { gracefulShutdownTestTrigger in
gracefulShutdownTestTrigger.triggerGracefulShutdown()
Expand Down Expand Up @@ -355,6 +358,7 @@ final class GracefulShutdownTests: XCTestCase {
}
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
func testCancelWhenGracefulShutdownSurvivesCancellation() async throws {
await withTaskGroup(of: Void.self) { group in
group.addTask {
Expand All @@ -375,6 +379,7 @@ final class GracefulShutdownTests: XCTestCase {
}
}

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
func testCancelWhenGracefulShutdownSurvivesErrorThrown() async throws {
struct MyError: Error, Equatable {}

Expand Down