Codex Handbook
state/src/model/backfill_state.rs 73 lines
use anyhow::Result;use chrono::DateTime;use chrono::Utc;use sqlx::Row;use sqlx::sqlite::SqliteRow;/// Persisted lifecycle state for rollout metadata backfill.#[derive(Debug, Clone, PartialEq, Eq)]pub struct BackfillState {    /// Current lifecycle status.    pub status: BackfillStatus,    /// Last processed rollout watermark.    pub last_watermark: Option<String>,    /// Last successful completion time.    pub last_success_at: Option<DateTime<Utc>>,}impl Default for BackfillState {    fn default() -> Self {        Self {            status: BackfillStatus::Pending,            last_watermark: None,            last_success_at: None,        }    }}impl BackfillState {    pub(crate) fn try_from_row(row: &SqliteRow) -> Result<Self> {        let status: String = row.try_get("status")?;        let last_success_at = row            .try_get::<Option<i64>, _>("last_success_at")?            .map(epoch_seconds_to_datetime)            .transpose()?;        Ok(Self {            status: BackfillStatus::parse(status.as_str())?,            last_watermark: row.try_get("last_watermark")?,            last_success_at,        })    }}/// Backfill lifecycle status.#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub enum BackfillStatus {    Pending,    Running,    Complete,}impl BackfillStatus {    pub const fn as_str(self) -> &'static str {        match self {            BackfillStatus::Pending => "pending",            BackfillStatus::Running => "running",            BackfillStatus::Complete => "complete",        }    }    pub fn parse(value: &str) -> Result<Self> {        match value {            "pending" => Ok(Self::Pending),            "running" => Ok(Self::Running),            "complete" => Ok(Self::Complete),            _ => Err(anyhow::anyhow!("invalid backfill status: {value}")),        }    }}fn epoch_seconds_to_datetime(secs: i64) -> Result<DateTime<Utc>> {    DateTime::<Utc>::from_timestamp(secs, 0)        .ok_or_else(|| anyhow::anyhow!("invalid unix timestamp: {secs}"))}