|
7 | 7 | use Hyperf\Database\ConnectionInterface; |
8 | 8 | use Hyperf\Database\ConnectionResolverInterface; |
9 | 9 | use Hyperf\Database\Exception\QueryException; |
| 10 | +use Hypervel\Cache\Contracts\RefreshableLock; |
| 11 | +use InvalidArgumentException; |
10 | 12 |
|
11 | 13 | use function Hyperf\Support\optional; |
12 | 14 |
|
13 | | -class DatabaseLock extends Lock |
| 15 | +class DatabaseLock extends Lock implements RefreshableLock |
14 | 16 | { |
15 | 17 | /** |
16 | 18 | * The database connection resolver. |
@@ -146,4 +148,56 @@ protected function expiresAt(): int |
146 | 148 |
|
147 | 149 | return $this->currentTime() + $lockTimeout; |
148 | 150 | } |
| 151 | + |
| 152 | + /** |
| 153 | + * Refresh the lock's TTL if still owned by this process. |
| 154 | + * |
| 155 | + * @throws InvalidArgumentException If an explicit non-positive TTL is provided |
| 156 | + */ |
| 157 | + public function refresh(?int $seconds = null): bool |
| 158 | + { |
| 159 | + // Permanent lock with no explicit TTL requested - nothing to refresh |
| 160 | + if ($seconds === null && $this->seconds <= 0) { |
| 161 | + return true; |
| 162 | + } |
| 163 | + |
| 164 | + $seconds ??= $this->seconds; |
| 165 | + |
| 166 | + if ($seconds <= 0) { |
| 167 | + throw new InvalidArgumentException( |
| 168 | + 'Refresh requires a positive TTL. For a permanent lock, acquire it with seconds=0.' |
| 169 | + ); |
| 170 | + } |
| 171 | + |
| 172 | + $updated = $this->connection()->table($this->table) |
| 173 | + ->where('key', $this->name) |
| 174 | + ->where('owner', $this->owner) |
| 175 | + ->update([ |
| 176 | + 'expiration' => $this->currentTime() + $seconds, |
| 177 | + ]); |
| 178 | + |
| 179 | + return $updated >= 1; |
| 180 | + } |
| 181 | + |
| 182 | + /** |
| 183 | + * Get the number of seconds until the lock expires. |
| 184 | + */ |
| 185 | + public function getRemainingLifetime(): ?float |
| 186 | + { |
| 187 | + $lock = $this->connection()->table($this->table) |
| 188 | + ->where('key', $this->name) |
| 189 | + ->first(); |
| 190 | + |
| 191 | + if ($lock === null) { |
| 192 | + return null; |
| 193 | + } |
| 194 | + |
| 195 | + $remaining = $lock->expiration - $this->currentTime(); |
| 196 | + |
| 197 | + if ($remaining <= 0) { |
| 198 | + return null; |
| 199 | + } |
| 200 | + |
| 201 | + return (float) $remaining; |
| 202 | + } |
149 | 203 | } |
0 commit comments