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}