karapace/crates/karapace-dbus/src/service.rs
Marco Allegretti 38be2c584d feat: karapace-dbus — socket-activated D-Bus service with 11 methods
- org.karapace.Manager1 D-Bus interface
- 11 methods: ListEnvironments, GetEnvironmentStatus, GetEnvironmentHash,
  BuildEnvironment, BuildNamedEnvironment, DestroyEnvironment, RunEnvironment,
  RenameEnvironment, ListPresets, GarbageCollect, VerifyStore
- Name-aware resolution (env_id, short_id, name, prefix)
- Desktop notifications via notify-rust (non-fatal if daemon unavailable)
- Typed serde response structs (no hand-rolled JSON)
- 30-second idle timeout for socket activation
- Hardened systemd unit: ProtectSystem=strict, ProtectHome=read-only,
  PrivateTmp, NoNewPrivileges
2026-02-22 18:38:09 +01:00

50 lines
1.6 KiB
Rust

use crate::interface::{KarapaceManager, DBUS_PATH};
use thiserror::Error;
use tracing::info;
use zbus::connection::Builder;
/// Default idle timeout before the service exits (for socket activation).
const IDLE_TIMEOUT_SECS: u64 = 30;
#[derive(Debug, Error)]
pub enum ServiceError {
#[error("DBus error: {0}")]
Dbus(#[from] zbus::Error),
}
/// Run the D-Bus service. If `idle_timeout` is Some, the service will exit
/// after that many seconds of inactivity. Use None for infinite runtime.
pub async fn run_service(store_root: String) -> Result<(), ServiceError> {
run_service_with_timeout(store_root, Some(IDLE_TIMEOUT_SECS)).await
}
pub async fn run_service_with_timeout(
store_root: String,
idle_timeout: Option<u64>,
) -> Result<(), ServiceError> {
let manager = KarapaceManager::new(store_root);
let _conn = Builder::session()?
.name("org.karapace.Manager1")?
.serve_at(DBUS_PATH, manager)?
.build()
.await?;
info!("karapace-dbus service started on session bus");
match idle_timeout {
Some(secs) => {
info!("idle timeout: {secs}s");
// In a socket-activated setup, the service exits after idle timeout.
// The D-Bus broker will restart it on next method call.
tokio::time::sleep(std::time::Duration::from_secs(secs)).await;
info!("idle timeout reached, shutting down");
}
None => {
// Run forever (e.g., when started manually for debugging)
std::future::pending::<()>().await;
}
}
Ok(())
}