Files
api/services/nginx/app/tests/Unit/Redis/RedisAtomicReservationTest.php
T

74 lines
1.8 KiB
PHP

<?php
app_require('classes/redis.php');
use classes\redis;
use Predis\Client as PredisClient;
class RedisAtomicReservationTestClient extends PredisClient
{
public array $calls = [];
public function __construct(private mixed $returnValue)
{
}
public function set(...$arguments): mixed
{
$this->calls[] = $arguments;
return $this->returnValue;
}
public function disconnect(): void
{
}
}
function redis_test_inject_client(redis $redis, PredisClient $client): void
{
$reflection = new ReflectionClass($redis);
$property = $reflection->getProperty('redis');
$property->setAccessible(true);
$property->setValue($redis, $client);
}
it('claims a slot atomically with nx and expiration', function (): void {
global $REDIS_CONFIG;
$REDIS_CONFIG = [
'host' => 'redis',
'database' => 0,
'password' => '',
];
$client = new RedisAtomicReservationTestClient('OK');
$redis = new redis();
redis_test_inject_client($redis, $client);
expect($redis->set_if_absent_with_expiration('goal_alert_sent:22:2026-03-17', '1', 86400))->toBeTrue();
expect($client->calls)->toBe([
['goal_alert_sent:22:2026-03-17', '1', 'EX', 86400, 'NX'],
]);
});
it('returns false when the slot is already claimed and clamps ttl to one second', function (): void {
global $REDIS_CONFIG;
$REDIS_CONFIG = [
'host' => 'redis',
'database' => 0,
'password' => '',
];
$client = new RedisAtomicReservationTestClient(null);
$redis = new redis();
redis_test_inject_client($redis, $client);
expect($redis->set_if_absent_with_expiration('goal_alert_sent:22:2026-03-17', '1', 0))->toBeFalse();
expect($client->calls)->toBe([
['goal_alert_sent:22:2026-03-17', '1', 'EX', 1, 'NX'],
]);
});