Skip to main content

cognee_http_server/
lifecycle.rs

1//! Server startup and shutdown lifecycle hooks.
2//!
3//! The closed `cognee-http-cloud` crate provides its own bootstrap that
4//! seeds the `principals` / `users` / `tenants` tables; OSS keeps the
5//! sync-registry sweep + pipeline-registry shutdown that are DB-free.
6
7use thiserror::Error;
8use uuid::Uuid;
9
10/// Errors that can occur during server lifecycle transitions.
11#[derive(Debug, Error)]
12pub enum LifecycleError {
13    /// Database migration failed.
14    #[error("migration failed: {0}")]
15    MigrationFailed(String),
16
17    /// Bootstrap of default principals failed.
18    #[error("bootstrap failed: {0}")]
19    BootstrapFailed(String),
20}
21
22/// All-zero UUID โ€” matches Python's `default_user_id`.
23const DEFAULT_USER_ID_HEX: &str = "00000000000000000000000000000000";
24
25/// Called once before the router is handed to `axum::serve`.
26///
27/// OSS-side bootstrap is a no-op: the synthetic default user is
28/// DB-free (no `principals`/`users`/`user_tenants` rows to seed). Closed
29/// `cognee-http-cloud` provides its own startup hook that seeds the
30/// `(default_user, default_tenant)` rows per `tenants.md ยง6`.
31pub async fn on_startup(_state: &crate::state::AppState) -> Result<(), LifecycleError> {
32    tracing::info!("Backend server has started");
33    Ok(())
34}
35
36/// Convenience accessor โ€” for callers that need the well-known IDs.
37pub fn default_user_id() -> Uuid {
38    Uuid::parse_str(DEFAULT_USER_ID_HEX).unwrap_or(Uuid::nil())
39}
40
41/// Called on graceful shutdown (SIGTERM / SIGINT).
42pub async fn on_shutdown(state: &crate::state::AppState) {
43    tracing::info!("Backend server is shutting down");
44
45    if let Err(e) = state.pipelines.shutdown().await {
46        tracing::warn!("pipeline registry shutdown failed (non-fatal): {e}");
47    } else {
48        tracing::info!("pipeline registry shutdown complete");
49    }
50
51    // Abort every in-flight cloud sync โ€” the durable-row "mark failed"
52    // step moved closed alongside `SyncOperationRepository`.
53    let aborted = state.sync.abort_all();
54    if !aborted.is_empty() {
55        tracing::info!(
56            "aborted {} in-flight cloud sync(s) on shutdown",
57            aborted.len()
58        );
59    }
60}