Skip to content

Commit 8d4eea7

Browse files
authored
chore: cache refactor (#582)
1 parent 83c103d commit 8d4eea7

32 files changed

+266
-368
lines changed

.env.example

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
ENVIRONMENT=production
1+
# Possible values: local, staging, production, ci, testing, other
2+
ENVIRONMENT=local
3+
4+
# The base URI that's used for all generated URIs
25
BASE_URI=http://localhost
6+
7+
# The CACHE key is used as a global override to turn all caches on or off
8+
# Should be true in production, but null or false in local development
9+
CACHE=null
10+
11+
# Enable or disable discovery cache
312
DISCOVERY_CACHE=false
4-
CACHE=false
13+
14+
# Enable or disable view cache
15+
VIEW_CACHE=false
16+
17+
# Enable or disable project cache (allround cache)
18+
PROJECT_CACHE=false

phpunit.xml.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@
3131
<php>
3232
<env name="ENVIRONMENT" value="testing" />
3333
<env name="BASE_URI" value="" />
34+
<env name="CACHE" value="null" />
35+
<env name="DISCOVERY_CACHE" value="true" />
3436
</php>
3537
</phpunit>

src/Tempest/Cache/src/Cache.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ public function resolve(string $key, Closure $cache, ?DateTimeInterface $expires
2020
public function remove(string $key): void;
2121

2222
public function clear(): void;
23+
24+
public function isEnabled(): bool;
2325
}

src/Tempest/Cache/src/CacheConfig.php

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,32 @@
55
namespace Tempest\Cache;
66

77
use Psr\Cache\CacheItemPoolInterface;
8-
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
98
use function Tempest\env;
109

1110
final class CacheConfig
1211
{
1312
/** @var class-string<\Tempest\Cache\Cache>[] */
1413
public array $caches = [];
1514

16-
public bool $enabled;
15+
public ?bool $enable;
16+
17+
public bool $projectCache = false;
18+
19+
public bool $viewCache = false;
20+
21+
public bool $discoveryCache = false;
1722

1823
public function __construct(
19-
public CacheItemPoolInterface $pool = new FilesystemAdapter(
20-
namespace: '',
21-
defaultLifetime: 0,
22-
directory: __DIR__ . '/../../../../.cache',
23-
),
24-
?bool $enabled = null,
24+
public string $directory = __DIR__ . '/../../../../.cache',
25+
public ?CacheItemPoolInterface $projectCachePool = null,
26+
27+
/** Used as a global override, should be true in production, null in local */
28+
?bool $enable = null,
2529
) {
26-
$this->enabled = $enabled ?? env('CACHE', true);
30+
$this->enable = $enable ?? env('CACHE') ?? null;
31+
$this->projectCache = (bool) env('PROJECT_CACHE', false);
32+
$this->viewCache = (bool) env('VIEW_CACHE', false);
33+
$this->discoveryCache = (bool) env('DISCOVERY_CACHE', false);
2734
}
2835

2936
/** @param class-string<\Tempest\Cache\Cache> $className */

src/Tempest/Cache/src/CacheInitializer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
final readonly class CacheInitializer implements Initializer
1212
{
1313
#[Singleton]
14-
public function initialize(Container $container): Cache|GenericCache
14+
public function initialize(Container $container): Cache|ProjectCache
1515
{
16-
return new GenericCache($container->get(CacheConfig::class));
16+
return new ProjectCache($container->get(CacheConfig::class));
1717
}
1818
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Cache;
6+
7+
use Tempest\Console\Console;
8+
use Tempest\Console\ConsoleCommand;
9+
use Tempest\Console\HasConsole;
10+
use Tempest\Container\Container;
11+
12+
final readonly class CacheStatusCommand
13+
{
14+
use HasConsole;
15+
16+
public function __construct(
17+
private Console $console,
18+
private CacheConfig $cacheConfig,
19+
private Container $container,
20+
) {
21+
}
22+
23+
#[ConsoleCommand(name: 'cache:status', aliases: ['cs'])]
24+
public function __invoke(): void
25+
{
26+
$caches = $this->cacheConfig->caches;
27+
28+
foreach ($caches as $cacheClass) {
29+
/** @var Cache $cache */
30+
$cache = $this->container->get($cacheClass);
31+
32+
$reason = match($this->cacheConfig->enable) {
33+
true => ' (global CACHE = true)',
34+
false => ' (global CACHE = false)',
35+
null => '',
36+
};
37+
38+
$this->writeln(sprintf(
39+
'<em>%s</em> %s%s',
40+
$cacheClass,
41+
$cache->isEnabled() ? '<success>enabled</success>' : '<error>disabled</error>',
42+
$reason
43+
));
44+
}
45+
}
46+
}

src/Tempest/Cache/src/GenericCache.php

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Tempest/Cache/src/IsCache.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ trait IsCache
1313
{
1414
abstract protected function getCachePool(): CacheItemPoolInterface;
1515

16-
abstract protected function isEnabled(): bool;
17-
1816
public function put(string $key, mixed $value, ?DateTimeInterface $expiresAt = null): CacheItemInterface
1917
{
2018
$item = $this->getCachePool()
@@ -25,13 +23,19 @@ public function put(string $key, mixed $value, ?DateTimeInterface $expiresAt = n
2523
$item = $item->expiresAt($expiresAt);
2624
}
2725

28-
$this->getCachePool()->save($item);
26+
if ($this->isEnabled()) {
27+
$this->getCachePool()->save($item);
28+
}
2929

3030
return $item;
3131
}
3232

3333
public function get(string $key): mixed
3434
{
35+
if (! $this->isEnabled()) {
36+
return null;
37+
}
38+
3539
return $this->getCachePool()->getItem($key)->get();
3640
}
3741

@@ -53,6 +57,10 @@ public function resolve(string $key, Closure $cache, ?DateTimeInterface $expires
5357

5458
public function remove(string $key): void
5559
{
60+
if (! $this->isEnabled()) {
61+
return;
62+
}
63+
5664
$this->getCachePool()->deleteItem($key);
5765
}
5866

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Cache;
6+
7+
use Psr\Cache\CacheItemPoolInterface;
8+
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
9+
use function Tempest\path;
10+
11+
final class ProjectCache implements Cache
12+
{
13+
use IsCache;
14+
15+
private CacheItemPoolInterface $pool;
16+
17+
public function __construct(
18+
private readonly CacheConfig $cacheConfig,
19+
) {
20+
$this->pool = $this->cacheConfig->projectCachePool ?? new FilesystemAdapter(
21+
directory: path($this->cacheConfig->directory, 'project'),
22+
);
23+
}
24+
25+
protected function getCachePool(): CacheItemPoolInterface
26+
{
27+
return $this->pool;
28+
}
29+
30+
public function isEnabled(): bool
31+
{
32+
return $this->cacheConfig->enable ?? $this->cacheConfig->projectCache;
33+
}
34+
}

src/Tempest/Cache/tests/CacheTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use PHPUnit\Framework\TestCase;
99
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1010
use Tempest\Cache\CacheConfig;
11-
use Tempest\Cache\GenericCache;
11+
use Tempest\Cache\ProjectCache;
1212
use Tempest\Clock\MockClock;
1313

1414
/**
@@ -20,7 +20,7 @@ public function test_put(): void
2020
{
2121
$clock = new MockClock();
2222
$pool = new ArrayAdapter(clock: $clock);
23-
$cache = new GenericCache(new CacheConfig($pool));
23+
$cache = new ProjectCache(new CacheConfig(projectCachePool: $pool, enable: true));
2424
$interval = new DateInterval('P1D');
2525

2626
$cache->put('a', 'a', $clock->now()->add($interval));
@@ -44,7 +44,7 @@ public function test_get(): void
4444
{
4545
$clock = new MockClock();
4646
$pool = new ArrayAdapter(clock: $clock);
47-
$cache = new GenericCache(new CacheConfig($pool));
47+
$cache = new ProjectCache(new CacheConfig(projectCachePool: $pool, enable: true));
4848
$interval = new DateInterval('P1D');
4949

5050
$cache->put('a', 'a', $clock->now()->add($interval));
@@ -64,10 +64,10 @@ public function test_resolve(): void
6464
$clock = new MockClock();
6565
$pool = new ArrayAdapter(clock: $clock);
6666
$config = new CacheConfig(
67-
pool: $pool,
68-
enabled: true,
67+
projectCachePool: $pool,
68+
enable: true,
6969
);
70-
$cache = new GenericCache($config);
70+
$cache = new ProjectCache($config);
7171
$interval = new DateInterval('P1D');
7272

7373
$a = $cache->resolve('a', fn () => 'a', $clock->now()->add($interval));
@@ -88,7 +88,7 @@ public function test_resolve(): void
8888
public function test_remove(): void
8989
{
9090
$pool = new ArrayAdapter();
91-
$cache = new GenericCache(new CacheConfig($pool));
91+
$cache = new ProjectCache(new CacheConfig(projectCachePool: $pool, enable: true));
9292

9393
$cache->put('a', 'a');
9494

@@ -100,7 +100,7 @@ public function test_remove(): void
100100
public function test_clear(): void
101101
{
102102
$pool = new ArrayAdapter();
103-
$cache = new GenericCache(new CacheConfig($pool));
103+
$cache = new ProjectCache(cacheConfig: new CacheConfig(projectCachePool: $pool));
104104

105105
$cache->put('a', 'a');
106106
$cache->put('b', 'b');

0 commit comments

Comments
 (0)