#![cfg(feature = "serve-history-postgres")]
use chrono::Utc;
use faucet_cli::serve::history::postgres::PostgresHistory;
use faucet_cli::serve::history::{
Claim, DeleteOutcome, ListFilter, RunHistory, RunRecord, RunStatus,
};
use std::collections::BTreeMap;
use std::time::Duration;
fn rec(id: &str, status: RunStatus) -> RunRecord {
let now = Utc::now();
let mut r = RunRecord::queued(
id.into(),
Some("pg-test".into()),
BTreeMap::new(),
None,
now,
);
r.status = status;
if status.is_terminal() {
r.finished_at = Some(now);
}
r
}
#[tokio::test]
async fn postgres_backend_full_lifecycle() {
let Ok(url) = std::env::var("FAUCET_TEST_POSTGRES_URL") else {
eprintln!(
"SKIP postgres_backend_full_lifecycle: set FAUCET_TEST_POSTGRES_URL to a \
reachable postgres:// URL to run this test"
);
return;
};
let h = PostgresHistory::connect(
&url,
Duration::from_secs(3600),
Duration::ZERO,
"pg-test".into(),
)
.await
.expect("connect postgres history (is FAUCET_TEST_POSTGRES_URL reachable?)");
let p = format!("pg-{}", Utc::now().timestamp_nanos_opt().unwrap_or(0));
let id = |s: &str| format!("{p}-{s}");
h.upsert(&rec(&id("1"), RunStatus::Running)).await.unwrap();
let got = h.get(&id("1")).await.unwrap().expect("present");
assert_eq!(got.status, RunStatus::Running);
assert!(h.get(&id("missing")).await.unwrap().is_none());
let key = id("k");
let w = Duration::from_secs(3600);
assert_eq!(
h.claim_idempotency(&key, "fp1", &id("r1"), w)
.await
.unwrap(),
Claim::Fresh
);
assert_eq!(
h.claim_idempotency(&key, "fp1", &id("r2"), w)
.await
.unwrap(),
Claim::Replay(id("r1"))
);
assert_eq!(
h.claim_idempotency(&key, "fp2", &id("r3"), w)
.await
.unwrap(),
Claim::Conflict
);
let page = h
.list(&ListFilter {
name: Some("pg-test".into()),
limit: 100,
..Default::default()
})
.await
.unwrap();
assert!(page.runs.iter().any(|r| r.run_id == id("1")));
assert_eq!(
h.delete(&id("1")).await.unwrap(),
DeleteOutcome::StillRunning
);
h.upsert(&rec(&id("1"), RunStatus::Completed))
.await
.unwrap();
assert_eq!(h.delete(&id("1")).await.unwrap(), DeleteOutcome::Deleted);
h.upsert(&rec(&id("orphan"), RunStatus::Running))
.await
.unwrap();
assert!(h.recover_orphans().await.unwrap() >= 1);
assert_eq!(
h.get(&id("orphan")).await.unwrap().unwrap().status,
RunStatus::Failed
);
}