Skip to content

Commit 3b5c0d1

Browse files
committed
refactor: select proper client automatically
1 parent 41ebf3e commit 3b5c0d1

File tree

9 files changed

+233
-197
lines changed

9 files changed

+233
-197
lines changed

packages/kv-store/src/Redis/Config/PhpRedisConfig.php

Lines changed: 0 additions & 70 deletions
This file was deleted.

packages/kv-store/src/Redis/Config/PredisConfig.php

Lines changed: 0 additions & 75 deletions
This file was deleted.

packages/kv-store/src/Redis/Config/RedisConfig.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,74 @@
22

33
namespace Tempest\KeyValue\Redis\Config;
44

5-
use Tempest\Container\HasTag;
5+
use UnitEnum;
66

7-
interface RedisConfig extends HasTag
7+
final class RedisConfig
88
{
9+
public function __construct(
10+
/**
11+
* Add a prefix to all keys in the Redis database.
12+
*/
13+
public ?string $prefix = null,
14+
15+
/**
16+
* Username to the Redis instance.
17+
*/
18+
public ?string $username = null,
19+
20+
/**
21+
* Password to the Redis instance.
22+
*/
23+
public ?string $password = null,
24+
25+
/**
26+
* IP or hostname of the target server. This is ignored when connecting to Redis using UNIX domain sockets.
27+
*/
28+
public ?string $host = null,
29+
30+
/**
31+
* TCP/IP port of the target server. This is ignored when connecting to Redis using UNIX domain sockets.
32+
*/
33+
public ?int $port = null,
34+
35+
/**
36+
* Logical database to connect to.
37+
*/
38+
public ?int $database = null,
39+
40+
/**
41+
* Path of the UNIX domain socket file used when connecting to Redis using UNIX domain sockets.
42+
*/
43+
public ?int $unixSocketPath = null,
44+
45+
/**
46+
* Specifies the protocol used to communicate with the Redis instance. This is specific to predis.
47+
*/
48+
public Scheme $scheme = Scheme::TCP,
49+
50+
/**
51+
* Specifies if the underlying connection resource should be left open when a script ends its lifecycle.
52+
*/
53+
public bool $persistent = false,
54+
55+
/**
56+
* The maximum duration, in seconds, to wait for a connection to be established.
57+
*/
58+
public ?float $connectionTimeOut = null,
59+
60+
/**
61+
* Less common Predis or PhpRedis client options.
62+
*/
63+
public array $options = [],
64+
65+
/**
66+
* Less common connection options.
67+
*/
68+
public array $connection = [],
69+
70+
/**
71+
* Identifier for this key-value store configuration.
72+
*/
73+
public null|string|UnitEnum $tag = null,
74+
) {}
975
}

packages/kv-store/src/Redis/Config/Scheme.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Tempest\KeyValue\Redis\Config;
44

