use std::time::Duration;
use sqlx::Error;
use super::{Event, Events, Settled, Settling, Values, run};
use crate::inbox::database::QueueDatabase;
use crate::inbox::queue::Queue;
const fn settled(queue: &Queue, changed: u64) -> Settled {
if queue.lease.is_some() && changed == 0 {
Settled::Lost
} else {
Settled::Written
}
}
pub(crate) async fn ack<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: Option<&Row::Token>,
) -> Result<Settled, Error> {
let values = Values::settling(*cx, Event::Ack, id, held.copied());
let changed = run::<DB, Row>(conn, cx.queue.prepared.ack, values).await?;
Ok(settled(cx.queue, changed))
}
pub(crate) async fn retry<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: Option<&Row::Token>,
) -> Result<Settled, Error> {
let Some(statement) = cx.queue.prepared.retry else {
return Ok(Settled::Untouched);
};
let values = Values::settling(*cx, Event::Retry, id, held.copied());
let changed = run::<DB, Row>(conn, Some(statement), values).await?;
Ok(settled(cx.queue, changed))
}
pub(crate) async fn retry_after<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: Option<&Row::Token>,
delay: Duration,
) -> Result<Settled, Error> {
let values = Values {
delay,
..Values::settling(*cx, Event::RetryAfter, id, held.copied())
};
let changed = run::<DB, Row>(conn, cx.queue.prepared.retry_after, values).await?;
Ok(settled(cx.queue, changed))
}
pub(crate) async fn discard<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: Option<&Row::Token>,
) -> Result<Settled, Error> {
let values = Values::settling(*cx, Event::Discard, id, held.copied());
let changed = run::<DB, Row>(conn, cx.queue.prepared.discard, values).await?;
Ok(settled(cx.queue, changed))
}
pub(crate) async fn dead_letter<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: Option<&Row::Token>,
destination: &str,
) -> Result<Settled, Error> {
let values = Values {
destination,
..Values::settling(*cx, Event::DeadLetter, id, held.copied())
};
let changed = run::<DB, Row>(conn, cx.queue.prepared.dead_letter, values).await?;
let moved = settled(cx.queue, changed);
let (Settled::Written, Some(then)) = (moved, cx.queue.prepared.dead_letter_then) else {
return Ok(moved);
};
let values = Values {
destination,
..Values::settling(*cx, Event::DeadLetter, id, held.copied())
};
let changed = run::<DB, Row>(conn, Some(then), values).await?;
Ok(settled(cx.queue, changed))
}
pub(crate) async fn extend<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Settling,
id: &Row::Id,
held: &Row::Token,
until: &Row::Token,
) -> Result<Settled, Error> {
let values = Values {
lease: Some(*until),
..Values::settling(*cx, Event::Extend, id, Some(*held))
};
let changed = run::<DB, Row>(conn, cx.queue.prepared.extend, values).await?;
Ok(settled(cx.queue, changed))
}