feat: wire relay API with dependency injection

- split settings module into per-struct files
- add DatabaseSettings with default in-memory SQLite path
- implement RelayApi struct with GET /relays and POST
  /relays/{id}/toggle
- wire create_relay_controller and create_label_repository into
  Application::build() with mock/real selection via cfg!(test) || CI
- register RelayApi in OpenApiService alongside existing APIs
This commit is contained in:
2026-03-04 12:47:21 +01:00
parent fd00d1925b
commit 2eebc52f17
30 changed files with 1170 additions and 670 deletions
+6 -5
View File
@@ -85,7 +85,7 @@ pub mod presentation;
type MaybeListener = Option<poem::listener::TcpListener<String>>;
fn prepare(listener: MaybeListener) -> startup::Application {
async fn prepare(listener: MaybeListener) -> startup::Application {
dotenvy::dotenv().ok();
let settings = settings::Settings::new().expect("Failed to read settings");
if !cfg!(test) {
@@ -98,7 +98,8 @@ fn prepare(listener: MaybeListener) -> startup::Application {
"Using these settings: {:?}",
settings
);
let application = startup::Application::build(settings, listener);
let application = startup::Application::build(settings, listener).await
.expect("Failed to build application");
tracing::event!(
target: "backend",
tracing::Level::INFO,
@@ -124,7 +125,7 @@ fn prepare(listener: MaybeListener) -> startup::Application {
/// an I/O error during runtime (e.g., port already in use, network issues).
#[cfg(not(tarpaulin_include))]
pub async fn run(listener: MaybeListener) -> Result<(), std::io::Error> {
let application = prepare(listener);
let application = prepare(listener).await;
application.make_app().run().await
}
@@ -137,7 +138,7 @@ fn make_random_tcp_listener() -> poem::listener::TcpListener<String> {
}
#[cfg(test)]
fn get_test_app() -> startup::App {
async fn get_test_app() -> startup::App {
let tcp_listener = make_random_tcp_listener();
prepare(Some(tcp_listener)).make_app().into()
prepare(Some(tcp_listener)).await.make_app().into()
}