Installation
composer require beyerz/aws-queue-bundle
Ensure beyerz/aws-sdk-bundle (dependency) is also installed.
Register Bundle
Add to config/bundles.php:
Beyerz\AwsQueueBundle\BeyerzAwsQueueBundle::class => ['all' => true],
Configure AWS Credentials
Use beyerz/aws-sdk-bundle to configure AWS SDK (e.g., via config/packages/beyerz_aws.yaml):
beyerz_aws:
region: 'us-east-1'
credentials:
key: '%env(AWS_ACCESS_KEY_ID)%'
secret: '%env(AWS_SECRET_ACCESS_KEY)%'
Define a Queue Create a Producer service to publish messages:
# config/services.yaml
services:
App\Service\MyQueueProducer:
tags: ['aws_queue.producer']
arguments:
$queueName: 'my_queue'
$region: 'us-east-1'
First Use Case: Publish a Message Inject the producer into a controller or command:
use Beyerz\AwsQueueBundle\Producer\ProducerInterface;
class MyController extends AbstractController
{
public function __construct(private ProducerInterface $producer) {}
public function publish()
{
$this->producer->send('Hello, AWS SQS!');
}
}
Producer-Consumer Pairing
services:
App\Service\MyQueueConsumer:
tags: ['aws_queue.consumer']
arguments:
$queueName: 'my_queue'
$region: 'us-east-1'
$handler: '@App\Service\MessageHandler'
Message Handling
handle() method):
class MessageHandler
{
public function handle(string $message): void
{
// Process $message (e.g., save to DB, trigger events)
}
}
Error Handling
onError() in consumers to log or retry failed messages:
class MyQueueConsumer
{
public function onError(string $message, \Exception $e): void
{
// Log or notify (e.g., via Monolog)
throw new \RuntimeException('Failed to process: ' . $e->getMessage());
}
}
Batch Processing
arguments:
$batchSize: 10 # Fetch 10 messages per poll
Symfony Events Trigger events when messages are published/consumed:
// In Producer:
$this->producer->send($message, ['event' => 'message.published']);
Dependency Injection
public function __construct(private ProducerInterface $producer) {}
Environment-Specific Queues
Use %env(QUEUE_NAME)% in services.yaml for dynamic queue names.
Testing
ProducerInterface and ConsumerInterface in PHPUnit:
$this->mockProducer->expects($this->once())->method('send')->with('test');
Dead-Letter Queues (DLQ)
Configure DLQs in AWS and route failed messages via consumer’s onError().
AWS Credentials
beyerz/aws-sdk-bundle is properly configured. Missing credentials will throw Aws\Sqs\Exception\SqsException..env or config/packages/beyerz_aws.yaml.Queue Permissions
AmazonSQSFullAccess (temporarily for testing) or custom policies.Consumer Visibility Timeout
Message Size Limits
json_encode() for small data or store large data in S3 and reference the URL.Consumer Overlapping
Enable AWS SDK Debugging
Add to config/packages/beyerz_aws.yaml:
beyerz_aws:
debug: true
Logs will appear in var/log/dev.log.
Check Queue ARN
$queueName in services matches the SQS queue ARN (e.g., my_queue.fifo for FIFO).aws sqs list-queues to verify queue names.Consumer Stuck on Polling
sleep() in a loop:
while (true) {
$this->consume();
sleep(5); // Poll every 5 seconds
}
Custom Message Attributes Extend producers to add metadata:
$this->producer->send('message', [
'attribute1' => 'value1',
'attribute2' => 'value2',
]);
Dynamic Queue Names
Override getQueueName() in custom producers/consumers:
class DynamicProducer implements ProducerInterface
{
public function getQueueName(): string
{
return 'queue_' . uniqid();
}
}
Retry Logic
Implement exponential backoff in onError():
private $retries = 0;
private $maxRetries = 3;
public function onError(string $message, \Exception $e): void
{
if ($this->retries++ < $this->maxRetries) {
sleep(2 ** $this->retries); // Exponential backoff
$this->consume(); // Re-consume
}
}
Cross-Account Access For cross-account SQS access, configure the queue policy to allow the external account’s IAM role.
us-east-1 if not specified in the service.arguments:
$messageGroupId: 'group1'
How can I help you explore Laravel packages today?