Files
links/application/common/service/SplitTicketSyncLockService.php
2026-06-09 03:36:30 +08:00

65 lines
1.5 KiB
PHP

<?php
declare(strict_types=1);
namespace app\common\service;
/**
* 工单同步互斥锁(基于 runtime 文件锁,不依赖 Cache/Redis 扩展)
*/
class SplitTicketSyncLockService
{
private const LOCK_TTL = 1800;
/**
* 尝试获取锁
*/
public function acquire(int $ticketId): bool
{
$path = $this->lockPath($ticketId);
if ($this->isStaleLock($path)) {
@unlink($path);
}
if (is_file($path)) {
return false;
}
$payload = json_encode([
'ticket_id' => $ticketId,
'pid' => getmypid(),
'time' => time(),
], JSON_UNESCAPED_UNICODE);
$written = @file_put_contents($path, $payload, LOCK_EX);
return $written !== false;
}
/**
* 释放锁
*/
public function release(int $ticketId): void
{
$path = $this->lockPath($ticketId);
if (is_file($path)) {
@unlink($path);
}
}
private function lockPath(int $ticketId): string
{
$runtime = defined('RUNTIME_PATH') ? RUNTIME_PATH : (dirname(__DIR__, 3) . '/runtime/');
$dir = $runtime . 'split_ticket_sync/';
if (!is_dir($dir)) {
@mkdir($dir, 0755, true);
}
return $dir . $ticketId . '.lock';
}
private function isStaleLock(string $path): bool
{
if (!is_file($path)) {
return false;
}
$mtime = (int) @filemtime($path);
return $mtime > 0 && (time() - $mtime) > self::LOCK_TTL;
}
}