feat: Fixes some tests and docker builds

This commit is contained in:
2024-11-14 14:58:09 -05:00
parent e7a849b003
commit 163f603b69
9 changed files with 176 additions and 282 deletions

View File

@@ -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 {