amranidev/micro-bus
Laravel/Lumen package for building event-driven microservices on AWS using SNS/SQS. Provides publisher/subscriber setup, config publishing, and env-based credentials to implement Pub-Sub messaging between services.
Installation
composer require amranidev/micro-bus
Publish the config (if needed):
php artisan vendor:publish --provider="Amranidev\MicroBus\MicroBusServiceProvider"
Configure AWS
Ensure your config/micro-bus.php is set up with your AWS SQS/SNS credentials and region. Example:
'aws' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
Define a Command Create a command that publishes an event:
php artisan make:command ProcessOrder
Example:
use Amranidev\MicroBus\Commands\BusCommand;
use Amranidev\MicroBus\Events\Event;
class ProcessOrder extends BusCommand
{
public function handle()
{
$event = new Event('order.processed', ['order_id' => 123]);
$this->publish($event);
}
}
Run the Command
php artisan process:order
Use MicroBus to decouple services by publishing events (e.g., order.created) and subscribing to them in other microservices.
Example:
// In a Lumen/Laravel microservice:
$bus = app('micro-bus');
$bus->subscribe('order.created', function ($event) {
// Handle order creation (e.g., send notification)
});
Synchronous vs. Asynchronous:
Use publish() for fire-and-forget or publishSync() for immediate local processing.
$this->publish(new Event('user.registered', ['user_id' => 1]));
Batch Processing: Publish multiple events in a loop (e.g., for bulk operations):
foreach ($orders as $order) {
$this->publish(new Event('order.inventory.check', ['order_id' => $order->id]));
}
Dynamic Subscriptions: Register subscribers dynamically in a service provider:
public function register()
{
$bus = app('micro-bus');
$bus->subscribe('payment.processed', [PaymentHandler::class, 'handle']);
}
Priority Handling: Use middleware to prioritize critical events:
$bus->pipe(function ($event, $next) {
if ($event->name === 'emergency.alert') {
return $this->handleEmergency($event);
}
return $next($event);
});
SQS Queues:
Configure per-event queues in config/micro-bus.php:
'queues' => [
'order.*' => 'order-queue-url',
'default' => env('AWS_SQS_DEFAULT_QUEUE'),
],
SNS Topics: Publish to SNS topics for fan-out:
$event->setTopic('order-updates-topic');
$this->publish($event);
Mock AWS:
Use Mockery or AWS SDK’s mock clients in tests:
$mock = Mockery::mock('overload:Aws\Sqs\SqsClient');
$mock->shouldReceive('sendMessage')->once();
Event Listeners:
Test subscriptions with BusCommand:
$this->app->instance('micro-bus', $mockBus);
$command = new ProcessOrder();
$command->handle();
AWS Credentials:
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set in .env. Hardcoding is not recommended.env() or AWS IAM roles (for EC2).Event Serialization:
json_encode():
$event = new Event('user.updated', ['user' => $user->toArray()]);
Dead Letter Queues (DLQ):
config/micro-bus.php:
'dead_letter_queue' => env('AWS_SQS_DLQ_URL'),
Race Conditions:
event_id or database transactions for idempotency:
$event->setId(uniqid());
'debug' => true in config/micro-bus.php to log AWS API calls.VisibilityTimeout (default: 30s). Increase it for long-running handlers:
$bus->setVisibilityTimeout(60); // 60 seconds
Custom Transport:
Extend Amranidev\MicroBus\Contracts\Transport to support other brokers (e.g., RabbitMQ):
class RabbitMqTransport implements Transport
{
public function publish($event) { /* ... */ }
}
Middleware: Add cross-cutting concerns (e.g., logging, rate limiting):
$bus->pipe(function ($event, $next) {
Log::info("Event published: {$event->name}");
return $next($event);
});
Retry Logic: Implement exponential backoff for failed events:
$bus->setRetryPolicy(new RetryPolicy(3, 1000)); // 3 retries, 1s delay
Batch Publishing: AWS SQS has a 10-message batch limit. For bulk operations, chunk your events:
$events = array_chunk($events, 10);
foreach ($events as $batch) {
$this->publishBatch($batch);
}
Memory Usage:
Large payloads may bloat memory. Stream events or use event:dispatch for local processing.
How can I help you explore Laravel packages today?