Skip to content

Commit 94c272a

Browse files
committed
feature: implement predis and phpredis clients
Signed-off-by: Mateusz Cholewka <mateusz@cholewka.com.pl>
1 parent dd88824 commit 94c272a

File tree

2 files changed

+274
-0
lines changed

2 files changed

+274
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Prometheus\Storage\RedisClients;
6+
7+
use Prometheus\Exception\StorageException;
8+
9+
class PHPRedis implements RedisClient
10+
{
11+
/**
12+
* @var \Redis
13+
*/
14+
private $redis;
15+
16+
private $options = [];
17+
18+
/**
19+
* @var bool
20+
*/
21+
private $connectionInitialized = false;
22+
23+
public function __construct(\Redis $redis, array $options)
24+
{
25+
$this->redis = $redis;
26+
$this->options = $options;
27+
}
28+
29+
public static function create(array $options): self
30+
{
31+
$redis = new \Redis;
32+
33+
return new self($redis, $options);
34+
}
35+
36+
public function getOption(int $option): mixed
37+
{
38+
return $this->redis->getOption($option);
39+
}
40+
41+
public function eval(string $script, array $args = [], int $num_keys = 0): mixed
42+
{
43+
return $this->redis->eval($script, $args, $num_keys);
44+
}
45+
46+
public function set(string $key, mixed $value, mixed $options = null): string|bool
47+
{
48+
return $this->redis->set($key, $value, $options);
49+
}
50+
51+
public function setNx(string $key, mixed $value): bool
52+
{
53+
return $this->redis->setNx($key, $value);
54+
}
55+
56+
public function hSetNx(string $key, string $field, mixed $value): bool
57+
{
58+
return $this->redis->hSetNx($key, $field, $value);
59+
}
60+
61+
public function sMembers(string $key): array|false
62+
{
63+
return $this->redis->sMembers($key);
64+
}
65+
66+
public function hGetAll(string $key): array|false
67+
{
68+
return $this->redis->hGetAll($key);
69+
}
70+
71+
public function keys(string $pattern)
72+
{
73+
return $this->redis->keys($pattern);
74+
}
75+
76+
public function get(string $key): mixed
77+
{
78+
return $this->redis->get($key);
79+
}
80+
81+
public function del(array|string $key, string ...$other_keys): int|false
82+
{
83+
try {
84+
return $this->redis->del($key, ...$other_keys);
85+
} catch (\RedisException $e) {
86+
throw new RedisClientException($e->getMessage());
87+
}
88+
}
89+
90+
public function getPrefix(): string
91+
{
92+
return $this->redis->_prefix('');
93+
}
94+
95+
/**
96+
* @throws StorageException
97+
*/
98+
public function ensureOpenConnection(): void
99+
{
100+
if ($this->connectionInitialized === true) {
101+
return;
102+
}
103+
104+
$this->connectToServer();
105+
$authParams = [];
106+
107+
if (isset($this->options['user']) && $this->options['user'] !== '') {
108+
$authParams[] = $this->options['user'];
109+
}
110+
111+
if (isset($this->options['password'])) {
112+
$authParams[] = $this->options['password'];
113+
}
114+
115+
if ($authParams !== []) {
116+
$this->redis->auth($authParams);
117+
}
118+
119+
if (isset($this->options['database'])) {
120+
$this->redis->select($this->options['database']);
121+
}
122+
123+
$this->redis->setOption(RedisClient::OPT_READ_TIMEOUT, $this->options['read_timeout']);
124+
125+
$this->connectionInitialized = true;
126+
}
127+
128+
/**
129+
* @throws StorageException
130+
*/
131+
private function connectToServer(): void
132+
{
133+
try {
134+
$connection_successful = false;
135+
if ($this->options['persistent_connections'] !== false) {
136+
$connection_successful = $this->redis->pconnect(
137+
$this->options['host'],
138+
(int) $this->options['port'],
139+
(float) $this->options['timeout']
140+
);
141+
} else {
142+
$connection_successful = $this->redis->connect($this->options['host'], (int) $this->options['port'], (float) $this->options['timeout']);
143+
}
144+
if (! $connection_successful) {
145+
throw new StorageException(
146+
sprintf("Can't connect to Redis server. %s", $this->redis->getLastError()),
147+
0
148+
);
149+
}
150+
} catch (\RedisException $e) {
151+
throw new StorageException(
152+
sprintf("Can't connect to Redis server. %s", $e->getMessage()),
153+
$e->getCode(),
154+
);
155+
}
156+
}
157+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Prometheus\Storage\RedisClients;
6+
7+
use Predis\Client;
8+
use Predis\Configuration\Option\Prefix;
9+
10+
class Predis implements RedisClient
11+
{
12+
private const OPTIONS_MAP = [
13+
RedisClient::OPT_PREFIX => Prefix::class,
14+
];
15+
16+
private $client;
17+
18+
private $prefix = '';
19+
20+
public function __construct(Client $redis)
21+
{
22+
$this->client = $redis;
23+
}
24+
25+
public static function create(array $options): self
26+
{
27+
$this->prefix = $options['prefix'] ?? '';
28+
$redisClient = new Client($options, ['prefix' => $options['prefix'] ?? '']);
29+
30+
return new self($redisClient);
31+
}
32+
33+
public function getOption(int $option): mixed
34+
{
35+
if (! isset(self::OPTIONS_MAP[$option])) {
36+
return null;
37+
}
38+
39+
$mappedOption = self::OPTIONS_MAP[$option];
40+
41+
return $this->client->getOptions()->$mappedOption;
42+
}
43+
44+
public function eval(string $script, array $args = [], int $num_keys = 0): mixed
45+
{
46+
return $this->client->eval($script, $num_keys, ...$args);
47+
}
48+
49+
public function set(string $key, mixed $value, mixed $options = null): string|bool
50+
{
51+
$result = $this->client->set($key, $value, ...$this->flattenFlags($options));
52+
53+
return (string) $result;
54+
}
55+
56+
private function flattenFlags(array $flags): array
57+
{
58+
$result = [];
59+
foreach ($flags as $key => $value) {
60+
if (is_int($key)) {
61+
$result[] = $value;
62+
} else {
63+
$result[] = $key;
64+
$result[] = $value;
65+
}
66+
}
67+
68+
return $result;
69+
}
70+
71+
public function setNx(string $key, mixed $value): bool
72+
{
73+
return $this->client->setnx($key, $value) === 1;
74+
}
75+
76+
public function hSetNx(string $key, string $field, mixed $value): bool
77+
{
78+
return $this->hsetnx($key, $field, $value);
79+
}
80+
81+
public function sMembers(string $key): array|false
82+
{
83+
return $this->client->smembers($key);
84+
}
85+
86+
public function hGetAll(string $key): array|false
87+
{
88+
return $this->client->hgetall($key);
89+
}
90+
91+
public function keys(string $pattern)
92+
{
93+
return $this->client->keys($pattern);
94+
}
95+
96+
public function get(string $key): mixed
97+
{
98+
return $this->client->get($key);
99+
}
100+
101+
public function del(array|string $key, string ...$other_keys): int|false
102+
{
103+
return $this->client->del($key, ...$other_keys);
104+
}
105+
106+
public function getPrefix(): string
107+
{
108+
$key = RedisClient::OPT_PREFIX;
109+
110+
return $this->prefix;
111+
}
112+
113+
public function ensureOpenConnection(): void
114+
{
115+
// Predis doesn't require to trigger connection
116+
}
117+
}

0 commit comments

Comments
 (0)