Back to Documentation
Guide
📚Queue & Mail Guide
The queue system processes background jobs asynchronously using a database-driven queue.
Queue System#
The queue system processes background jobs asynchronously using a database-driven queue.
Configuration#
env
QUEUE_DRIVER=database
QUEUE_DEFAULT_MAX_ATTEMPTS=3
Requires a jobs table (created by the default migration).
Pushing Jobs#
php
use Siro\Core\Queue;
// Push a job to the default queue
Queue::push(SendWelcomeEmail::class, [
'email' => 'user@example.com',
'name' => 'John',
]);
// With delay (seconds)
Queue::push(SendWelcomeEmail::class, ['email' => 'user@example.com'], 3600);
// With priority (higher = processed first)
Queue::push(UrgentJob::class, $data, 0, 10);
// With custom max attempts
Queue::push(FailableJob::class, $data, 0, 0, 5);
Writing Jobs#
php
namespace App\Jobs;
final class SendWelcomeEmail
{
public function handle(array $data = []): void
{
$email = $data['email'] ?? '';
$name = $data['name'] ?? 'User';
if ($email === '') {
return;
}
Mail::to($email)
->subject('Welcome to our platform!')
->html('<h1>Welcome, ' . htmlspecialchars($name) . '!</h1>')
->send();
}
}
Processing Jobs#
bash
php siro queue:work # Process one job
php siro queue:work --daemon # Run continuously
php siro queue:status # Show queue status
php siro queue:retry <id> # Retry failed job
php
// In code
Queue::work(); // Process next available job
$count = Queue::workAll(); // Process all available jobs (returns count)
Queue Status#
php
$pending = Queue::pendingCount(); // Number of pending jobs
$failed = Queue::failedCount(); // Number of failed jobs
Failed Jobs#
When a job exceeds max attempts, it moves to the failed_jobs table:
bash
php siro queue:retry <id> # Retry specific failed job
Mail System#
Configuration#
env
MAIL_DRIVER=sendmail # or: smtp
MAIL_FROM_ADDRESS=noreply@localhost
MAIL_FROM_NAME="Siro API"
# SMTP settings (when MAIL_DRIVER=smtp)
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=user
MAIL_PASSWORD=pass
Config file: config/mail.php loads from .env.
Sending Mail#
php
use Siro\Core\Mail;
// Basic email
Mail::to('user@example.com')
->subject('Welcome!')
->html('<h1>Hello</h1><p>Welcome to our platform.</p>')
->send();
Mail Templates#
Create reusable mail classes:
php
namespace App\Mails;
final class WelcomeMail
{
public function build(array $data = []): string
{
$name = $data['name'] ?? 'User';
$safeName = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
return '<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="font-family: sans-serif;">
<h1>Welcome, ' . $safeName . '!</h1>
<p>Thank you for joining us.</p>
</body>
</html>';
}
}
// Usage
Mail::to('user@example.com')
->subject('Welcome!')
->html((new WelcomeMail())->build(['name' => 'John']))
->send();
Queueing Mail#
Send emails asynchronously via the queue:
php
// Queue the email (processed by queue worker)
Mail::to('queued@test.com')
->subject('Queued Email')
->html('<p>This email was queued.</p>')
->queue(); // Pushes SendMailJob to the queue
// Process queued mails
php siro queue:work
The SendMailJob reconstructs the mail from serialized data including to, subject, body, content_type, cc, bcc, reply_to, and attachments.
SMTP Configuration#
For production, use SMTP with TLS:
env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=SG.xxxxx
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="Your App"
Best Practices#
- Always queue emails in production to avoid blocking HTTP responses.
- Run
php siro queue:work --daemonas a supervised background process. - Monitor failed jobs and set up alerts for repeated failures.
- Use descriptive job class names that reflect the action (e.g.
SendWelcomeEmail). - Keep job handlers idempotent — they may be retried.
- Set realistic timeouts for jobs that make external HTTP calls.