完整版V1 加入爬虫功能
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user