use std::time::Duration;
use sqlx::Row;
use uuid::Uuid;
use super::dialect::{JobPool, sql};
use super::error::WorkerError;
#[derive(Debug, Clone)]
pub struct ClaimedJob {
pub id: Uuid,
pub claim_token: Uuid,
pub kind: String,
pub version: i16,
pub payload: serde_json::Value,
pub attempts: i32,
pub max_attempts: i32,
pub lease_seconds: i32,
}
fn lease_seconds(lease: Duration) -> i32 {
lease.as_secs().min(i32::MAX as u64) as i32
}
#[cfg(feature = "db-postgres")]
pub async fn claim_jobs(
pool: &JobPool,
worker_id: &str,
lease: Duration,
batch: i64,
) -> Result<Vec<ClaimedJob>, WorkerError> {
let claim_token = Uuid::new_v4();
let rows = sqlx::query(sql::CLAIM)
.bind(worker_id)
.bind(claim_token)
.bind(lease_seconds(lease))
.bind(batch)
.fetch_all(pool)
.await?;
let mut claimed = Vec::with_capacity(rows.len());
for row in &rows {
claimed.push(ClaimedJob {
id: row.try_get("id")?,
claim_token: row.try_get("claim_token")?,
kind: row.try_get("kind")?,
version: row.try_get("version")?,
payload: row.try_get("payload")?,
attempts: row.try_get("attempts")?,
max_attempts: row.try_get("max_attempts")?,
lease_seconds: row.try_get("lease_seconds")?,
});
}
Ok(claimed)
}
#[cfg(any(feature = "db-sqlite", feature = "db-mysql"))]
pub async fn claim_jobs(
pool: &JobPool,
worker_id: &str,
lease: Duration,
batch: i64,
) -> Result<Vec<ClaimedJob>, WorkerError> {
use sqlx::Connection;
let claim_token = Uuid::new_v4();
let lease_seconds = lease_seconds(lease);
let mut conn = pool.acquire().await?;
if let Some(setup) = sql::SESSION_SETUP {
sqlx::query(setup).execute(&mut *conn).await?;
}
let mut tx = conn.begin_with(sql::BEGIN).await?;
let picked = sqlx::query(sql::CLAIM_PICK)
.bind(batch)
.fetch_all(&mut *tx)
.await?;
let mut claimed = Vec::with_capacity(picked.len());
for row in &picked {
let id: Uuid = row.try_get("id")?;
let marked = sqlx::query(sql::CLAIM_MARK)
.bind(worker_id)
.bind(claim_token)
.bind(lease_seconds)
.bind(id)
.execute(&mut *tx)
.await?
.rows_affected();
if marked == 0 {
continue;
}
claimed.push(ClaimedJob {
id,
claim_token,
kind: row.try_get("kind")?,
version: row.try_get("version")?,
payload: row.try_get("payload")?,
attempts: row.try_get::<i32, _>("attempts")? + 1,
max_attempts: row.try_get("max_attempts")?,
lease_seconds,
});
}
tx.commit().await?;
Ok(claimed)
}