Installation
composer require arko/queue-manager
Register the service in your Laravel container (if using DI):
$this->app->singleton(Arko\QueueManager\QueueManagerInterface::class, function ($app) {
return new Arko\QueueManager\QueueManager();
});
First Use Case: Delayed Task Execution
// In a controller, command, or service
$queueManager = app(Arko\QueueManager\QueueManagerInterface::class);
$queueManager->add(function () {
// Your logic here (e.g., send email, process data)
Log::info('Task executed!');
}, 'email-queue');
// Later, trigger processing (e.g., via CLI or HTTP endpoint)
$queueManager->process('email-queue');
Where to Look First
QueueManager class: Core logic for adding/processing queues.QueueManagerInterface: Contract for dependency injection.process() method: Key entry point for execution.Named Queues for Isolation
Use distinct queue names (e.g., notifications, reports) to logically separate tasks. Example:
$queueManager->add(fn() => $this->sendWelcomeEmail(), 'notifications');
$queueManager->add(fn() => $this->generateReport(), 'reports');
Dependency Injection
Bind the manager to your container (Laravel’s AppServiceProvider):
public function register()
{
$this->app->bind(QueueManagerInterface::class, function () {
return new QueueManager();
});
}
Inject via constructor:
public function __construct(private QueueManagerInterface $queueManager) {}
Contextual Processing Process queues in response to events or triggers:
// In a controller after user signup
$this->queueManager->add(fn() => $this->notifyAdmin(), 'admin-alerts');
$this->queueManager->process('admin-alerts'); // Process immediately or defer
Closure-Based Tasks Leverage closures for scoped variables:
$userId = 123;
$queueManager->add(function () use ($userId) {
$user = User::find($userId);
// Task logic using $user
}, 'user-tasks');
CLI Processing Create an Artisan command to process queues:
php artisan queue:process notifications
(Extend QueueManager to support CLI flags.)
Webhook Triggers Expose an endpoint to process queues via HTTP:
Route::post('/process-queue/{name}', function (string $name) {
app(QueueManagerInterface::class)->process($name);
return response()->json(['status' => 'processed']);
});
Batch Processing Process multiple queues sequentially:
$queues = ['emails', 'backups', 'logs'];
foreach ($queues as $queue) {
$this->queueManager->process($queue);
}
process() in a job:
Queue::push(new ProcessQueueJob('queue-name'));
QueueManager to log queue operations:
$queueManager = new LoggingQueueManager(new QueueManager());
QueueManagerInterface in unit tests:
$mock = Mockery::mock(QueueManagerInterface::class);
$mock->shouldReceive('process')->once();
Stateful Closures Avoid capturing mutable state (e.g., class properties) in closures unless intentional:
// ❌ Risky: $this may change between adds/processes
$queueManager->add(function () { $this->doSomething(); }, 'queue');
// ✅ Safer: Pass dependencies explicitly
$queueManager->add(fn() => $service->doSomething(), 'queue');
Queue Clearing Queues are cleared before processing, which may cause issues if:
No Retry Mechanism Failed tasks are not retried by default. Implement retry logic manually:
$attempts = 0;
$queueManager->add(function () use (&$attempts) {
try {
$this->riskyOperation();
} catch (Exception $e) {
if ($attempts++ < 3) {
throw $e; // Requeue
}
Log::error("Failed after retries", ['error' => $e]);
}
}, 'retryable-queue');
Thread Safety
The package is not thread-safe. Avoid concurrent access to the same QueueManager instance.
Queue Inspection Add a debug method to inspect pending tasks:
public function debug(string $queueName): array
{
return $this->queues[$queueName] ?? [];
}
Error Handling
Wrap process() calls to catch exceptions:
try {
$queueManager->process('critical-queue');
} catch (Exception $e) {
report($e);
// Fallback logic
}
Memory Leaks Large queues may consume memory. For long-running tasks:
Singleton vs. Non-Singleton The package assumes singleton usage. If you need multiple instances:
$instance1 = new QueueManager();
$instance2 = new QueueManager(); // Separate queues
Queue Naming
Use descriptive names (e.g., user-123-exports) to avoid collisions.
Custom Storage
Extend QueueManager to use a database or Redis:
class DatabaseQueueManager implements QueueManagerInterface {
public function add(callable $callable, string $queueName) {
DB::table('queues')->insert([...]);
}
public function process(string $queueName) {
// Fetch from DB, execute, delete
}
}
Priority Queues
Add a priority parameter to add() and sort queues accordingly:
$queueManager->add($callable, 'high-priority', 1); // Lower number = higher priority
Event Dispatching Trigger events before/after processing:
$queueManager->process('queue', fn() => event(new QueueProcessed('queue')));
How can I help you explore Laravel packages today?