Installation
composer require badpixxel/tasking-bundle
Add the bundle to config/bundles.php in Symfony:
return [
// ...
BadPixxel\TaskingBundle\BadPixxelTaskingBundle::class => ['all' => true],
];
Basic Configuration Publish the default config:
php bin/console badpixxel:tasking:install
Review config/packages/badpixxel_tasking.yaml for queue/transport settings (e.g., doctrine, redis, or amqp).
First Task
Define a task class (e.g., src/Task/MyTask.php):
namespace App\Task;
use BadPixxel\TaskingBundle\Task\TaskInterface;
class MyTask implements TaskInterface
{
public function execute(): void
{
// Your logic here
}
}
Dispatch a Task
use BadPixxel\TaskingBundle\Task\TaskDispatcherInterface;
class MyController
{
public function __construct(private TaskDispatcherInterface $dispatcher) {}
public function runTask()
{
$this->dispatcher->dispatch(new MyTask());
}
}
Run the Worker
php bin/console badpixxel:tasking:worker
config/packages/badpixxel_tasking.yaml for queue/transport settings.src/Task/TaskInterface.php to understand required methods (execute(), getName()).php bin/console list badpixxel:tasking
Dispatch a task to process a large CSV file without blocking the HTTP request:
$this->dispatcher->dispatch(new ProcessCsvTask($filePath));
The worker handles execution asynchronously.
Task Dispatching
TaskDispatcherInterface (e.g., in controllers/services).dispatchMultiple() for batch processing:
$this->dispatcher->dispatchMultiple([
new TaskA(),
new TaskB(),
]);
$this->dispatcher->dispatch(new MyTask(), new \DateTime('+1 hour'));
Task Dependencies Link tasks sequentially or in parallel:
# config/packages/badpixxel_tasking.yaml
badpixxel_tasking:
tasks:
task_a:
depends_on: [task_b, task_c]
Result Handling
TaskResultRepository:
$result = $this->resultRepository->getResult($taskId);
Worker Management
high_priority_worker).Symfony Events
Trigger tasks from Symfony events (e.g., kernel.terminate):
use Symfony\Component\HttpKernel\Event\TerminateEvent;
$event->getRequest()->getSession()->getFlashbag()->add(...);
$this->dispatcher->dispatch(new CleanupSessionTask());
Doctrine Integration Use Doctrine tasks for database-heavy operations:
badpixxel_tasking:
transports:
doctrine:
enabled: true
connection: default
Retry Mechanisms
Configure retries in config/packages/badpixxel_tasking.yaml:
badpixxel_tasking:
retries:
max_attempts: 3
delay: 60
Monitoring
TaskLoggerInterface.Task Chaining Chain tasks dynamically in a service:
$taskA = new TaskA();
$taskB = new TaskB();
$taskA->setNext($taskB); // Custom chaining logic
$this->dispatcher->dispatch($taskA);
Task Prioritization
Use custom priority queues (e.g., high, medium, low) via transport configuration.
Task Serialization
Implement TaskInterface::serialize() and unserialize() for complex payloads.
Testing
Mock TaskDispatcherInterface in unit tests:
$dispatcher = $this->createMock(TaskDispatcherInterface::class);
$dispatcher->expects($this->once())->method('dispatch');
Worker Stuck in Loop
TaskInterface::execute() crash the worker.try-catch and log errors:
public function execute(): void
{
try {
// Task logic
} catch (\Throwable $e) {
$this->logger->error($e->getMessage(), ['task' => $this->getName()]);
throw $e; // Re-throw to trigger retry
}
}
Task Timeout
task_timeout (default: 60 seconds).Queue Blocking
dispatchMultiple() for bursts.Serialization Issues
TaskInterface::serialize()/unserialize() or avoid non-serializable data.Worker Logs
Enable verbose logging in config/packages/badpixxel_tasking.yaml:
badpixxel_tasking:
logging:
level: debug
Check logs at var/log/dev.log.
Task Inspection List pending tasks:
php bin/console badpixxel:tasking:list
View task details:
php bin/console badpixxel:tasking:show <task_id>
Transport-Specific Issues
php bin/console doctrine:database:status).rabbitmqctl list_queues.Default Transport
The bundle defaults to doctrine if no transport is configured. Explicitly set your preferred transport:
badpixxel_tasking:
transport: redis
Task Naming
Tasks without a getName() method use their class name. Override for clarity:
public function getName(): string
{
return 'custom.task.name';
}
Worker Auto-Start Workers do not start automatically. Always run them manually or via a process manager (e.g., Supervisor).
Custom Transports
Implement BadPixxel\TaskingBundle\Transport\TransportInterface for new transports (e.g., Kafka, SQS).
Task Middleware
Add middleware to tasks via TaskMiddlewareInterface (e.g., logging, auth):
badpixxel_tasking:
middleware:
- App\Middleware\LogTaskMiddleware
Event Listeners
Subscribe to task events (e.g., TaskStartedEvent, TaskFailedEvent):
use BadPixxel\TaskingBundle\Event\TaskEvent;
class MyListener
{
public function onTaskFailed(TaskEvent $event)
{
// Handle failure
}
}
Register in services.yaml:
services:
App\Listener\MyListener:
tags:
- { name: 'kernel.event_listener', event: 'task.failed', method: 'onTaskFailed' }
Custom Task Factories Override the default factory to
How can I help you explore Laravel packages today?