-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathRatingListCache.php
97 lines (76 loc) · 2.54 KB
/
RatingListCache.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php declare(strict_types=1);
namespace h4kuna\Exchange\RatingList;
use h4kuna\CriticalCache\PSR16\CacheLocking;
use h4kuna\CriticalCache\Utils\Dependency;
use h4kuna\Exchange\Download\SourceDownloadInterface;
use h4kuna\Exchange\Exceptions\InvalidStateException;
use h4kuna\Exchange\Utils;
use Nette\Utils\DateTime;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\SimpleCache\CacheInterface;
final class RatingListCache
{
public int $floatTtl = Utils::CacheMinutes - DateTime::MINUTE; // 29 minutes
public function __construct(
private CacheLocking $cache,
private SourceDownloadInterface $sourceDownload,
)
{
}
/**
* @throws ClientExceptionInterface
*/
public function build(CacheEntity $cacheEntity): RatingListInterface
{
$ratingList = null;
$this->cache->load($cacheEntity->cacheKeyTtl, function (
Dependency $dependency,
CacheInterface $cache,
) use ($cacheEntity, &$ratingList): string {
[$ratingList, $ttl] = $this->buildCache($cacheEntity, $cache);
$dependency->ttl = $ttl;
return self::toDate($ratingList);
});
if ($ratingList === null) {
$ratingList = $this->cache->get($cacheEntity->cacheKeyAll);
if (($ratingList instanceof RatingListInterface) === false) {
throw new InvalidStateException('Cache is broken.');
}
}
return $ratingList;
}
/**
* @return array{RatingListInterface, ?int}
* @throws ClientExceptionInterface
*/
private function buildCache(CacheEntity $cacheEntity, CacheInterface $cache): array
{
try {
$ratingList = $this->sourceDownload->execute($cacheEntity->source, $cacheEntity->date);
} catch (ClientExceptionInterface $e) {
$ratingList = $cache->get($cacheEntity->cacheKeyAll);
if (($ratingList instanceof RatingListInterface) === false) {
throw $e;
}
$ratingList->getExpire()?->modify(sprintf('now, +%s seconds', Utils::CacheMinutes));
}
$ttl = $ratingList->getExpire() === null ? null : Utils::countTTL($ratingList->getExpire(), $this->floatTtl);
$this->cache->set($cacheEntity->cacheKeyAll, $ratingList);
return [$ratingList, $ttl];
}
/**
* @throws ClientExceptionInterface
*/
public function rebuild(CacheEntity $cacheEntity): bool
{
$oldValue = $this->cache->get($cacheEntity->cacheKeyTtl);
[$ratingList, $ttl] = $this->buildCache($cacheEntity, $this->cache);
$value = self::toDate($ratingList);
$this->cache->set($cacheEntity->cacheKeyTtl, $value, $ttl);
return $oldValue !== $value;
}
private static function toDate(RatingListInterface $ratingList): string
{
return $ratingList->getDate()->format(DATE_RFC3339);
}
}