use std::convert::identity;
use sqlx::{Decode, Error, Type};
use super::{Claimed, Claiming, Event, Events, Leasing, Stmt, Values, arguments, run, unprepared};
use crate::inbox::QueueRow;
use crate::inbox::database::QueueDatabase;
pub(crate) async fn claim_rows<DB, Row>(
conn: &mut DB::Connection,
cx: &Claiming,
lease: Option<&Leasing<Row::Token>>,
out: &mut Vec<Claimed<Row>>,
) -> Result<(), Error>
where
DB: QueueDatabase,
Row: Events<DB>,
Row::Id: for<'r> Decode<'r, DB> + Type<DB>,
{
let statement = cx
.queue
.prepared
.claim
.ok_or_else(|| unprepared(Event::Claim))?;
let arguments = arguments::<DB, Row>(statement, &Values::claiming(*cx, Event::Claim, lease))?;
DB::fetch_rows(conn, statement.sql, arguments, cx.queue, out).await
}
pub(crate) async fn claim_ids<DB, Row>(
conn: &mut DB::Connection,
cx: &Claiming,
lease: Option<&Leasing<Row::Token>>,
ids: &mut Vec<Row::Id>,
) -> Result<(), Error>
where
DB: QueueDatabase,
Row: Events<DB>,
Row::Id: for<'r> Decode<'r, DB> + Type<DB> + Unpin,
{
let statement = cx
.queue
.prepared
.claim
.ok_or_else(|| unprepared(Event::Claim))?;
let arguments = arguments::<DB, Row>(statement, &Values::claiming(*cx, Event::Claim, lease))?;
DB::fetch_ids(conn, statement.sql, arguments, ids).await
}
pub(crate) async fn fetch_by_ids<DB, Row>(
conn: &mut DB::Connection,
cx: &Claiming,
lease: Option<&Leasing<Row::Token>>,
ids: &[Row::Id],
) -> Result<Vec<Claimed<Row>>, Error>
where
DB: QueueDatabase,
Row: Events<DB>,
Row::Id: for<'r> Decode<'r, DB> + Type<DB>,
{
let statement = cx
.queue
.prepared
.fetch
.ok_or_else(|| unprepared(Event::Fetch))?;
let values = Values {
ids,
..Values::claiming(*cx, Event::Fetch, lease)
};
let arguments = arguments::<DB, Row>(statement, &values)?;
let mut fetched = Vec::with_capacity(ids.len());
DB::fetch_rows(conn, statement.sql, arguments, cx.queue, &mut fetched).await?;
Ok(fetched)
}
pub(crate) fn match_claimed<DB, Row>(
ids: &mut Vec<Row::Id>,
fetched: Vec<Claimed<Row>>,
out: &mut Vec<Claimed<Row>>,
) where
DB: QueueDatabase,
Row: Events<DB>,
Row::Id: PartialEq,
{
pair(ids, fetched, Claimed::id::<DB>, identity, out);
}
pub(crate) fn match_rows<DB, Row>(
ids: &mut Vec<Row::Id>,
rows: Vec<Row>,
out: &mut Vec<Claimed<Row>>,
) where
DB: QueueDatabase,
Row: Events<DB>,
Row::Id: PartialEq,
{
pair(ids, rows, Row::id, Claimed::Row, out);
}
fn pair<Row, Entry>(
ids: &mut Vec<Row::Id>,
mut fetched: Vec<Entry>,
id_of: impl Fn(&Entry) -> &Row::Id,
claimed: impl Fn(Entry) -> Claimed<Row>,
out: &mut Vec<Claimed<Row>>,
) where
Row: QueueRow,
Row::Id: PartialEq,
{
for id in ids.drain(..) {
match fetched.iter().position(|entry| id_of(entry) == &id) {
Some(position) => out.push(claimed(fetched.swap_remove(position))),
None => out.push(Claimed::Missing(id)),
}
}
}
pub(crate) async fn take_group<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Claiming,
guard: Stmt,
lease: Option<&Leasing<Row::Token>>,
) -> Result<bool, Error> {
let arguments = arguments::<DB, Row>(guard, &Values::claiming(*cx, Event::Claim, lease))?;
DB::fetch_flag(conn, guard.sql, arguments).await
}
pub(crate) async fn stamp<DB: QueueDatabase, Row: Events<DB>>(
conn: &mut DB::Connection,
cx: &Claiming,
id: &Row::Id,
lease: &Leasing<Row::Token>,
) -> Result<bool, Error> {
let values = Values {
id: Some(id),
..Values::claiming(*cx, Event::Stamp, Some(lease))
};
Ok(run::<DB, Row>(conn, cx.queue.prepared.stamp, values).await? > 0)
}