Compare commits

...
Author SHA1 Message Date
mackabyandZaki 5677e5e955 fix(db): invoke shutdown during runtime teardown
Call Database::shutdown() from async_main graceful shutdown after webhook/tunnel stop.

Add debug logs for libSQL no-op shutdown paths (no replicator and sync-not-supported).
2026-03-12 15:08:08 -07:00
mackabyandZaki 91e0c2ee62 feat(db): add backend shutdown hook for graceful runtime shutdown
Add Database::shutdown() with a default no-op implementation for backward compatibility.

Implement libSQL shutdown via flush_replicator(), treating SyncNotSupported as non-fatal.

Implement Postgres shutdown by closing the pool.
2026-03-12 15:06:12 -07:00
4 changed files with 38 additions and 0 deletions
+18
View File
@@ -326,6 +326,24 @@ impl Database for LibSqlBackend {
libsql_migrations::run_incremental(&conn).await?; libsql_migrations::run_incremental(&conn).await?;
Ok(()) Ok(())
} }
async fn shutdown(&self) -> Result<(), DatabaseError> {
match self.db.flush_replicator().await {
Ok(Some(frame_no)) => {
tracing::debug!("libSQL replicator flushed at frame {}", frame_no);
Ok(())
}
Ok(None) => {
tracing::debug!("No libSQL replicator to flush, skipping shutdown sync");
Ok(())
}
Err(libsql::Error::SyncNotSupported(_)) => {
tracing::debug!("libSQL sync not supported, skipping flush on shutdown");
Ok(())
}
Err(error) => Err(DatabaseError::from(error)),
}
}
} }
// ==================== Row conversion helpers ==================== // ==================== Row conversion helpers ====================
+7
View File
@@ -523,6 +523,13 @@ pub trait Database:
{ {
/// Run schema migrations for this backend. /// Run schema migrations for this backend.
async fn run_migrations(&self) -> Result<(), DatabaseError>; async fn run_migrations(&self) -> Result<(), DatabaseError>;
/// Shutdown hook for backend-specific drain/flush behavior.
///
/// Default implementation is a no-op so existing backends remain compatible.
async fn shutdown(&self) -> Result<(), DatabaseError> {
Ok(())
}
} }
#[cfg(test)] #[cfg(test)]
+5
View File
@@ -61,6 +61,11 @@ impl Database for PgBackend {
async fn run_migrations(&self) -> Result<(), DatabaseError> { async fn run_migrations(&self) -> Result<(), DatabaseError> {
self.store.run_migrations().await self.store.run_migrations().await
} }
async fn shutdown(&self) -> Result<(), DatabaseError> {
self.store.pool().close();
Ok(())
}
} }
// ==================== ConversationStore ==================== // ==================== ConversationStore ====================
+8
View File
@@ -672,6 +672,8 @@ async fn async_main() -> anyhow::Result<()> {
.as_ref() .as_ref()
.map(|db| Arc::clone(db) as Arc<dyn ironclaw::db::SettingsStore>); .map(|db| Arc::clone(db) as Arc<dyn ironclaw::db::SettingsStore>);
let db_for_shutdown = components.db.clone();
let deps = AgentDeps { let deps = AgentDeps {
store: components.db, store: components.db,
llm: components.llm, llm: components.llm,
@@ -930,6 +932,12 @@ async fn async_main() -> anyhow::Result<()> {
} }
} }
if let Some(db) = db_for_shutdown {
if let Err(e) = db.shutdown().await {
tracing::warn!("Failed to shutdown database cleanly: {}", e);
}
}
tracing::debug!("Agent shutdown complete"); tracing::debug!("Agent shutdown complete");
Ok(()) Ok(())