Skip to content

marko/queue-sync

Synchronous queue driver --- executes jobs immediately during the current request, ideal for development and testing. The sync driver runs jobs inline when they are pushed, with no external dependencies or background processes. Delayed jobs execute immediately. Failed jobs throw JobFailedException so errors surface instantly during development. Use marko/queue-database or marko/queue-rabbitmq for production workloads.

Implements QueueInterface from marko/queue.

Terminal window
composer require marko/queue-sync

Bind SyncQueue as the QueueInterface implementation in your module:

module.php
use Marko\Queue\QueueInterface;
use Marko\Queue\Sync\SyncQueue;
return [
'bindings' => [
QueueInterface::class => SyncQueue::class,
],
];

Then dispatch jobs normally --- they execute synchronously:

use Marko\Queue\QueueInterface;
public function __construct(
private readonly QueueInterface $queue,
) {}
public function process(): void
{
// Executes immediately, throws on failure
$this->queue->push(new SendWelcomeEmail('[email protected]'));
}

SyncQueue is constructed with the container and the JobEnvelope, and the container autowires both. Before a job that implements ContainerAwareJobInterface runs, SyncQueue calls setContainer() and setJobEnvelope() on it, just as the worker does, and calls releaseContainer() once handle() returns or throws. This is how #[Observer(async: true)] observers run under the sync driver. The observer is queued as an AsyncObserverJob, and push() runs it straight away against a copy of the event unwrapped from the signed envelope. If the observer throws, dispatch() throws a JobFailedException.

The sync driver includes NullFailedJobRepository since jobs either succeed or throw immediately:

module.php
use Marko\Queue\FailedJobRepositoryInterface;
use Marko\Queue\Sync\NullFailedJobRepository;
return [
'bindings' => [
FailedJobRepositoryInterface::class => NullFailedJobRepository::class,
],
];

Implements all methods from QueueInterface. See marko/queue for the full contract.

MethodDescription
__construct(ContainerInterface $container, JobEnvelope $jobEnvelope)Autowired. Both are passed to container-aware jobs before they run.
push(JobInterface $job, ?string $queue = null): stringExecute the job immediately and return its ID. Container-aware jobs get the container and job envelope first, and release them afterwards. Throws JobFailedException on failure.
later(int $delay, JobInterface $job, ?string $queue = null): stringIgnores the delay and executes immediately via push().
pop(?string $queue = null): ?JobInterfaceAlways returns null --- no jobs are ever queued.
size(?string $queue = null): intAlways returns 0.
clear(?string $queue = null): intAlways returns 0.
delete(string $jobId): boolAlways returns true.
release(string $jobId, int $delay = 0): boolAlways returns true.

module.php binds QueueInterface straight to SyncQueue; there is no factory.

A no-op implementation of FailedJobRepositoryInterface --- since the sync driver throws on failure, there are no failed jobs to store.

MethodDescription
store(FailedJob $failedJob): voidNo-op.
all(): arrayAlways returns [].
find(string $id): ?FailedJobAlways returns null.
delete(string $id): boolAlways returns false.
clear(): intAlways returns 0.
count(): intAlways returns 0.