Installation Add the bundle via Composer:
composer require aligent/async-bundle
Ensure it’s enabled in config/bundles.php:
Aligent\AsyncBundle\AligentAsyncBundle::class => ['all' => true],
First Use Case: Dispatching an Async Job Extend Oro’s async processing for custom logic (e.g., webhooks, delayed tasks):
use Aligent\AsyncBundle\Job\AsyncJob;
use Oro\AsyncBundle\Entity\Job;
// Dispatch a job via Oro's async system
$job = new AsyncJob('my_custom_job', ['param' => 'value']);
$job->setEntityClass(Job::class);
$job->setEntityData(['status' => 'pending']);
$this->get('oro_async.job_executor')->execute($job);
Key Classes to Explore
AsyncJob: Base class for custom async jobs.JobExecutor: Service for executing jobs.WebhookEvent: For custom Oro webhook events (v5.0+).ChannelManager: For managing async channels (e.g., queues).Extend AsyncJob to create reusable async tasks:
namespace App\Async;
use Aligent\AsyncBundle\Job\AsyncJob;
class ProcessOrderJob extends AsyncJob
{
protected $orderId;
public function __construct($orderId)
{
$this->orderId = $orderId;
parent::__construct('app.process_order', ['order_id' => $orderId]);
}
public function run()
{
// Custom logic here
$order = $this->entityManager->find(Order::class, $this->orderId);
// ...
}
}
Dispatch via:
$job = new ProcessOrderJob(123);
$this->get('oro_async.job_executor')->execute($job);
Create custom webhook events:
use Aligent\AsyncBundle\Event\WebhookEvent;
class CustomWebhookEvent extends WebhookEvent
{
protected $eventName = 'custom.webhook';
public function __construct($payload)
{
parent::__construct($payload, 'custom_webhook_channel');
}
}
Trigger via:
$event = new CustomWebhookEvent(['data' => 'payload']);
$this->get('oro_async.webhook.dispatcher')->dispatch($event);
Dynamically manage async channels (queues):
// Create a channel
$channel = $this->get('oro_async.channel_manager')->createChannel('custom_channel');
// Delete a channel (fixes cache issue from v5.0.3)
$this->get('oro_async.channel_manager')->deleteChannel('custom_channel');
Query failed jobs (note: uses TEXT field for exceptions since v4.1.1):
$failedJobs = $this->get('oro_async.job_repository')->findBy(['status' => 'failed']);
foreach ($failedJobs as $job) {
$exception = $job->getException(); // TEXT field, may need JSON decode
}
Hook into Oro’s async lifecycle:
// config/services.yaml
services:
App\Async\Listener\JobListener:
tags:
- { name: kernel.event_listener, event: oro_async.job.execute, method: onJobExecute }
class JobListener
{
public function onJobExecute(JobExecuteEvent $event)
{
$job = $event->getJob();
// Pre/post-processing logic
}
}
deleteChannel() after removal:
$this->get('oro_async.channel_manager')->deleteChannel('old_channel');
oro_async_channel table for orphaned entries.TEXT field (not LONGTEXT).$exceptionData = json_decode($job->getException(), true);
oro_async.webhook.dispatcher).Job entity references to match Oro 5.0’s schema.WebhookEvent for reusable payloads:
class OrderWebhookEvent extends WebhookEvent
{
public function getOrderId(): int
{
return $this->getPayload()['order_id'];
}
}
config/packages/oro_async.yaml.JobExecutor with bulk flags:
$this->get('oro_async.job_executor')->execute($job, ['batch_size' => 50]);
config/packages/monolog.yaml:
handlers:
async:
type: stream
path: "%kernel.logs_dir%/async.log"
level: debug
oro_async_job table directly for stuck jobs:
SELECT * FROM oro_async_job WHERE status = 'pending' AND created_at < NOW() - INTERVAL '1 hour';
JobHandlerInterface for unique logic:
class CustomHandler implements JobHandlerInterface
{
public function handle(Job $job)
{
// Custom processing
}
}
# config/services.yaml
services:
App\Async\Handler\CustomHandler:
tags:
- { name: oro_async.job_handler, jobName: 'custom_job' }
How can I help you explore Laravel packages today?