Awesome-claude-code create-cache-aside

Generates Cache-Aside pattern for PHP 8.4. Creates cache executor with PSR-16 integration, stampede protection via distributed locking, tag-based invalidation, and key generation. Includes unit tests.

install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-cache-aside" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-cache-aside && rm -rf "$T"
manifest: skills/create-cache-aside/SKILL.md
source content

Cache-Aside Generator

Creates Cache-Aside infrastructure with stampede protection and tag-based invalidation.

When to Use

ScenarioExample
Read-heavy workloadsProduct catalog, user profiles
Expensive queriesComplex reports, aggregated data
External API responsesThird-party API caching
Computed valuesPricing calculations, search results

Component Characteristics

CacheAsideInterface

  • get(string $key, callable $loader, int $ttl): mixed
    — load from cache or compute
  • invalidate(string $key): void
    — remove specific cache entry
  • invalidateByTag(string $tag): void
    — remove all entries tagged with given tag

CacheKeyGenerator

  • Builds deterministic cache keys from prefix and parameters
  • Hashes long keys to prevent exceeding storage limits
  • Supports tag-based key grouping

CacheAsideExecutor

  • PSR-16 SimpleCache integration
  • Configurable TTL per cache operation
  • Stampede protection via distributed locking
  • Prevents thundering herd on cache miss

CacheInvalidator

  • Tag-based invalidation (invalidate all entries for a tag)
  • Pattern-based clearing (wildcard key matching)
  • Batch invalidation support

Generation Process

Step 1: Generate Domain Components

Path:

src/Domain/Shared/Cache/

  1. CacheAsideInterface.php
    — Cache-aside contract
  2. CacheKeyGeneratorInterface.php
    — Key generation contract

Step 2: Generate Infrastructure Components

Path:

src/Infrastructure/Cache/

  1. CacheKeyGenerator.php
    — Key builder with hashing
  2. CacheAsideExecutor.php
    — PSR-16 cache executor with locking
  3. CacheInvalidator.php
    — Tag-based and pattern-based invalidation
  4. CacheLockInterface.php
    — Distributed lock contract
  5. RedisCacheLock.php
    — Redis-based lock implementation

Step 3: Generate Tests

  1. CacheKeyGeneratorTest.php
    — Key generation and hashing tests
  2. CacheAsideExecutorTest.php
    — Cache hit/miss, stampede protection tests
  3. CacheInvalidatorTest.php
    — Tag and pattern invalidation tests

File Placement

ComponentPath
Domain Interfaces
src/Domain/Shared/Cache/
Infrastructure
src/Infrastructure/Cache/
Unit Tests
tests/Unit/Infrastructure/Cache/

Naming Conventions

ComponentPatternExample
Interface
CacheAsideInterface
CacheAsideInterface
Key Generator
CacheKeyGenerator
CacheKeyGenerator
Executor
CacheAsideExecutor
CacheAsideExecutor
Invalidator
CacheInvalidator
CacheInvalidator
Lock Interface
CacheLockInterface
CacheLockInterface
Lock Impl
{Store}CacheLock
RedisCacheLock
Test
{ClassName}Test
CacheAsideExecutorTest

Quick Template Reference

CacheAsideInterface

interface CacheAsideInterface
{
    /**
     * @template T
     * @param callable(): T $loader
     * @return T
     */
    public function get(string $key, callable $loader, int $ttl = 3600): mixed;
    public function invalidate(string $key): void;
    public function invalidateByTag(string $tag): void;
}

CacheKeyGenerator

final readonly class CacheKeyGenerator
{
    public function __construct(private string $prefix = 'app');
    public function generate(string $context, string ...$parts): string;
    public function generateHashed(string $context, string ...$parts): string;
}

CacheLockInterface

interface CacheLockInterface
{
    public function acquire(string $key, int $ttl = 10): bool;
    public function release(string $key): void;
}

Usage Example

$executor = new CacheAsideExecutor($cache, $lock, defaultTtl: 3600);

// Cache-aside: returns cached value or computes via loader
$product = $executor->get(
    key: 'product:123',
    loader: fn() => $repository->findById(123),
    ttl: 1800
);

// Invalidate on update
$executor->invalidate('product:123');

// Tag-based invalidation
$invalidator->invalidateByTag('products');

Pattern Comparison

PatternDescriptionUse Case
Cache-AsideApp manages cache (check → miss → load → store)Read-heavy, tolerates stale data
Read-ThroughCache loads data on miss (transparent to app)Simpler app code, cache manages loading
Write-ThroughWrite to cache and DB simultaneouslyStrong consistency needed
Write-BehindWrite to cache, async write to DBHigh write throughput, eventual consistency

Anti-patterns to Avoid

Anti-patternProblemSolution
No TTLStale data served foreverAlways set TTL, even long ones
Thundering herdAll requests compute on cache missStampede protection with locking
Cache poisoningInvalid data cachedValidate data before caching
Inconsistent invalidationUpdate DB but forget cacheUse events/listeners for invalidation
Key collisionsDifferent data for same keyUse prefix + context + params
Over-cachingMemory waste, stale dataCache only expensive/frequent operations

References

For complete PHP templates and examples, see:

  • references/templates.md
    — CacheAsideInterface, CacheKeyGenerator, CacheAsideExecutor, CacheInvalidator, lock templates
  • references/examples.md
    — Repository integration, event-driven invalidation, and unit tests