create-idempotent-consumer
Idempotent Consumer Generator
Creates Idempotent Consumer pattern infrastructure for exactly-once message processing guarantees.
When to Use
| Scenario | Example |
|---|---|
| Payment processing | Prevent double charges on message replay |
| Inventory updates | Avoid duplicate stock deductions |
| Event handlers | Process domain events exactly once |
| Webhook processing | Handle duplicate webhook deliveries |
| Message queue consumers | Deduplicate redelivered messages |
Component Characteristics
IdempotencyKey
- Value object combining messageId + handlerName
- Deterministic key generation
- Immutable with toString() representation
IdempotencyStoreInterface
- Application layer port
- has(IdempotencyKey): bool — check if already processed
- mark(IdempotencyKey, DateTimeImmutable ttl): void — mark as processed
- remove(IdempotencyKey): void — remove entry (for reprocessing)
DatabaseIdempotencyStore
- PDO-based implementation
- TTL-based automatic cleanup
- Unique constraint prevents race conditions
RedisIdempotencyStore
- Redis SETNX-based implementation
- TTL via Redis EXPIRE
- Atomic check-and-set
IdempotentConsumerMiddleware
- Wraps message handler
- Checks idempotency before processing
- Marks as processed after success
- Returns ProcessingResult enum
ProcessingResult
- Enum: Processed, Duplicate, Failed
- Includes original result data on success
- Includes reason on duplicate/failure
Generation Process
Step 1: Analyze Request
Determine:
- Storage backend (Database, Redis, or both)
- TTL for idempotency keys (default: 7 days)
- Integration point (middleware, decorator, manual)
Step 2: Generate Core Components
-
Domain Layer (
src/Domain/Shared/Idempotency/)IdempotencyKey.php— Key value objectProcessingResult.php— Result value object with statusProcessingStatus.php— Status enum (Processed/Duplicate/Failed)
-
Application Layer (
src/Application/Shared/Idempotency/)IdempotencyStoreInterface.php— Storage portIdempotentConsumerMiddleware.php— Middleware wrapper
-
Infrastructure Layer (
src/Infrastructure/Idempotency/)DatabaseIdempotencyStore.php— PDO implementationRedisIdempotencyStore.php— Redis implementation- Database migration
-
Tests
IdempotencyKeyTest.phpProcessingResultTest.phpIdempotentConsumerMiddlewareTest.phpDatabaseIdempotencyStoreTest.php
File Placement
| Layer | Path |
|---|---|
| Domain Types | src/Domain/Shared/Idempotency/ |
| Application Port | src/Application/Shared/Idempotency/ |
| Infrastructure | src/Infrastructure/Idempotency/ |
| Unit Tests | tests/Unit/{Layer}/{Path}/ |
Key Principles
Idempotency Strategy
- Generate deterministic key from message ID + handler name
- Check store BEFORE processing
- Mark as processed AFTER successful handling
- Use database unique constraint as safety net
- TTL cleanup prevents unbounded growth
Race Condition Handling
- Use INSERT ... ON CONFLICT (database)
- Use SETNX (Redis)
- If duplicate detected mid-processing, return Duplicate result
TTL Management
- Default TTL: 7 days (configurable)
- Cleanup via cron/scheduled command
- Redis handles TTL automatically via EXPIRE
Naming Conventions
| Component | Pattern | Example |
|---|---|---|
| Key VO | IdempotencyKey |
IdempotencyKey |
| Result VO | ProcessingResult |
ProcessingResult |
| Status Enum | ProcessingStatus |
ProcessingStatus |
| Store Interface | IdempotencyStoreInterface |
IdempotencyStoreInterface |
| DB Store | DatabaseIdempotencyStore |
DatabaseIdempotencyStore |
| Redis Store | RedisIdempotencyStore |
RedisIdempotencyStore |
| Middleware | IdempotentConsumerMiddleware |
IdempotentConsumerMiddleware |
| Test | {ClassName}Test |
IdempotencyKeyTest |
Quick Template Reference
IdempotencyKey
final readonly class IdempotencyKey
{
public function __construct(
public string $messageId,
public string $handlerName,
) {}
public static function fromMessage(string $messageId, string $handlerName): self;
public function toString(): string;
public function equals(self $other): bool;
}
IdempotencyStoreInterface
interface IdempotencyStoreInterface
{
public function has(IdempotencyKey $key): bool;
public function mark(IdempotencyKey $key, \DateTimeImmutable $expiresAt): void;
public function remove(IdempotencyKey $key): void;
}
Usage
$middleware = new IdempotentConsumerMiddleware($store);
$result = $middleware->process(
key: IdempotencyKey::fromMessage($message->id, 'handle_payment'),
handler: fn() => $paymentHandler->handle($message),
ttl: new \DateTimeImmutable('+7 days')
);
match ($result->status) {
ProcessingStatus::Processed => $logger->info('Processed'),
ProcessingStatus::Duplicate => $logger->info('Skipped duplicate'),
ProcessingStatus::Failed => $logger->error('Failed', ['error' => $result->error]),
};
Database Schema
CREATE TABLE idempotency_keys (
key VARCHAR(255) PRIMARY KEY,
handler_name VARCHAR(255) NOT NULL,
processed_at TIMESTAMP(6) NOT NULL,
expires_at TIMESTAMP(6) NOT NULL
);
CREATE INDEX idx_idempotency_expires ON idempotency_keys (expires_at);
References
For complete PHP templates and test examples, see:
references/templates.md— All component templatesreferences/examples.md— Payment handler example and unit tests
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12