pub(super) fn sweep_lock_key(schema: &str) -> i64 {
let mut state: u64 = 0xcbf2_9ce4_8422_2325;
for byte in format!("alkblobs:sweep:{schema}").as_bytes() {
state ^= u64::from(*byte);
state = state.wrapping_mul(0x0000_0100_0000_01b3);
}
(state & !(1_u64 << 63)) as i64
}
#[cfg(test)]
mod tests {
use super::*;
use crate::backend::Backend;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use parking_lot::Mutex;
use crate::gc::EngineFleetState;
use crate::gc::EngineWindowState;
use crate::pg_common::time_to_nanos;
use crate::pg_common::PgOpts;
use crate::postgres::pool::DEFAULT_PIN_TTL;
use crate::postgres::testing::{
arc_backend, harness_dsn, harness_gc, harness_with, pin_row, pin_rows, raw_connection,
stored_value, CONTENT,
};
use crate::postgres::PostgresBackend;
use crate::{Error, PinState};
#[tokio::test]
async fn joint_put_and_pin_commit_publish_together() {
let Some(backend) = harness_gc("joint").await else {
return;
};
let key = b"\x01joint-key".to_vec();
let owner = b"\x01instance-id".to_vec();
let mut tx = backend.begin_joint_tx().await.unwrap();
EngineFleetState::joint_put(&*backend, &mut tx, &key, CONTENT)
.await
.unwrap();
let expiry = SystemTime::now() + DEFAULT_PIN_TTL;
backend
.pin_commit(tx, &[pin_row(&key, &owner, expiry)])
.await
.unwrap();
assert!(backend.has(&key).await.unwrap(), "entry published");
assert_eq!(
backend.pin_check(&key).await.unwrap(),
PinState::Protected,
"the pin row landed with the entry"
);
assert_eq!(stored_value(&backend, &key).await.as_deref(), Some(CONTENT));
let before = pin_rows(&backend).await;
assert_eq!(
before,
vec![(key.clone(), owner.clone(), time_to_nanos(expiry))],
"the pin row's identity is (key, owner), expiry the store-resolved one"
);
let mut tx = backend.begin_joint_tx().await.unwrap();
EngineFleetState::joint_put(&*backend, &mut tx, &key, b"overwritten")
.await
.unwrap();
let renewed = SystemTime::now() + DEFAULT_PIN_TTL + Duration::from_secs(7);
backend
.pin_commit(tx, &[pin_row(&key, &owner, renewed)])
.await
.unwrap();
assert_eq!(
stored_value(&backend, &key).await.as_deref(),
Some(CONTENT),
"joint re-put does not overwrite (first writer wins)"
);
assert_eq!(
pin_rows(&backend).await,
vec![(key, owner, time_to_nanos(renewed))],
"the re-put's pin row upsert renews the same instance's row"
);
}
#[tokio::test]
async fn pin_commit_failure_aborts_with_zero_residue() {
let Some(backend) = harness_gc("joint-fail").await else {
return;
};
let key = b"\x01joint-failure-key".to_vec();
let owner = b"\x01instance-id".to_vec();
let failing = PostgresBackend {
pool: backend.pool.clone(),
table: backend.table.clone(),
schema: backend.schema.clone(),
pins_table: backend.pins_table.clone(),
window_table: backend.window_table.clone(),
pin_ttl: backend.pin_ttl,
lease: Mutex::new(None),
liveness_sources: Arc::new(Mutex::new(Vec::new())),
#[cfg(test)]
fail_commit: false,
#[cfg(test)]
fail_joint_commit: true,
#[cfg(test)]
fail_window_stage: false,
};
let mut tx = failing.begin_joint_tx().await.unwrap();
EngineFleetState::joint_put(&failing, &mut tx, &key, CONTENT)
.await
.unwrap();
let expiry = SystemTime::now() + DEFAULT_PIN_TTL;
let err = failing
.pin_commit(tx, &[pin_row(&key, &owner, expiry)])
.await
.unwrap_err();
assert!(
matches!(err, Error::Io(_)),
"engine joint media failure surfaces as Io"
);
assert!(
!backend.has(&key).await.unwrap(),
"the aborted tx published nothing"
);
assert_eq!(
backend.pin_check(&key).await.unwrap(),
PinState::Unprotected,
"no pin row survived"
);
assert_eq!(pin_rows(&backend).await, vec![], "zero residue in gc_pins");
assert!(
backend.list().await.unwrap().is_empty(),
"zero residue in the blobs table itself"
);
}
#[tokio::test]
async fn sweep_lock_acquire_contention_release() {
let Some(backend) = harness_gc("sweep-lock").await else {
return;
};
assert!(
backend.sweep_lock_acquire().await.unwrap(),
"first acquire: held"
);
assert!(
!backend.sweep_lock_acquire().await.unwrap(),
"second acquire on the held backend contended"
);
let dsn = harness_dsn().unwrap();
let (raw, _conn) = raw_connection(&dsn).await;
let key = sweep_lock_key(&backend.schema);
let held = raw
.query_one("SELECT pg_try_advisory_lock($1)", &[&key])
.await
.unwrap()
.get::<_, bool>(0);
assert!(!held, "a concurrent session's try contends on the same key");
backend.sweep_lock_release().await.unwrap();
backend.sweep_lock_release().await.unwrap();
assert!(
backend.sweep_lock_acquire().await.unwrap(),
"acquire after release: held again (release freed the lock)"
);
backend.sweep_lock_release().await.unwrap();
}
#[tokio::test]
async fn sweep_lock_session_loss_reaps_the_lease() {
let Some(backend) = harness_gc("sweep-reap").await else {
return;
};
let dsn = harness_dsn().unwrap();
let key = sweep_lock_key(&backend.schema);
let (holder, conn) = raw_connection(&dsn).await;
let held = holder
.query_one("SELECT pg_try_advisory_lock($1)", &[&key])
.await
.unwrap()
.get::<_, bool>(0);
assert!(held, "the foreign session holds the lock");
assert!(
!backend.sweep_lock_acquire().await.unwrap(),
"the backend's acquire contends while the foreign session lives"
);
drop(holder);
let _ = conn.await;
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
assert!(
backend.sweep_lock_acquire().await.unwrap(),
"session loss reaped the lease — the backend now holds it"
);
backend.sweep_lock_release().await.unwrap();
}
#[tokio::test]
async fn sweep_lock_in_instance_session_loss_reaps_the_lease() {
let Some(backend) = harness_gc("sweep-reap-own").await else {
return;
};
assert!(backend.sweep_lock_acquire().await.unwrap(), "held");
let held_client = backend
.lease
.lock()
.take()
.expect("the acquire stored its checkout");
let pid = held_client
.query_one("SELECT pg_backend_pid()", &[])
.await
.unwrap()
.get::<_, i32>(0);
*backend.lease.lock() = Some(held_client);
let dsn = harness_dsn().unwrap();
let (raw, _conn) = raw_connection(&dsn).await;
raw.query_one("SELECT pg_terminate_backend($1)", &[&pid])
.await
.unwrap();
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
assert!(
backend.sweep_lock_acquire().await.unwrap(),
"the dead in-instance lease is reaped without a release call"
);
assert!(
!backend.sweep_lock_acquire().await.unwrap(),
"the re-acquired lease contends again"
);
backend.sweep_lock_release().await.unwrap();
}
#[tokio::test]
async fn cancel_mid_joint_tx_leaves_the_next_checkout_clean() {
let Some(backend) = harness_with(
"joint-cancel",
PgOpts {
max_size: 1,
..PgOpts::default()
},
)
.await
else {
return;
};
backend.ensure_gc_schema().await.expect("gc schema");
let stranded_key = b"\x01joint-cancel-key".to_vec();
let holder = arc_backend(&backend);
let put_key = stranded_key.clone();
let (begun_tx, tx_begun) = tokio::sync::oneshot::channel();
let task = tokio::spawn(async move {
let mut tx = holder.begin_joint_tx().await.unwrap();
EngineFleetState::joint_put(&*holder, &mut tx, &put_key, CONTENT)
.await
.unwrap();
let _ = begun_tx.send(());
std::future::pending::<()>().await;
});
tx_begun.await.expect("the task reached the begun joint tx");
task.abort();
let _ = task.await;
let mut clean = backend.begin_joint_tx().await.unwrap();
let clean_key = b"\x01joint-cancel-clean-key".to_vec();
let clean_owner = b"\x01joint-cancel-clean-owner".to_vec();
EngineFleetState::joint_put(&*backend, &mut clean, &clean_key, CONTENT)
.await
.unwrap();
backend
.pin_commit(
clean,
&[pin_row(
&clean_key,
&clean_owner,
SystemTime::now() + DEFAULT_PIN_TTL,
)],
)
.await
.unwrap();
assert!(
!backend.has(&stranded_key).await.unwrap(),
"the cancelled tx published nothing — its insert was rolled back"
);
assert!(
backend.has(&clean_key).await.unwrap(),
"the next checkout ran its joint tx (BEGIN/COMMIT) cleanly"
);
assert_eq!(
pin_rows(&backend).await[0].0,
clean_key,
"the clean tx's pin row is the only residue in gc_pins"
);
}
}