100 lines
2.7 KiB
PHP
100 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace app\service;
|
|
|
|
use support\Redis;
|
|
|
|
class AiMetadataQueue
|
|
{
|
|
public function push(string $archiveUid): void
|
|
{
|
|
Redis::lPush($this->pendingKey(), $archiveUid);
|
|
}
|
|
|
|
public function pop(int $timeout = 5): ?string
|
|
{
|
|
$result = Redis::brPop([$this->pendingKey()], $timeout);
|
|
if (!is_array($result) || count($result) < 2) {
|
|
return null;
|
|
}
|
|
|
|
return (string) $result[1];
|
|
}
|
|
|
|
public function retryLater(string $archiveUid, string $error): void
|
|
{
|
|
$retryKey = $this->retryKey($archiveUid);
|
|
$retryCount = (int) Redis::incr($retryKey);
|
|
Redis::setEx($this->errorKey($archiveUid), 86400, $error);
|
|
|
|
if ($retryCount > $this->maxRetries()) {
|
|
Redis::lPush($this->failedKey(), $archiveUid);
|
|
return;
|
|
}
|
|
|
|
$delay = $this->baseDelaySeconds() * (2 ** max(0, $retryCount - 1));
|
|
Redis::zAdd($this->delayedKey(), time() + $delay, $archiveUid);
|
|
}
|
|
|
|
public function releaseDueDelayed(): int
|
|
{
|
|
$now = time();
|
|
$items = Redis::zRangeByScore($this->delayedKey(), '-inf', (string) $now, ['limit' => [0, 100]]);
|
|
if (!is_array($items) || $items === []) {
|
|
return 0;
|
|
}
|
|
|
|
foreach ($items as $archiveUid) {
|
|
Redis::zRem($this->delayedKey(), $archiveUid);
|
|
Redis::lPush($this->pendingKey(), $archiveUid);
|
|
}
|
|
|
|
return count($items);
|
|
}
|
|
|
|
public function clearRetry(string $archiveUid): void
|
|
{
|
|
Redis::del($this->retryKey($archiveUid), $this->errorKey($archiveUid));
|
|
}
|
|
|
|
public function blockTimeout(): int
|
|
{
|
|
return (int) config('queue.ai_metadata.block_timeout', 5);
|
|
}
|
|
|
|
private function pendingKey(): string
|
|
{
|
|
return config('queue.ai_metadata.pending', 'proofdb:ai:metadata:pending');
|
|
}
|
|
|
|
private function delayedKey(): string
|
|
{
|
|
return config('queue.ai_metadata.delayed', 'proofdb:ai:metadata:delayed');
|
|
}
|
|
|
|
private function failedKey(): string
|
|
{
|
|
return config('queue.ai_metadata.failed', 'proofdb:ai:metadata:failed');
|
|
}
|
|
|
|
private function retryKey(string $archiveUid): string
|
|
{
|
|
return config('queue.ai_metadata.retry_prefix', 'proofdb:ai:metadata:retry:') . $archiveUid;
|
|
}
|
|
|
|
private function errorKey(string $archiveUid): string
|
|
{
|
|
return config('queue.ai_metadata.error_prefix', 'proofdb:ai:metadata:error:') . $archiveUid;
|
|
}
|
|
|
|
private function maxRetries(): int
|
|
{
|
|
return (int) config('queue.ai_metadata.max_retries', 5);
|
|
}
|
|
|
|
private function baseDelaySeconds(): int
|
|
{
|
|
return (int) config('queue.ai_metadata.base_delay_seconds', 60);
|
|
}
|
|
}
|