| name | create-idempotency-handler |
| description | Generates Idempotency Handler for PHP 8.4. Creates PSR-15 middleware with Redis-backed deduplication, IdempotencyKey value object, and storage interface. Includes unit tests. |
Idempotency Handler Generator
Creates idempotency handling infrastructure for safe request deduplication.
When to Use
| Scenario | Example |
|---|
| Payment processing | Prevent duplicate charges on retry |
| Order creation | Avoid duplicate orders from network retries |
| Webhook handling | Deduplicate incoming webhook deliveries |
| API mutations | Ensure POST/PUT/PATCH safety on retry |
Component Characteristics
IdempotencyKey
- Value Object validating UUID v4 format
- Immutable, self-validating on construction
- Extracted from
Idempotency-Key HTTP header
IdempotencyStorageInterface
- Storage contract for idempotency records
- Methods:
exists(), store(), get(), remove()
- TTL-based expiration support
RedisIdempotencyStorage
- Redis SETNX implementation for atomic check-and-store
- Configurable TTL for automatic key expiration
- Stores serialized response for replay
IdempotencyMiddleware
- PSR-15 middleware intercepting requests
- Checks for existing idempotency key before processing
- Stores response after successful processing
- Returns cached response on duplicate request
IdempotencyException
- Thrown when duplicate request detected without stored response
- Contains the conflicting idempotency key
Generation Process
Step 1: Generate Core Components
Path: src/Infrastructure/Idempotency/
IdempotencyKey.php — Value Object with UUID validation
IdempotencyException.php — Duplicate request exception
StoredResponse.php — Serializable response wrapper
Step 2: Generate Storage Layer
Path: src/Infrastructure/Idempotency/
IdempotencyStorageInterface.php — Storage contract
RedisIdempotencyStorage.php — Redis SETNX + TTL implementation
Step 3: Generate Middleware
Path: src/Infrastructure/Idempotency/
IdempotencyMiddleware.php — PSR-15 middleware
Step 4: Generate Tests
IdempotencyKeyTest.php — Value Object validation tests
IdempotencyMiddlewareTest.php — Middleware behavior tests
File Placement
| Component | Path |
|---|
| All Classes | src/Infrastructure/Idempotency/ |
| Unit Tests | tests/Unit/Infrastructure/Idempotency/ |
Naming Conventions
| Component | Pattern | Example |
|---|
| Value Object | IdempotencyKey | IdempotencyKey |
| Storage Interface | IdempotencyStorageInterface | IdempotencyStorageInterface |
| Redis Storage | RedisIdempotencyStorage | RedisIdempotencyStorage |
| Middleware | IdempotencyMiddleware | IdempotencyMiddleware |
| Response VO | StoredResponse | StoredResponse |
| Exception | IdempotencyException | IdempotencyException |
| Test | {ClassName}Test | IdempotencyKeyTest |
Quick Template Reference
IdempotencyKey
final readonly class IdempotencyKey
{
public function __construct(public string $value)
{
}
public static function fromHeader(string $headerValue): self;
public function toString(): string;
}
IdempotencyStorageInterface
interface IdempotencyStorageInterface
{
public function exists(IdempotencyKey $key): bool;
public function store(IdempotencyKey $key, StoredResponse $response, int $ttl): void;
public function get(IdempotencyKey $key): ?StoredResponse;
public function remove(IdempotencyKey $key): void;
}
IdempotencyMiddleware
final readonly class IdempotencyMiddleware implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface;
}
Usage Example
$middleware = new IdempotencyMiddleware(
storage: $redisStorage,
ttl: 86400,
headerName: 'Idempotency-Key'
);
Request Flow
Request ──→ Extract Idempotency-Key header
│
Key exists in storage?
│ │
YES NO
│ │
Return stored Process request
response │
Store response
│
Return response
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|
| No TTL on keys | Storage grows unbounded | Set TTL (e.g., 24h) |
| In-memory storage | Lost on restart, no clustering | Use Redis or database |
| Idempotency on GET | GET is already idempotent | Only apply to mutations |
| Missing key validation | Accept invalid keys | Validate UUID format |
| No response caching | Cannot replay response | Store full response |
| Race conditions | Concurrent duplicates | Use SETNX atomic operation |
References
For complete PHP templates and examples, see:
references/templates.md — IdempotencyKey, StorageInterface, RedisStorage, Middleware templates
references/examples.md — API integration examples and tests