package demo.service
import demo.dao.*
import std.time.*
import stdx.logger.*
import stdx.log.*
import opengauss.slog.*
import std.database.sql.*
// CREATE TABLE lock_t (
// lock_name VARCHAR(255) PRIMARY KEY, -- 锁的名称,确保每个锁是唯一的
// locked BOOLEAN NOT NULL, -- 锁是否被占用
// locked_at TIMESTAMPTZ DEFAULT NOW(), -- 锁被占用的时间戳
// locked_by VARCHAR(255) -- 锁被哪个客户端/进程占用
// );
public class Locker {
var logger: Logger
public Locker(var connector: Connector, var tableName: String) {
logger = Default()
}
private func addLock(lockName: String, lockedBy: String) {
let sqlInsert = "insert into ${tableName} (lock_name, locked, locked_at, locked_by) values(?, ?, ?, ?)"
connector.update(sqlInsert, [lockName, true, DateTime.now(), lockedBy])
}
public func tryLock(lockName: String, lockedBy: String): Bool {
var transaction = connector.conn.createTransaction()
transaction.begin()
try {
let sqlSelect = "select locked, locked_by from ${tableName} where lock_name = ? for update"
var result = connector.select(sqlSelect, [lockName])
if (result.next() && (result.getOrNull<Bool>(1) ?? false)) {
if (result.get<String>(2) != lockedBy) {
return false
}
}
addLock(lockName, lockedBy)
return true
} catch (e: Exception) {
logger.debug("Exception: ${e.toString()}")
var sqlDelete = "delete from ${tableName} where lock_name = ? and locked_by = ?"
connector.update(sqlDelete, [lockName, lockedBy])
return false
} finally {
transaction.commit()
}
}
public func unLock(lockName: String, lockeBy: String) {
var sqlDelete = "delete from ${tableName} where lock_name = ? and locked_by = ?"
connector.update(sqlDelete, [lockName, lockeBy])
}
}