QueryCacher::__invoke()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 16
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RemotelyLiving\PHPQueryBus\Middleware;
6
7
use Psr\Cache as PSRCache;
8
use RemotelyLiving\PHPQueryBus\DTO;
9
use RemotelyLiving\PHPQueryBus\Interfaces;
10
11
final class QueryCacher
12
{
13
    private PSRCache\CacheItemPoolInterface $cachePool;
14
15
    public function __construct(PSRCache\CacheItemPoolInterface $cachePool)
16
    {
17
        $this->cachePool = $cachePool;
18
    }
19
20
    public function __invoke(object $query, callable $next): Interfaces\Result
21
    {
22
        if (!$query instanceof Interfaces\CacheableQuery) {
23
            return $next($query);
24
        }
25
26
        $cachedResult = $this->cachePool->getItem($query->getCacheKey());
27
28
        if ($query->shouldRecomputeResult() || $this->shouldRecomputeResult($cachedResult)) {
29
            return $this->recomputeResult($cachedResult, $query, $next);
30
        }
31
32
        /** @var DTO\Cache\ResultWrapper $resultWrapper */
33
        $resultWrapper = $cachedResult->get();
34
35
        return $resultWrapper->getResult();
36
    }
37
38
    private function shouldRecomputeResult(PSRCache\CacheItemInterface $cacheItem): bool
39
    {
40
        if (!$cacheItem->isHit()) {
41
            return true;
42
        }
43
44
        if (!is_object($cacheItem->get()) || ($cacheItem->get() instanceof DTO\Cache\ResultWrapper) === false) {
45
            return true;
46
        }
47
48
        /** @var DTO\Cache\ResultWrapper $wrapper */
49
        $wrapper = $cacheItem->get();
50
        return $wrapper->willProbablyExpireSoon();
51
    }
52
53
    private function recomputeResult(
54
        PSRCache\CacheItemInterface $cacheItem,
55
        Interfaces\CacheableQuery $query,
56
        callable $next
57
    ): Interfaces\Result {
58
        $startTime = microtime(true);
59
        /** @var Interfaces\Result $result */
60
        $result = $next($query);
61
        $stopTime = microtime(true);
62
        $computeTime = (int) ($stopTime - $startTime);
63
        $recomputed = $cacheItem->set(DTO\Cache\ResultWrapper::wrap($result, $computeTime, $query->getTTL()))
64
          ->expiresAfter($query->getTTL());
65
66
        $this->cachePool->save($recomputed);
67
68
        return $result;
69
    }
70
}
71