Issues (61)

src/CacheInterceptor.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\QueryRepository;
6
7
use BEAR\QueryRepository\Exception\LogicException;
8
use BEAR\Resource\ResourceObject;
9
use Override;
10
use Ray\Aop\MethodInterceptor;
11
use Ray\Aop\MethodInvocation;
12
use Throwable;
13
14
use function assert;
15
use function sprintf;
16
use function trigger_error;
17
18 24
use const E_USER_WARNING;
19
20
/**
21 24
 * Interceptor for TTL-based caching on CQRS queries with #[Cacheable]
22 24
 *
23
 * Bound to query methods (onGet) of classes marked with #[Cacheable].
24
 * Retrieves cached resource state if available, otherwise executes
25
 * the method and stores the result with configured TTL.
26
 *
27 22
 * @see \BEAR\RepositoryModule\Annotation\Cacheable
28
 * @see https://bearsunday.github.io/manuals/1.0/en/cache.html#cacheable
29
 */
30 22
final readonly class CacheInterceptor implements MethodInterceptor
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_READONLY, expecting T_CLASS on line 30 at column 6
Loading history...
31 22
{
32 22
    public function __construct(
33 12
        private QueryRepositoryInterface $repository,
34
    ) {
35 12
    }
36
37
    /**
38
     * {@inheritDoc}
39 22
     */
40 22
    #[Override]
41 1
    public function invoke(MethodInvocation $invocation)
42 1
    {
43
        $ro = $invocation->getThis();
44 1
        assert($ro instanceof ResourceObject);
45
        try {
46
            $state = $this->repository->get($ro->uri);
47 21
        } catch (Throwable $e) {
48
            $this->triggerWarning($e);
49
50
            return $invocation->proceed(); // @codeCoverageIgnore
51
        }
52
53
        if ($state instanceof ResourceState) {
54
            $state->visit($ro);
55
56
            return $ro;
57
        }
58
59
        /** @psalm-suppress MixedAssignment */
60
        $ro = $invocation->proceed();
61
        assert($ro instanceof ResourceObject);
62
        try {
63
            $ro->code === 200 ? $this->repository->put($ro) : $this->repository->purge($ro->uri);
64
        } catch (LogicException $e) {
65
            throw $e;
66
        } catch (Throwable $e) {  // @codeCoverageIgnore
67
            $this->triggerWarning($e); // @codeCoverageIgnore
68
        }
69
70
        return $ro;
71
    }
72
73
    /**
74
     * Trigger warning
75
     *
76
     * When the cache server is down, it will issue a warning rather than an exception to continue service.
77
     *
78
     * @codeCoverageIgnore
79
     */
80
    private function triggerWarning(Throwable $e): void
81
    {
82
        $message = sprintf('%s: %s in %s:%s', $e::class, $e->getMessage(), $e->getFile(), $e->getLine());
83
        trigger_error($message, E_USER_WARNING);
84
    }
85
}
86