Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
CachedQueryBus
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
2 / 2
4
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dispatch
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10namespace Phexium\Plugin\QueryBus\Adapter;
11
12use DateInterval;
13use Override;
14use Phexium\Application\Query\CacheableQueryInterface;
15use Phexium\Application\Query\QueryInterface;
16use Phexium\Application\Query\QueryResponseInterface;
17use Phexium\Plugin\Cache\Port\CacheInterface;
18use Phexium\Plugin\Logger\Port\LoggerInterface;
19use Phexium\Plugin\QueryBus\Internal\QueryCacheKeyGenerator;
20use Phexium\Plugin\QueryBus\Port\QueryBusInterface;
21
22final readonly class CachedQueryBus implements QueryBusInterface
23{
24    public function __construct(
25        private QueryBusInterface $innerQueryBus,
26        private CacheInterface $cache,
27        private LoggerInterface $logger,
28        private DateInterval|int|null $defaultTtl = 300,
29    ) {}
30
31    #[Override]
32    public function dispatch(QueryInterface $query): QueryResponseInterface
33    {
34        if (!$query instanceof CacheableQueryInterface) {
35            return $this->innerQueryBus->dispatch($query);
36        }
37
38        $cacheKey = QueryCacheKeyGenerator::generate($query);
39        $cachedResponse = $this->cache->get($cacheKey);
40
41        if ($cachedResponse instanceof QueryResponseInterface) {
42            $this->logger->debug('Cache hit for query', [
43                'query' => $query::class,
44                'cacheKey' => $cacheKey,
45            ]);
46
47            return $cachedResponse;
48        }
49
50        $response = $this->innerQueryBus->dispatch($query);
51
52        $ttl = $query->getCacheTtl() ?? $this->defaultTtl;
53
54        $this->cache->set($cacheKey, $response, $ttl);
55
56        $this->logger->debug('Cache miss for query', [
57            'query' => $query::class,
58            'cacheKey' => $cacheKey,
59            'ttl' => $ttl,
60        ]);
61
62        return $response;
63    }
64}