Passed
Push — main ( 72c6fa...9344f0 )
by Sílvio
02:59
created

RedisCacheStore::setMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Silviooosilva\CacheerPhp\CacheStore;
4
5
use Exception;
6
use Silviooosilva\CacheerPhp\Utils\CacheLogger;
7
use Silviooosilva\CacheerPhp\Helpers\CacheRedisHelper;
8
use Silviooosilva\CacheerPhp\Interface\CacheerInterface;
9
use Silviooosilva\CacheerPhp\Exceptions\CacheRedisException;
10
use Silviooosilva\CacheerPhp\CacheStore\CacheManager\RedisCacheManager;
11
12
/**
13
 * Class RedisCacheStore
14
 * @author Sílvio Silva <https://github.com/silviooosilva>
15
 * @package Silviooosilva\CacheerPhp
16
 */
17
class RedisCacheStore implements CacheerInterface
18
{
19
  /** @var */
20
  private $redis;
21
22
  /** @param string $namespace */
23
  private string $namespace = '';
24
25
  /**
26
  * @var CacheLogger
27
  */
28
  private $logger = null;
29
30
  /**
31
  * @var string
32
  */
33
  private string $message = '';
34
35
  /**
36
  * @var boolean
37
  */
38
  private bool $success = false;
39
40
41
  /**
42
  * @return void
43
  */
44
  public function __construct(string $logPath)
45
  {
46
    $this->redis = RedisCacheManager::connect();
47
    $this->logger = new CacheLogger($logPath);
48
  }
49
50
  /**
51
  * @param string $cacheKey
52
  * @param string $namespace
53
  * @param string|int $ttl
54
  * @return mixed
55
  */
56
  public function getCache(string $cacheKey, string $namespace = '', string|int $ttl = 3600)
57
  {
58
    $fullCacheKey = $this->buildKey($cacheKey, $namespace);
59
    $cacheData = $this->redis->get($fullCacheKey);
60
61
    if($cacheData) {
62
      $this->setMessage("Cache retrieved successfully", true);
63
      $this->logger->debug("{$this->getMessage()} from redis driver.");
64
      return CacheRedisHelper::serialize($cacheData, false);
65
    }
66
67
    $this->setMessage("CacheData not found, does not exists or expired", false);
68
    $this->logger->info("{$this->getMessage()} from redis driver.");
69
  }
70
71
  /**
72
  * Armazena um item no cache Redis, com suporte a namespace e TTL opcional.
73
  *
74
  * @param string $cacheKey
75
  * @param mixed  $cacheData
76
  * @param string $namespace
77
  * @param string|int|null $ttl
78
  * @return mixed
79
  */
80
  public function putCache(string $cacheKey, mixed $cacheData, string $namespace = '', string|int|null $ttl = null)
81
  {
82
      $cacheFullKey = $this->buildKey($cacheKey, $namespace);
83
      $serializedData = CacheRedisHelper::serialize($cacheData);
84
85
      $result = $ttl ? $this->redis->setex($cacheFullKey, (int) $ttl, $serializedData) 
86
                    : $this->redis->set($cacheFullKey, $serializedData);
87
88
      if ($result) {
89
          $this->setMessage("Cache stored successfully", true);
90
      } else {
91
          $this->setMessage("Failed to store cache", false);
92
      }
93
94
      $this->logger->debug("{$this->getMessage()} from Redis driver.");
95
      return $result;
96
  }
97
98
99
  /**
100
  * @param string $cacheKey
101
  * @param string $namespace
102
  * @return bool
103
  */
104
  public function clearCache(string $cacheKey, string $namespace = '')
105
  {
106
    $cacheFullKey = $this->buildKey($cacheKey, $namespace);
107
108
109
    if($this->redis->del($cacheFullKey) > 0) {
110
        $this->setMessage("Cache cleared successfully", true);
111
    } else {
112
        $this->setMessage("Something went wrong. Please, try again.", false);
113
    }
114
115
116
    $this->logger->debug("{$this->getMessage()} from redis driver.");
117
  }
118
119
  /**
120
  * @param string $cacheKey
121
  * @param string $namespace
122
  * @return void
123
  */
124
  public function has(string $cacheKey, string $namespace = '')
125
  {
126
    $cacheFullKey = $this->buildKey($cacheKey, $namespace);
127
128
    if($this->redis->exists($cacheFullKey) > 0) {
129
        $this->setMessage("Cache Key: {$cacheKey} exists!", true);
130
    } else {
131
        $this->setMessage("Cache Key: {$cacheKey} does not exists!", false);
132
      }
133
134
    $this->logger->debug("{$this->getMessage()} from redis driver.");
135
  }
136
137
  /**
138
  * @param string $cacheKey
139
  * @param string|int $ttl
140
  * @param string $namespace
141
  * @return void
142
  */
143
  public function renewCache(string $cacheKey, string|int $ttl, string $namespace = '')
144
  {
145
      $cacheFullKey = $this->buildKey($cacheKey, $namespace);
146
      $dump = $this->getDump($cacheFullKey);
147
148
      if (!$dump) {
149
          $this->setMessage("Cache Key: {$cacheKey} not found.", false);
150
          $this->logger->warning("{$this->getMessage()} from Redis driver.");
151
          return;
152
      }
153
154
      $this->clearCache($cacheFullKey);
155
156
      if ($this->restoreKey($cacheFullKey, $ttl, $dump)) {
157
          $this->setMessage("Cache Key: {$cacheKey} renewed successfully.", true);
158
          $this->logger->debug("{$this->getMessage()} from Redis driver.");
159
      } else {
160
          $this->setMessage("Failed to renew cache key: {$cacheKey}.", false);
161
          $this->logger->error("{$this->getMessage()} from Redis driver.");
162
      }
163
  }
164
165
166
  /**
167
  * @param string $cacheKey
168
  * @param mixed  $cacheData
169
  * @param string $namespace
170
  * @return void
171
  */
172
  public function appendCache(string $cacheKey, mixed $cacheData, string $namespace = '')
173
  {
174
      $cacheFullKey = $this->buildKey($cacheKey, $namespace);
175
      $existingData = $this->getCache($cacheFullKey);
176
177
      $mergedCacheData = CacheRedisHelper::arrayIdentifier($existingData, $cacheData);
178
179
      $serializedData = CacheRedisHelper::serialize($mergedCacheData);
180
181
      if ($this->redis->set($cacheFullKey, $serializedData)) {
182
          $this->setMessage("Cache appended successfully", true);
183
      } else {
184
          $this->setMessage("Something went wrong. Please, try again.", false);
185
      }
186
187
  
188
      $this->logger->debug("{$this->getMessage()} from redis driver.");
189
  }
190
191
192
  /**
193
  * @param array  $items
194
  * @param string $namespace
195
  * @param int    $batchSize
196
  * @return bool
197
  */
198
  public function putMany(array $items, string $namespace = '', int $batchSize = 100)
199
  {
200
      $processedCount = 0;
201
      $itemCount = count($items);
202
203
      while($processedCount < $itemCount)
204
      {
205
206
        $batchItems = array_slice($items, $processedCount, $batchSize);
207
        $this->processBatchItems($batchItems, $namespace);
208
        $processedCount += count($batchItems);
209
      }
210
211
  }
212
213
  /**
214
  * @return void
215
  */
216
  public function flushCache()
217
  {
218
  
219
    if($this->redis->flushall()) {
220
        $this->setMessage("Cache flushed successfully", true);
221
    } else {
222
        $this->setMessage("Something went wrong. Please, try again.", false);
223
    }
224
225
    $this->logger->debug("{$this->getMessage()} from redis driver.");
226
  }
227
228
    /**
229
     * @return string
230
     */
231
    public function getMessage()
232
    {
233
        return $this->message;
234
    }
235
236
    /**
237
     * @return boolean
238
     */
239
    public function isSuccess()
240
    {
241
        return $this->success;
242
    }
243
244
  /**
245
  * @param string $key
246
  * @param string $namespace
247
  * @return string
248
  */
249
  private function buildKey(string $key, string $namespace)
250
  {
251
    return $this->namespace . ($namespace ? $namespace . ':' : '') . $key;
252
  }
253
254
  /**
255
     * @param string  $message
256
     * @param boolean $success
257
     * @return void
258
     */
259
    private function setMessage(string $message, bool $success)
260
    {
261
        $this->message = $message;
262
        $this->success = $success;
263
    }
264
265
        /**
266
     * @param array  $batchItems
267
     * @param string $namespace
268
     * @return void
269
     */
270
    private function processBatchItems(array $batchItems, string $namespace)
271
    {
272
        foreach($batchItems as $item) {
273
            CacheRedisHelper::validateCacheItem($item);
274
            $cacheKey = $item['cacheKey'];
275
            $cacheData = $item['cacheData'];
276
            $mergedData = CacheRedisHelper::mergeCacheData($cacheData);
277
            $this->putCache($cacheKey, $mergedData, $namespace);
278
        }
279
    }
280
281
      /**
282
  * @param string $fullKey
283
  * @return string|null
284
  */
285
  private function getDump(string $fullKey)
286
  {
287
      return $this->redis->dump($fullKey);
288
  }
289
290
291
  /**
292
  * @param string $fullKey
293
  * @param string|int $ttl
294
  * @param mixed $dump
295
  * @return bool
296
  */
297
  private function restoreKey(string $fullKey, string|int $ttl, mixed $dump)
298
  {
299
      try {
300
          $this->redis->restore($fullKey, $ttl * 1000, $dump, 'REPLACE');
301
          return true;
302
      } catch (Exception $e) {
303
          throw CacheRedisException::create($e->getMessage());
304
      }
305
  }
306
}
307