5+
/**
6+
* Represents the connection scheme used to connect to Redis (predis only).
7+
*/
58
enum Scheme: string
69
{
710
/**

packages/kv-store/src/Redis/PhpRedisClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Tempest\DateTime\DateTimeInterface;
88
use Tempest\DateTime\Duration;
99
use Tempest\EventBus\EventBus;
10-
use Tempest\KeyValue\Redis\Config\PhpRedisConfig;
10+
use Tempest\KeyValue\Redis\Config\RedisConfig;
1111
use Tempest\Support\Arr\ArrayInterface;
1212

1313
use function Tempest\Support\Arr\is_associative;
@@ -16,7 +16,7 @@
1616
{
1717
public function __construct(
1818
private \Redis $client,
19-
private PhpRedisConfig $config,
19+
private RedisConfig $config,
2020
private ?EventBus $eventBus = null,
2121
) {}
2222

packages/kv-store/src/Redis/RedisInitializer.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,31 @@
77
use Tempest\Container\DynamicInitializer;
88
use Tempest\Container\Singleton;
99
use Tempest\EventBus\EventBus;
10-
use Tempest\KeyValue\Redis\Config\PhpRedisConfig;
11-
use Tempest\KeyValue\Redis\Config\PredisConfig;
1210
use Tempest\KeyValue\Redis\Config\RedisConfig;
1311
use Tempest\Reflection\ClassReflector;
12+
use UnitEnum;
1413

1514
final class RedisInitializer implements DynamicInitializer
1615
{
17-
public function canInitialize(ClassReflector $class, ?string $tag): bool
16+
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
1817
{
1918
return $class->getType()->matches(Redis::class);
2019
}
2120

2221
#[Singleton]
23-
public function initialize(ClassReflector $class, ?string $tag, Container $container): Redis
22+
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): Redis
2423
{
2524
$config = $container->get(RedisConfig::class, $tag);
2625
$bus = $container->get(EventBus::class);
2726

28-
return match ($config::class) {
29-
PredisConfig::class => new PredisClient($this->buildPredisClient($config), $bus),
30-
PhpRedisConfig::class => new PhpRedisClient($this->buildPhpRedisClient($config), $config, $bus),
31-
};
27+
try {
28+
return new PhpRedisClient($this->buildPhpRedisClient(), $config, $bus);
29+
} catch (MissingRedisException) {
30+
return new PredisClient($this->buildPredisClient($config), $bus);
31+
}
3232
}
3333

34-
private function buildPhpRedisClient(PhpRedisConfig $config): \Redis
34+
private function buildPhpRedisClient(): \Redis
3535
{
3636
if (! extension_loaded('redis') || ! class_exists(\Redis::class)) {
3737
throw new MissingRedisException(Redis::class);
@@ -40,7 +40,7 @@ private function buildPhpRedisClient(PhpRedisConfig $config): \Redis
4040
return new \Redis();
4141
}
4242

43-
private function buildPredisClient(PredisConfig $config): Predis\Client
43+
private function buildPredisClient(RedisConfig $config): Predis\Client
4444
{
4545
if (! class_exists(Predis\Client::class)) {
4646
throw new MissingRedisException(Predis\Client::class);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Tempest\KeyValue\Tests;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Tempest\KeyValue\Redis\Config\RedisConfig;
7+
use Tempest\KeyValue\Redis\PhpRedisClient;
8+
9+
final class PhpRedisClientTest extends TestCase
10+
{
11+
private PhpRedisClient $redis;
12+
13+
protected function setUp(): void
14+
{
15+
parent::setUp();
16+
17+
$this->redis = new PhpRedisClient(
18+
client: new \Redis(),
19+
config: new RedisConfig(
20+
prefix: 'tempest_test:',
21+
database: 6,
22+
connectionTimeOut: .2,
23+
),
24+
);
25+
26+
try {
27+
$this->redis->connect();
28+
} catch (\Throwable) {
29+
$this->markTestSkipped('Could not connect to Redis.');
30+
}
31+
}
32+
33+
protected function tearDown(): void
34+
{
35+
try {
36+
$this->redis->flush();
37+
} finally {
38+
parent::tearDown();
39+
}
40+
}
41+
42+
public function test_basic(): void
43+
{
44+
$this->assertSame('response', $this->redis->command('PING', 'response'));
45+
$this->assertInstanceOf(\Redis::class, $this->redis->getClient());
46+
}
47+
48+
public function test_set(): void
49+
{
50+
$this->redis->set('key_string', 'my-value');
51+
$this->redis->set('key_array_associative', ['foo' => 'bar']);
52+
$this->redis->set('key_array_list', ['foo', 'bar']);
53+
54+
$this->assertSame('my-value', $this->redis->getClient()->rawcommand('GET', 'key_string'));
55+
$this->assertSame('{"foo":"bar"}', $this->redis->getClient()->rawcommand('GET', 'key_array_associative'));
56+
$this->assertSame('["foo","bar"]', $this->redis->getClient()->rawcommand('GET', 'key_array_list'));
57+
}
58+
59+
public function test_get(): void
60+
{
61+
$this->redis->getClient()->rawcommand('SET', 'key_string', 'my_value');
62+
$this->redis->getClient()->rawcommand('SET', 'key_array_associative', '{"foo":"bar"}');
63+
$this->redis->getClient()->rawcommand('SET', 'key_array_list', '["foo","bar"]');
64+
65+
$this->assertSame('my_value', $this->redis->get('key_string'));
66+
$this->assertSame(['foo' => 'bar'], $this->redis->get('key_array_associative'));
67+
$this->assertSame(['foo', 'bar'], $this->redis->get('key_array_list'));
68+
}
69+
}

0 commit comments

Comments
 (0)