Observability

Cache

Cache stores, PSR-6 integration and practical diagnostics boundaries.

Overview

Cache module is a standalone runtime service registered by CacheServiceProvider. It provides PSR-6 pools and CacheManager convenience methods for rebuildable data.

Provider wiring

CacheServiceProvider registers cache pool implementations, chooses default pool from config and exposes both class-based and string aliases.

$container->singleton(CacheItemPoolInterface::class, static function (ContainerInterface $container): CacheItemPoolInterface {
    $config = $container->get(Config::class);
    $context = $container->get(ApplicationContext::class);
    $directories = $container->get(DirectoryManagerInterface::class);

    $default = (string) $config->get('cache.default', 'file');

    return match ($default) {
        'array' => new ArrayCacheItemPool(),
        'null' => new NullCacheItemPool(),
        'file' => new FileCacheItemPool(
            directory: $context->resolveStoragePath(
                (string) $config->get('cache.stores.file.path', 'cache/framework')
            ),
            directoryManager: $directories,
        ),
        default => throw new RuntimeException(sprintf('Unsupported cache store "%s".', $default)),
    };
});

$container->singleton(CacheManager::class, static fn (ContainerInterface $container): CacheManager => new CacheManager(
    $container->get(CacheItemPoolInterface::class),
));
$container->singleton('cache', CacheManager::class);

Cache configuration

Default store is selected through cache.default. File store uses cache.stores.file.path resolved via ApplicationContext::resolveStoragePath().

CACHE_DEFAULT=file
CACHE_FILE_PATH=cache/framework

Cache manager usage

CacheManager wraps the configured PSR-6 pool and provides common operations such as get, put, remember, rememberForever, has, forget and clear.

$value = $cache->remember(
    key: 'documentation.catalog.pages',
    ttlSeconds: 3600,
    callback: fn () => $this->buildPages(),
);

$cache->put('homepage.stats', $stats, 300);

$cache->forget('documentation.catalog.pages');

Cache services

Services may type-hint Psr\Cache\CacheItemPoolInterface when they need direct PSR-6 access. Cache keys are validated through Lemonade\Framework\Cache\CacheKeyValidator, and invalid keys fail explicitly with Lemonade\Framework\Cache\Exception\InvalidCacheKeyException.

$item = $pool->getItem('documentation.catalog.pages');

if (!$item->isHit()) {
    $item->set($this->buildPages());
    $item->expiresAfter(3600);

    $pool->save($item);
}

$pages = $item->get();

Diagnostics and limitations

Framework does not expose built-in cache metrics API (hit/miss counters, timings or dashboard telemetry) as part of cache public API. Cache observability is primarily operational: use application logging and benchmark context around cache-heavy code paths when needed.

Cache stores

The framework supports multiple cache store implementations. file persists cache entries under storage/cache, array keeps values only for the current process, and null validates calls but never stores values. The null store is useful for tests and for disabling cache behavior without changing application code.

Invalidation strategy

Cache values should be treated as rebuildable data. Prefer stable, namespaced keys such as documentation.catalog.pages or schema.metadata.tables. Clear or replace cache entries after configuration changes, deployment changes or changes to source definitions that affect cached output.

$cache->forget('documentation.catalog.pages');

$cache->clear();