diff --git a/.gitignore b/.gitignore
index acb159a..bb9d983 100755
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ DerivedData/
mqtt_password.txt
.env
.smbdelete*
+buildServer.json
+.nvim/*
diff --git a/.swiftpm/dewpoint-controller-Package.xctestplan b/.swiftpm/dewpoint-controller-Package.xctestplan
new file mode 100644
index 0000000..5e8bdf3
--- /dev/null
+++ b/.swiftpm/dewpoint-controller-Package.xctestplan
@@ -0,0 +1,35 @@
+{
+ "configurations" : [
+ {
+ "id" : "AFB1047B-4742-43D2-AFB9-680C1CB2D273",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:",
+ "identifier" : "dewpoint-controller",
+ "name" : "dewpoint-controller"
+ }
+ },
+ "testTargets" : [
+ {
+ "target" : {
+ "containerPath" : "container:",
+ "identifier" : "MQTTConnectionServiceTests",
+ "name" : "MQTTConnectionServiceTests"
+ }
+ },
+ {
+ "target" : {
+ "containerPath" : "container:",
+ "identifier" : "SensorsServiceTests",
+ "name" : "SensorsServiceTests"
+ }
+ }
+ ],
+ "version" : 1
+}
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/DewPointEnvironment.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/DewPointEnvironment.xcscheme
deleted file mode 100755
index 1a3b0b2..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/DewPointEnvironment.xcscheme
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/EnvVars.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/EnvVars.xcscheme
deleted file mode 100755
index 1983919..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/EnvVars.xcscheme
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/ClientLive.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/MQTTConnectionService.xcscheme
old mode 100755
new mode 100644
similarity index 77%
rename from .swiftpm/xcode/xcshareddata/xcschemes/ClientLive.xcscheme
rename to .swiftpm/xcode/xcshareddata/xcschemes/MQTTConnectionService.xcscheme
index 3327fe3..45f5e1a
--- a/.swiftpm/xcode/xcshareddata/xcschemes/ClientLive.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/MQTTConnectionService.xcscheme
@@ -1,10 +1,11 @@
+ LastUpgradeVersion = "1610"
+ version = "1.7">
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
@@ -26,9 +27,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES">
-
-
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Bootstrap.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/MQTTManager.xcscheme
old mode 100755
new mode 100644
similarity index 79%
rename from .swiftpm/xcode/xcshareddata/xcschemes/Bootstrap.xcscheme
rename to .swiftpm/xcode/xcshareddata/xcschemes/MQTTManager.xcscheme
index fc5f894..a9416cb
--- a/.swiftpm/xcode/xcshareddata/xcschemes/Bootstrap.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/MQTTManager.xcscheme
@@ -1,10 +1,11 @@
+ LastUpgradeVersion = "1610"
+ version = "1.7">
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
@@ -26,9 +27,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES">
-
-
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Client.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SensorsService.xcscheme
old mode 100755
new mode 100644
similarity index 78%
rename from .swiftpm/xcode/xcshareddata/xcschemes/Client.xcscheme
rename to .swiftpm/xcode/xcshareddata/xcschemes/SensorsService.xcscheme
index 543cd43..f4e1101
--- a/.swiftpm/xcode/xcshareddata/xcschemes/Client.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/SensorsService.xcscheme
@@ -1,10 +1,11 @@
+ LastUpgradeVersion = "1610"
+ version = "1.7">
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
@@ -26,9 +27,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES">
-
-
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller-Package.xcscheme
old mode 100755
new mode 100644
index 8f82c6f..62a0843
--- a/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller-Package.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller-Package.xcscheme
@@ -1,10 +1,11 @@
+ LastUpgradeVersion = "1610"
+ version = "1.7">
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
@@ -28,51 +29,9 @@
buildForAnalyzing = "YES">
-
-
-
-
-
-
-
-
-
-
-
-
@@ -90,62 +49,6 @@
ReferencedContainer = "container:">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
@@ -239,9 +142,9 @@
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller.xcscheme
old mode 100755
new mode 100644
index 7e9546e..2ccaeb1
--- a/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/dewPoint-controller.xcscheme
@@ -1,10 +1,11 @@
+ LastUpgradeVersion = "1610"
+ version = "1.7">
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
-
-
-
-
-
-
-
-
@@ -54,29 +27,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES">
-
-
-
-
-
-
-
-
-
-
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
@@ -109,9 +61,9 @@
runnableDebuggingMode = "0">
diff --git a/Makefile b/Makefile
index 3ff79d4..9ec2468 100755
--- a/Makefile
+++ b/Makefile
@@ -20,3 +20,10 @@ test-docker:
@docker compose --file docker/docker-compose-test.yaml \
run --build --remove-orphans -i --rm test
@docker compose --file docker/docker-compose-test.yaml down
+
+start-mosquitto:
+ @docker compose --file docker/docker-compose.yaml \
+ up -d mosquitto
+
+test-swift: start-mosquitto
+ @swift test --enable-code-coverage
diff --git a/Package.swift b/Package.swift
index 92bb0a8..86e17da 100755
--- a/Package.swift
+++ b/Package.swift
@@ -73,6 +73,7 @@ let package = Package(
dependencies: [
"MQTTConnectionService",
"MQTTManager",
+ .product(name: "PsychrometricClientLive", package: "swift-psychrometrics"),
.product(name: "ServiceLifecycleTestKit", package: "swift-service-lifecycle")
]
),
@@ -84,6 +85,7 @@ let package = Package(
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies"),
.product(name: "MQTTNIO", package: "mqtt-nio"),
+ .product(name: "PsychrometricClient", package: "swift-psychrometrics"),
.product(name: "ServiceLifecycle", package: "swift-service-lifecycle")
],
swiftSettings: swiftSettings
diff --git a/Sources/MQTTConnectionService/MQTTConnectionService.swift b/Sources/MQTTConnectionService/MQTTConnectionService.swift
index 438316c..fd5e85f 100644
--- a/Sources/MQTTConnectionService/MQTTConnectionService.swift
+++ b/Sources/MQTTConnectionService/MQTTConnectionService.swift
@@ -19,19 +19,22 @@ public struct MQTTConnectionService: Service {
/// to the MQTT broker and handles graceful shutdown of the
/// connection.
public func run() async throws {
+ try await mqtt.connect()
+
try await withGracefulShutdownHandler {
- try await mqtt.connect()
for await event in try mqtt.connectionStream().cancelOnGracefulShutdown() {
// We don't really need to do anything with the events, so just logging
// for now. But we need to iterate on an async stream for the service to
// continue to run and handle graceful shutdowns.
logger?.trace("Received connection event: \(event)")
}
- // when we reach here we are shutting down, so we shutdown
- // the manager.
- mqtt.shutdown()
} onGracefulShutdown: {
self.logger?.trace("Received graceful shutdown.")
+ shutdown()
}
}
+
+ public func shutdown() {
+ mqtt.shutdown()
+ }
}
diff --git a/Sources/MQTTManager/Interface.swift b/Sources/MQTTManager/Interface.swift
index 2307aa1..c618782 100644
--- a/Sources/MQTTManager/Interface.swift
+++ b/Sources/MQTTManager/Interface.swift
@@ -183,6 +183,7 @@ public extension MQTTManager {
)
},
shutdown: {
+ Task { try await client.shutdown() }
manager.shutdown()
},
_withClient: { callback in
diff --git a/Tests/MQTTConnectionServiceTests/MQTTConnectionServiceTests.swift b/Tests/MQTTConnectionServiceTests/MQTTConnectionServiceTests.swift
index bcd9651..8940623 100644
--- a/Tests/MQTTConnectionServiceTests/MQTTConnectionServiceTests.swift
+++ b/Tests/MQTTConnectionServiceTests/MQTTConnectionServiceTests.swift
@@ -1,24 +1,60 @@
-import AsyncAlgorithms
+import Dependencies
import Logging
import Models
import MQTTConnectionService
@_spi(Internal) import MQTTManager
import MQTTNIO
import NIO
+import PsychrometricClientLive
import ServiceLifecycle
import ServiceLifecycleTestKit
import XCTest
+// TODO: Rename to integration test when other tests are moved.
final class MQTTConnectionServiceTests: XCTestCase {
static let hostname = ProcessInfo.processInfo.environment["MOSQUITTO_SERVER"] ?? "localhost"
static let logger: Logger = {
var logger = Logger(label: "MQTTConnectionServiceTests")
- logger.logLevel = .trace
+ logger.logLevel = .info
return logger
}()
+ override func invokeTest() {
+ let client = createClient(identifier: "\(Self.self)")
+
+ withDependencies {
+ $0.mqtt = .live(client: client, logger: Self.logger)
+ $0.psychrometricClient = PsychrometricClient.liveValue
+ } operation: {
+ super.invokeTest()
+ }
+ }
+
+ func testConnectionServiceShutdown() async throws {
+ @Dependency(\.mqtt) var mqtt
+
+ let service = MQTTConnectionService(logger: Self.logger)
+ let task = Task { try await service.run() }
+ defer { task.cancel() }
+
+ try await Task.sleep(for: .milliseconds(200))
+
+ // check the connection is active here.
+ try await mqtt.withClient { client in
+ XCTAssert(client.isActive())
+ }
+ service.shutdown()
+
+ try await Task.sleep(for: .milliseconds(500))
+
+ // check the connection is active here.
+ try await mqtt.withClient { client in
+ XCTAssertFalse(client.isActive())
+ }
+ }
+
// TODO: Move to integration tests.
func testMQTTConnectionStream() async throws {
let client = createClient(identifier: "testNonManagedStream")
@@ -43,11 +79,10 @@ final class MQTTConnectionServiceTests: XCTestCase {
try await Task.sleep(for: .milliseconds(100))
}
try await Task.sleep(for: .milliseconds(200))
- manager.shutdown()
try await client.disconnect()
- try await Task.sleep(for: .seconds(1))
- try await client.shutdown()
- try await Task.sleep(for: .seconds(1))
+ try await Task.sleep(for: .milliseconds(500))
+ manager.shutdown()
+ try await Task.sleep(for: .milliseconds(500))
connectionStream1.stop()
connectionStream2.stop()
}