use sqlx::sqlite::SqliteQueryResult;
use sqlx::Sqlite;
use crate::sqlx_repo::is_sqlite_busy;
use super::sqlx_common::{LockDialect, SqlxLock, SqlxLockManager};
#[derive(Debug, Clone, Copy)]
pub struct SqliteDialect;
impl LockDialect for SqliteDialect {
type Db = Sqlite;
const OWNER_PREFIX: &'static str = "sqlite";
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 REAL NOT NULL,\
expires_at REAL 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, unixepoch('now','subsec'), unixepoch('now','subsec') + ?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 <= unixepoch('now','subsec')
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 <= unixepoch('now','subsec')";
fn busy_is_contention(err: &sqlx::Error) -> bool {
is_sqlite_busy(err)
}
fn rows_affected(result: SqliteQueryResult) -> u64 {
result.rows_affected()
}
}
pub type SqliteLockManager = SqlxLockManager<SqliteDialect>;
pub type SqliteLock = SqlxLock<SqliteDialect>;