Symfony-hexagonal-skill symfony-messenger-async
Symfony Messenger async processing — message queues, retry strategies, failure transport, Symfony Scheduler, idempotency patterns, background jobs. Triggers on: messenger, async, queue, retry, scheduler, background job, worker, transport, message queue, cron, scheduled task
install
source · Clone the upstream repo
git clone https://github.com/aligundogdu/symfony-hexagonal-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/aligundogdu/symfony-hexagonal-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/symfony-messenger-async" ~/.claude/skills/aligundogdu-symfony-hexagonal-skill-symfony-messenger-async && rm -rf "$T"
manifest:
skills/symfony-messenger-async/SKILL.mdsource content
Symfony Messenger & Async Processing
You are an expert in async message processing with Symfony Messenger within hexagonal architecture.
When to Activate
- User needs async processing or background jobs
- User asks about message queues or retry strategies
- User mentions cron jobs (redirect to Scheduler)
- User needs idempotency or failure handling
- User asks about Symfony Scheduler
Core Principle: No Cron Jobs
Never use raw cron. Always use:
- Symfony Messenger for async message processing
- Symfony Scheduler for recurring tasks
Async Command Pattern
// The command is the same — async is a routing concern, not a code concern namespace App\Application\Report\Command; final readonly class GenerateReport { public function __construct( public string $reportId, public string $userId, public string $type, ) { } } // Handler is identical to sync — the bus handles async dispatch #[AsMessageHandler(bus: 'command.bus')] final readonly class GenerateReportHandler { public function __invoke(GenerateReport $command): void { // Long-running operation } }
# Route to async transport framework: messenger: routing: 'App\Application\Report\Command\GenerateReport': async
Idempotency
Every async handler MUST be idempotent — safe to retry:
#[AsMessageHandler(bus: 'command.bus')] final readonly class ProcessPaymentHandler { public function __construct( private PaymentRepositoryInterface $paymentRepository, private PaymentGatewayInterface $paymentGateway, ) { } public function __invoke(ProcessPayment $command): void { // Check if already processed (idempotency) $existing = $this->paymentRepository->findByIdempotencyKey($command->idempotencyKey); if ($existing !== null) { return; // Already processed, skip } // Process payment $result = $this->paymentGateway->charge($command->customerId, $command->amount); $this->paymentRepository->save($result); } }
References
See
references/ for detailed guides:
— Full Messenger YAML configurationmessenger-config.md
— Idempotency key strategiesidempotency-patterns.md
— Symfony Scheduler setup and patternsscheduler-patterns.md