Skip to content

Commit e7f1e1f

Browse files
0.6.0
* [R] требует PHP 7.4+ * [-] убран тип аргумента `PDO` при инцициализации. Теперь можно инициализироваться без базы. * [*] исправлен метод `getAllKeys()` - теперь он отдает данные из локального репозитория только если это указано прямо * [*] исправлен метод `redisDel()` - для аргумента `*` он выполняет flushDB команду. * [*] метод `jsonize()` теперь публичный через CacheHelper * [*] мелкие оптимизации в классе RedisClient
1 parent 692447e commit e7f1e1f

File tree

5 files changed

+147
-88
lines changed

5 files changed

+147
-88
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616
],
1717
"require": {
18-
"php": ">=7.3.0",
18+
"php": ">=7.4.0",
1919
"ext-pdo": "*",
2020
"ext-json": "*",
2121
"ext-redis": "*",

src/Cache.php

Lines changed: 105 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Arris\Cache\Exceptions\RedisClientException;
99
use Psr\Log\LoggerInterface;
1010

11+
use Psr\Log\NullLogger;
1112
use function array_key_exists, array_keys, array_walk, is_array;
1213
use function json_decode, json_encode;
1314
use function class_exists, method_exists, function_exists, call_user_func_array;
@@ -31,18 +32,25 @@ class Cache implements CacheInterface
3132
private static $logger;
3233

3334
/**
34-
* @var PDO $pdo
35+
* @var PDO|null $pdo
3536
*/
3637
private static $pdo;
3738

39+
/**
40+
* @var array
41+
*/
42+
/*private static $connection_options = [];*/
43+
44+
/*private static $connectors = [];*/
45+
3846
/**
3947
* @var array
4048
*/
4149
public static $repository = [];
4250

43-
public static function init(array $credentials = [], array $rules = [], PDO $PDO = null, LoggerInterface $logger = null)
51+
public static function init(array $credentials = [], array $rules = [], $PDO = null, LoggerInterface $logger = null)
4452
{
45-
self::$logger = $logger;
53+
self::$logger = is_null($logger) ? new NullLogger() : $logger;
4654
self::$is_redis_connected = false;
4755
self::$pdo = $PDO;
4856

@@ -55,7 +63,7 @@ public static function init(array $credentials = [], array $rules = [], PDO $PDO
5563
'database' => self::REDIS_DEFAULT_DB,
5664
'password' => self::REDIS_DEFAULT_PASSWORD
5765
];
58-
$options = self::overrideDefaults($options, $credentials);
66+
/*self::$connection_options = */$options = self::overrideDefaults($options, $credentials);
5967

6068
if ($options['enabled']) {
6169
try {
@@ -69,6 +77,7 @@ public static function init(array $credentials = [], array $rules = [], PDO $PDO
6977
// теперь перебираем $rules
7078
foreach ($rules as $rule_name => $rule_definition) {
7179
$message = self::defineRule($rule_name, $rule_definition);
80+
7281
if ($logger instanceof LoggerInterface) {
7382
$logger->debug($message);
7483
}
@@ -81,6 +90,20 @@ public static function getConnector():RedisClient
8190
return self::$redis_connector;
8291
}
8392

93+
/*public static function switchDatabase($database):RedisClient
94+
{
95+
$options = self::$connection_options;
96+
97+
if ($options['database'] !== $database) {
98+
$connector = new RedisClient($options['host'], $options['port'], $options['timeout'], $options['persistent'], $database, $options['password']);
99+
$connector->connect();
100+
} else {
101+
$connector = self::$redis_connector;
102+
}
103+
104+
return $connector;
105+
}*/
106+
84107
public static function addRule(string $rule_name, $rule_definition):string
85108
{
86109
$message = self::defineRule($rule_name, $rule_definition);
@@ -90,15 +113,45 @@ public static function addRule(string $rule_name, $rule_definition):string
90113
return $message;
91114
}
92115

93-
public static function getAllKeys():array
116+
public static function getAllLocalKeys():array
94117
{
95118
return array_keys(self::$repository);
96119
}
97120

121+
public static function getAllRedisKeys():array
122+
{
123+
if (!self::$is_redis_connected) {
124+
self::$logger->debug("[getAllRedisKeys] Redis not connected");
125+
return [];
126+
}
127+
128+
$keys = self::$redis_connector->keys('*');
129+
$keys_count = count($keys);
130+
131+
self::$logger->debug("[getAllRedisKeys] Returned {$keys_count} key(s)");
132+
133+
return $keys;
134+
}
135+
136+
public static function getAllKeys(bool $use_keys_from_redis):array
137+
{
138+
if (!self::$is_redis_connected) {
139+
self::$logger->debug("[getAllKeys] Redis not connected");
140+
return [];
141+
}
142+
143+
$keys = $use_keys_from_redis ? self::$redis_connector->keys('*') : array_keys(self::$repository);
144+
$keys_count = count($keys);
145+
146+
self::$logger->debug("[getAllKeys] Returned {$keys_count} key(s)");
147+
148+
return $keys;
149+
}
150+
98151
public static function get(string $key, $default = null)
99152
{
100153
if (self::check($key)) {
101-
self::$logger->debug("Recieved `{$key}` from cache");
154+
self::$logger->debug("Received `{$key}` from cache");
102155
return self::$repository[ $key ];
103156
}
104157
return $default;
@@ -110,7 +163,7 @@ public static function set(string $key, $data)
110163
self::$repository[ $key ] = $data;
111164
}
112165

113-
public static function check(string $key)
166+
public static function check(string $key): bool
114167
{
115168
return array_key_exists($key, self::$repository);
116169
}
@@ -139,15 +192,16 @@ public static function flush(string $key, bool $clean_redis = true):string
139192
return $key;
140193
} else {
141194
$custom_mask = self::createMask($key);
142-
$custom_list = preg_grep($custom_mask, self::getAllKeys());
195+
$all_keys = $clean_redis ? self::getAllRedisKeys() : self::getAllLocalKeys();
196+
$custom_list = preg_grep($custom_mask, $all_keys);
143197
foreach ($custom_list as $k) {
144198
self::flush($k, $clean_redis);
145199
}
146200
return $custom_mask;
147201
}
148202
}
149203

150-
public static function redisFetch(string $key_name, $use_json_decode = true)
204+
public static function redisFetch(string $key_name, bool $use_json_decode = true)
151205
{
152206
if (self::$is_redis_connected === false) {
153207
return null;
@@ -168,7 +222,7 @@ public static function redisPush(string $key_name, $data, int $ttl = 0):bool
168222
return false;
169223
}
170224

171-
self::$redis_connector->set($key_name, self::jsonize($data));
225+
self::$redis_connector->set($key_name, CacheHelper::jsonize($data));
172226

173227
if ($ttl > 0) {
174228
self::$redis_connector->expire($key_name, $ttl);
@@ -188,20 +242,24 @@ public static function redisDel(string $key_name)
188242
}
189243

190244
$deleted = [];
191-
192-
if (strpos($key_name, '*') === false) {
245+
246+
if ($key_name === '*') {
247+
self::$redis_connector->flushDb();
248+
$deleted = [ '*' ];
249+
} elseif (strpos($key_name, '*') === false) {
193250
self::$redis_connector->del($key_name);
194-
return $key_name;
251+
$deleted = [ $key_name ];
195252
} else {
196253
$custom_mask = self::createMask($key_name);
197254
$custom_list = preg_grep($custom_mask, self::$redis_connector->keys('*'));
198-
// $custom_list = self::$redis_connector->keys($key_name);
199-
255+
200256
foreach ($custom_list as $k) {
201257
$deleted[] = self::redisDel($k);
202258
}
203-
return $deleted;
259+
204260
}
261+
return $deleted;
262+
205263
// return !(self::$redis_connector->exists($key_name));
206264
}
207265

@@ -265,7 +323,7 @@ public static function decrCounter(string $key, int $diff = 1):int
265323
return self::$repository[ $key ];
266324
}
267325

268-
public static function getCounter(string $key, $default = 0):int
326+
public static function getCounter(string $key, int $default = 0):int
269327
{
270328
if (self::$is_redis_connected) {
271329
return self::$redis_connector->get($key);
@@ -299,8 +357,7 @@ private static function defineRule($rule_name, $rule_definition)
299357

300358
if ($rule_value !== false) {
301359
self::set($rule_name, json_decode($rule_value, true, 512, JSON_THROW_ON_ERROR));
302-
$message = "Loaded `{$rule_name}` from redis, stored to cache";
303-
return $message;
360+
return "[INFO] Loaded `{$rule_name}` from redis, stored to cache";
304361
}
305362
}
306363

@@ -315,50 +372,51 @@ private static function defineRule($rule_name, $rule_definition)
315372

316373
// если ACTION пуст - кладем в репозиторий NULL и продолжаем
317374
if (empty($action)) {
318-
$message = '[ERROR] Key not found, but action is empty';
375+
$message = "[ERROR] Key found, but action is empty";
319376
self::set($rule_name, null);
320377
return $message;
321378
}
322379

323-
$data = '';
380+
switch ($rule_definition['source']) {
381+
case self::RULE_SOURCE_SQL: {
382+
// коннекта к БД нет: кладем в репозиторий null и продолжаем
383+
if (is_null(self::$pdo)) {
384+
$message = '[ERROR] Key not found, PDO not defined';
385+
self::set($rule_name, null);
386+
return $message;
387+
}
324388

325-
// если источник данных SQL
326-
if ($rule_definition['source'] === self::RULE_SOURCE_SQL) {
389+
$sth = self::$pdo->query($rule_definition['action']);
390+
if (false === $sth) {
391+
$message = '[ERROR] Key not found, PDO present, PDO Answer invalid';
392+
self::set($rule_name, null);
393+
return $message;
394+
}
395+
$data = $sth->fetchAll();
396+
$message = "Data for `{$rule_name}` fetched from DB,";
327397

328-
// коннекта к БД нет: кладем в репозиторий null и продолжаем
329-
if (is_null(self::$pdo)) {
330-
$message = '[ERROR] Key not found, PDO not defined';
331-
self::set($rule_name, null);
332-
return $message;
398+
break;
333399
}
400+
case self::RULE_SOURCE_RAW: {
401+
$data = $rule_definition['data'];
402+
$message = "Data for `{$rule_name}` fetched raw data,";
334403

335-
$sth = self::$pdo->query($rule_definition['action']);
336-
if (false === $sth) {
337-
$message = '[ERROR] Key not found, PDO present, PDO Answer invalid';
338-
self::set($rule_definition, null);
339-
return $message;
404+
break;
405+
}
406+
// case self::RULE_SOURCE_CALLBACK
407+
default: {
408+
[$actor, $params] = self::compileCallbackHandler($rule_definition['action']);
409+
$data = call_user_func_array($actor, $params);
410+
$message = "Data for `{$rule_name}` fetched from callback,";
340411
}
341-
$data = $sth->fetchAll();
342-
$message = "Data for `{$rule_name}` fetched from DB,";
343412
}
344413

345-
if ($rule_definition['source'] === self::RULE_SOURCE_CALLBACK) {
346-
[$actor, $params] = self::compileCallbackHandler($rule_definition['action']);
347-
$data = call_user_func_array($actor, $params);
348-
$message = "Data for `{$rule_name}` fetched from callback,";
349-
}
350-
351-
if ($rule_definition['source'] === self::RULE_SOURCE_RAW) {
352-
$data = $rule_definition['data'];
353-
$message = "Data for `{$rule_name}` fetched raw data,";
354-
}
355-
356414
// кладем результат в репозиторий
357415
self::set($rule_name, $data);
358416

359417
// и в редис, если он запущен
360418
if (self::$is_redis_connected) {
361-
self::$redis_connector->set($rule_name, self::jsonize($data));
419+
self::$redis_connector->set($rule_name, CacheHelper::jsonize($data));
362420
if ($ttl > 0) {
363421
self::$redis_connector->expire($rule_name, $ttl);
364422
}
@@ -374,18 +432,6 @@ public static function isRedisConnected():bool
374432
{
375433
return self::$is_redis_connected;
376434
}
377-
378-
379-
/**
380-
*
381-
* @param $data
382-
* @return false|string
383-
* @throws JsonException
384-
*/
385-
private static function jsonize($data)
386-
{
387-
return json_encode($data, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_THROW_ON_ERROR);
388-
}
389435

390436
/**
391437
* Перезаписывает набор дефолтных значений на основе переданного списка опций
@@ -432,7 +478,6 @@ private static function compileCallbackHandler($actor)
432478
$handler = $actor[0];
433479
$params = (count($actor) > 1) ? $actor[1] : [];
434480

435-
//@todo: нужна проверка is_string() - но зачем?
436481
if (!is_string($handler)) {
437482
throw new CacheCallbackException("First argument of callback array is NOT a string");
438483
}

src/CacheHelper.php

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

33
namespace Arris\Cache;
44

5+
use JsonException;
56
use function mb_strpos;
67
use function array_filter;
78

@@ -104,13 +105,23 @@ public static function sortHashBySubkey(array $dataset, string $order_by, bool $
104105
* @param string $flag
105106
* @param int $value
106107
* @param int $ttl
107-
* @throws \JsonException
108+
* @throws JsonException
108109
*/
109110
public static function raiseFlag(string $flag, int $value = 1, $ttl = 86400)
110111
{
111112
Cache::redisPush($flag, $value, $ttl);
112113
}
113-
114114

115-
115+
/**
116+
* Конвертирует в JSON
117+
*
118+
* @param $data
119+
* @return false|string
120+
* @throws JsonException
121+
*/
122+
public static function jsonize($data)
123+
{
124+
return json_encode($data, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_THROW_ON_ERROR);
125+
}
126+
116127
}

0 commit comments

Comments
 (0)