feat: Fixes some tests and docker builds
This commit is contained in:
@@ -3,6 +3,7 @@ import DependenciesMacros
|
||||
import Foundation
|
||||
import Logging
|
||||
import Models
|
||||
import MQTTConnectionManager
|
||||
import MQTTNIO
|
||||
import NIO
|
||||
import PsychrometricClient
|
||||
@@ -16,6 +17,7 @@ import TopicDependencies
|
||||
///
|
||||
public actor SensorsService: Service {
|
||||
|
||||
@Dependency(\.mqttConnectionManager.stream) var connectionStream
|
||||
@Dependency(\.topicListener) var topicListener
|
||||
@Dependency(\.topicPublisher) var topicPublisher
|
||||
|
||||
@@ -55,25 +57,41 @@ public actor SensorsService: Service {
|
||||
public func run() async throws {
|
||||
precondition(sensors.count > 0, "Sensors should not be empty.")
|
||||
|
||||
let stream = try await makeStream()
|
||||
|
||||
await withGracefulShutdownHandler {
|
||||
await withDiscardingTaskGroup { group in
|
||||
for await result in stream.cancelOnGracefulShutdown() {
|
||||
logger?.trace("Received result for topic: \(result.topic)")
|
||||
group.addTask { await self.handleResult(result) }
|
||||
try await withGracefulShutdownHandler {
|
||||
// Listen for connection events, so that we can automatically
|
||||
// reconnect any sensor topics we're listening to upon a disconnect / reconnect
|
||||
// event. We can also shutdown any topic listeners upon a shutdown event.
|
||||
for await event in try connectionStream().cancelOnGracefulShutdown() {
|
||||
switch event {
|
||||
case .shuttingDown:
|
||||
logger?.debug("Received shutdown event.")
|
||||
try await self.shutdown()
|
||||
case .disconnected:
|
||||
logger?.debug("Received disconnected event.")
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
case .connected:
|
||||
logger?.debug("Received connected event.")
|
||||
let stream = try await makeStream()
|
||||
for await result in stream.cancelOnGracefulShutdown() {
|
||||
logger?.debug("Received result for topic: \(result.topic)")
|
||||
await self.handleResult(result)
|
||||
}
|
||||
}
|
||||
// group.cancelAll()
|
||||
}
|
||||
} onGracefulShutdown: {
|
||||
Task {
|
||||
self.logger?.trace("Received graceful shutdown.")
|
||||
try? await self.publishUpdates()
|
||||
await self.topicListener.shutdown()
|
||||
self.logger?.debug("Received graceful shutdown.")
|
||||
try await self.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public func shutdown() async throws {
|
||||
try await publishUpdates()
|
||||
topicListener.shutdown()
|
||||
}
|
||||
|
||||
private func makeStream() async throws -> AsyncStream<(buffer: ByteBuffer, topic: String)> {
|
||||
try await topicListener.listen(to: topics)
|
||||
// ignore errors, so that we continue to listen, but log them
|
||||
@@ -81,7 +99,7 @@ public actor SensorsService: Service {
|
||||
.compactMap { result in
|
||||
switch result {
|
||||
case let .failure(error):
|
||||
self.logger?.trace("Received error listening for sensors: \(error)")
|
||||
self.logger?.debug("Received error listening for sensors: \(error)")
|
||||
return nil
|
||||
case let .success(info):
|
||||
return (info.payload, info.topicName)
|
||||
@@ -100,7 +118,7 @@ public actor SensorsService: Service {
|
||||
do {
|
||||
let topic = result.topic
|
||||
assert(topics.contains(topic))
|
||||
logger?.trace("Begin handling result for topic: \(topic)")
|
||||
logger?.debug("Begin handling result for topic: \(topic)")
|
||||
|
||||
func decode<V: BufferInitalizable>(_: V.Type) -> V? {
|
||||
var buffer = result.buffer
|
||||
@@ -108,28 +126,28 @@ public actor SensorsService: Service {
|
||||
}
|
||||
|
||||
if topic.contains("temperature") {
|
||||
logger?.trace("Begin handling temperature result.")
|
||||
logger?.debug("Begin handling temperature result.")
|
||||
guard let temperature = decode(DryBulb.self) else {
|
||||
logger?.trace("Failed to decode temperature: \(result.buffer)")
|
||||
logger?.debug("Failed to decode temperature: \(result.buffer)")
|
||||
throw DecodingError()
|
||||
}
|
||||
logger?.trace("Decoded temperature: \(temperature)")
|
||||
logger?.debug("Decoded temperature: \(temperature)")
|
||||
try sensors.update(topic: topic, keyPath: \.temperature, with: temperature)
|
||||
|
||||
} else if topic.contains("humidity") {
|
||||
logger?.trace("Begin handling humidity result.")
|
||||
logger?.debug("Begin handling humidity result.")
|
||||
guard let humidity = decode(RelativeHumidity.self) else {
|
||||
logger?.trace("Failed to decode humidity: \(result.buffer)")
|
||||
logger?.debug("Failed to decode humidity: \(result.buffer)")
|
||||
throw DecodingError()
|
||||
}
|
||||
logger?.trace("Decoded humidity: \(humidity)")
|
||||
logger?.debug("Decoded humidity: \(humidity)")
|
||||
try sensors.update(topic: topic, keyPath: \.humidity, with: humidity)
|
||||
}
|
||||
|
||||
try await publishUpdates()
|
||||
logger?.trace("Done handling result for topic: \(topic)")
|
||||
logger?.debug("Done handling result for topic: \(topic)")
|
||||
} catch {
|
||||
logger?.error("Received error: \(error)")
|
||||
logger?.error("Received error while handling result: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +159,7 @@ public actor SensorsService: Service {
|
||||
qos: .exactlyOnce,
|
||||
retain: true
|
||||
)
|
||||
logger?.trace("Published update to topic: \(topic)")
|
||||
logger?.debug("Published update to topic: \(topic)")
|
||||
}
|
||||
|
||||
private func publishUpdates() async throws {
|
||||
|
||||
Reference in New Issue
Block a user