Skip to content

Commit

Permalink
Overhaul service lifecycle for Structured Concurrency
Browse files Browse the repository at this point in the history
# Motivation
Since the release of Swift Concurrency the server ecosystem has adopted `async`/`await` in a lot of APIs making the user experience amazing. Another thing that Swift Concurrency introduced is Structured Concurrency which allows to create a task tree that with parent to child relations. Structured Concurrency has many benefits such as automatic cancellation and task local propagation.
The current state of this library predates the introduction of Swift Concurrency and is not inline anymore with how applications are structured that want to leverage Concurrency.

# Modification
This PR overhauls the implementation of service lifecycle completely. The reason for this is that the current implementation is very focused on how NIO based applications work before the introduction of Concurrency. Furthermore, Structured Concurrency is actually replacing part of the current functionality by providing new scoping mechanisms.
The overhauled implementation provides two primitive types. Anew `Service` protocol and a `ServiceRunner`. The former is providing a clear API which services have to conform to so that they can be run by the `ServiceRunner`.

An example usage of the types looks like this

```swift
actor FooService: Service {
    func run() async throws {}

    func shutdownGracefully() async throws {}
}
actor BarService: Service {
    func run() async throws {}

    func shutdownGracefully() async throws {}
}

let fooService = FooService()
let barService = BarService()

let runner = ServiceRunner(
    services: [fooService, barService],
   configuration: .init(),
   logger: logger
)

try await runner.run()
```

# Result
We now have a service lifecycle library that integrates nicely with Structured Concurrency. Its value add is that it solves to complex setup of the task group with the signal handling. Furthermore, it provides a currency type `Service` that can be passed to inject services.
  • Loading branch information
FranzBusch committed Mar 10, 2023
1 parent fbdb075 commit 695cde5
Show file tree
Hide file tree
Showing 38 changed files with 1,665 additions and 4,750 deletions.
2 changes: 1 addition & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 1
builder:
configs:
- documentation_targets: [Lifecycle, LifecycleNIOCompat]
- documentation_targets: [ServiceLifecycle, UnixSignals]
12 changes: 11 additions & 1 deletion .swiftformat
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
# file options

--swiftversion 5.0
--swiftversion 5.5
--exclude .build

# format options

--self insert
--patternlet inline
--ranges nospace
--stripunusedargs unnamed-only
--ifdef no-indent
--extensionacl on-declarations
--disable typeSugar # https://github.com/nicklockwood/SwiftFormat/issues/636
--disable andOperator
--disable wrapMultilineStatementBraces
--disable enumNamespaces
--disable redundantExtensionACL
--disable redundantReturn
--disable preferKeyPath
--disable sortedSwitchCases

# rules
70 changes: 48 additions & 22 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,34 +1,60 @@
// swift-tools-version:5.6
// swift-tools-version:5.7

import PackageDescription

let package = Package(
name: "swift-service-lifecycle",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.watchOS(.v6),
.tvOS(.v13),
],
products: [
.library(name: "Lifecycle", targets: ["Lifecycle"]),
.library(name: "LifecycleNIOCompat", targets: ["LifecycleNIOCompat"]),
.library(
name: "ServiceLifecycle",
targets: ["ServiceLifecycle"]
),
.library(
name: "UnixSignals",
targets: ["UnixSignals"]
),
],
dependencies: [
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-metrics.git", "1.0.0" ..< "3.0.0"),
.package(url: "https://github.com/swift-server/swift-backtrace.git", from: "1.1.1"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"), // used in tests
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
.package(
url: "https://github.com/apple/swift-log.git",
from: "1.5.2"
),
.package(
url: "https://github.com/apple/swift-docc-plugin",
from: "1.0.0"
),
],
targets: [
.target(name: "Lifecycle", dependencies: [
.product(name: "Atomics", package: "swift-atomics"),
.product(name: "Logging", package: "swift-log"),
.product(name: "Metrics", package: "swift-metrics"),
.product(name: "Backtrace", package: "swift-backtrace"),
]),

.target(name: "LifecycleNIOCompat", dependencies: [
"Lifecycle",
.product(name: "NIO", package: "swift-nio"),
]),

.testTarget(name: "LifecycleTests", dependencies: ["Lifecycle", "LifecycleNIOCompat"]),
.target(
name: "ServiceLifecycle",
dependencies: [
.product(
name: "Logging",
package: "swift-log"
),
.target(name: "UnixSignals"),
]
),
.target(
name: "UnixSignals"
),
.testTarget(
name: "ServiceLifecycleTests",
dependencies: [
.target(name: "ServiceLifecycle"),
]
),
.testTarget(
name: "UnixSignalsTests",
dependencies: [
.target(name: "UnixSignals"),
]
),
]
)
37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

37 changes: 0 additions & 37 deletions [email protected]

This file was deleted.

Loading

0 comments on commit 695cde5

Please sign in to comment.