use sqlx::postgres::PgQueryResult;
use sqlx::Postgres;
use super::sqlx_common::{LockDialect, SqlxLock, SqlxLockManager};
#[derive(Debug, Clone, Copy)]
pub struct PostgresDialect;
impl LockDialect for PostgresDialect {
type Db = Postgres;
const OWNER_PREFIX: &'static str = "pg";
const DDL: &'static str = "\
CREATE TABLE IF NOT EXISTS aggregate_locks (\
lock_key text NOT NULL PRIMARY KEY,\
owner_token text NOT NULL,\
acquired_at double precision NOT NULL,\
expires_at double precision NOT NULL,\
CHECK (lock_key <> ''),\
CHECK (owner_token <> '')\
);\
CREATE INDEX IF NOT EXISTS aggregate_locks_expires_at_idx ON aggregate_locks (expires_at);";
const ACQUIRE_SQL: &'static str = r#"
INSERT INTO aggregate_locks (lock_key, owner_token, acquired_at, expires_at)
VALUES ($1, $2, extract(epoch from now()), extract(epoch from now()) + $3)
ON CONFLICT (lock_key) DO UPDATE
SET owner_token = EXCLUDED.owner_token,
acquired_at = EXCLUDED.acquired_at,
expires_at = EXCLUDED.expires_at
WHERE aggregate_locks.expires_at <= extract(epoch from now())
OR aggregate_locks.owner_token = EXCLUDED.owner_token
RETURNING owner_token
"#;
const RELEASE_SQL: &'static str =
"DELETE FROM aggregate_locks WHERE lock_key = $1 AND owner_token = $2";
const SWEEP_SQL: &'static str =
"DELETE FROM aggregate_locks WHERE expires_at <= extract(epoch from now())";
fn rows_affected(result: PgQueryResult) -> u64 {
result.rows_affected()
}
}
pub type PostgresLockManager = SqlxLockManager<PostgresDialect>;
pub type PostgresLock = SqlxLock<PostgresDialect>;