use anyhow::{Context, Result};
use deadpool_postgres::Pool;
use fraiseql_db::postgres::PostgresTlsConfig;
pub struct CursorRow {
pub source_name: String,
pub value: Option<serde_json::Value>,
pub version: i64,
pub updated_at: String,
pub age_seconds: f64,
}
pub struct SourceCursorReader {
pool: Pool,
}
impl SourceCursorReader {
pub async fn connect(db_url: &str, tls: &PostgresTlsConfig) -> Result<Self> {
let pool = crate::connection::postgres_pool(db_url, "source cursor reads", tls).await?;
Ok(Self { pool })
}
pub async fn load_cursors(&self) -> Result<Vec<CursorRow>> {
let client = self.pool.get().await.context("failed to acquire DB connection")?;
let rows = client
.query(
"SELECT source_name, cursor_value, version, updated_at::text AS updated_at_text, \
EXTRACT(EPOCH FROM (now() - updated_at))::float8 AS age_seconds \
FROM _fraiseql_source_cursor",
&[],
)
.await
.context(
"failed to read _fraiseql_source_cursor (is the source subsystem initialized?)",
)?;
Ok(rows
.iter()
.map(|row| CursorRow {
source_name: row.get("source_name"),
value: row.get("cursor_value"),
version: row.get("version"),
updated_at: row.get("updated_at_text"),
age_seconds: row.get("age_seconds"),
})
.collect())
}
}