Job و Queue در لاراول؛ راهنمای کامل صفها
Job و Queue در لاراول یکی از مهمترین ابزارها برای اجرای پردازشهای زمانبر در پسزمینه، افزایش سرعت پاسخگویی برنامه، بهبود تجربه کاربری و طراحی معماری مقیاسپذیر هستند. با استفاده از Queue میتوان کارهایی مثل ارسال ایمیل، ارسال پیامک، پردازش تصویر، تولید گزارش، اتصال به API خارجی، همگامسازی داده، ارسال اعلان و اجرای پردازشهای سنگین را از چرخه مستقیم Request خارج کرد. در این مقاله، بهصورت کامل و فنی با مفهوم Job، Queue، Worker، Driver، Retry، Failed Job، Delay، Timeout، Supervisor، Laravel Horizon و بهترین روشهای استفاده از صفها در پروژههای حرفهای Laravel آشنا میشویم.
برای شنیدن متن، روی «پخش صوت مقاله» بزنید.
مقدمه
در یک نرمافزار تحت وب حرفهای، همه کارها نباید همزمان با درخواست کاربر انجام شوند. وقتی کاربر روی دکمه ثبت سفارش، ثبتنام، آپلود تصویر، ارسال پیام یا تولید گزارش کلیک میکند، انتظار دارد سیستم سریع پاسخ بدهد. اما پشت صحنه ممکن است کارهای زمانبری وجود داشته باشد؛ مثل ارسال ایمیل، ارسال پیامک، کاهش موجودی، تولید فایل PDF، پردازش تصویر، اتصال به درگاه پرداخت، ارتباط با API خارجی یا همگامسازی داده با یک سرویس دیگر.
اگر همه این کارها داخل همان Request اصلی انجام شوند، کاربر باید چند ثانیه یا حتی چند دقیقه منتظر بماند. این موضوع باعث کاهش سرعت سایت، فشار روی سرور، تجربه کاربری ضعیف و افزایش احتمال Timeout میشود. راهحل حرفهای در Laravel استفاده از Job و Queue است.
در لاراول، Job نماینده یک کار مشخص است که باید اجرا شود؛ مثل ارسال ایمیل خوشامدگویی یا پردازش تصویر. Queue یا صف، محلی است که این Jobها در آن قرار میگیرند تا بعداً توسط Worker اجرا شوند. بهجای اینکه کار زمانبر در همان لحظه انجام شود، برنامه Job را در صف قرار میدهد، سریع به کاربر پاسخ میدهد و Workerها در پسزمینه Jobها را اجرا میکنند.
طبق مستندات رسمی Laravel، Queueهای لاراول یک API یکپارچه برای Queue Backendهای مختلف مثل Amazon SQS، Redis، Beanstalkd و حتی Database ارائه میدهند و اجازه میدهند پردازش کارهای زمانبر، مانند ارسال ایمیل، به زمان بعد موکول شود تا سرعت پاسخگویی برنامه افزایش پیدا کند. مطالعه مستندات رسمی Laravel درباره Queues
برای شرکتهای تولید نرمافزار، استفاده درست از Job و Queue فقط یک تکنیک بهینهسازی نیست؛ بلکه بخشی از معماری مقیاسپذیر، پایدار و قابل اعتماد است. در این مقاله، بهصورت کامل و فنی بررسی میکنیم Job و Queue در Laravel چیستند، چگونه ساخته و اجرا میشوند، چه Driverهایی دارند، چطور باید Workerها را در محیط Production مدیریت کرد، Failed Job چیست، Retry چگونه کار میکند، Laravel Horizon چه نقشی دارد و چه Best Practiceهایی برای پروژههای شرکتی باید رعایت شود. 🚀
Job و Queue در لاراول چیست؟
برای درک بهتر موضوع، ابتدا باید تفاوت Job و Queue را بدانیم.
Job یک کلاس PHP است که یک کار مشخص را انجام میدهد. برای مثال:
- ارسال ایمیل خوشامدگویی
- ارسال پیامک تایید سفارش
- پردازش تصویر پروفایل
- تولید گزارش مالی
- همگامسازی داده با CRM
- ارسال اعلان به کاربر
- پاکسازی فایلهای موقت
- ساخت فایل خروجی Excel
Queue صفی است که Jobها در آن قرار میگیرند. Workerها این صف را بررسی میکنند و Jobها را یکییکی یا همزمان اجرا میکنند.
جریان ساده:
User Request → Controller/Service → Dispatch Job → Queue → Worker → Execute Job
مثال واقعی:
ثبت سفارش → ایجاد سفارش → قرار دادن Job ارسال پیامک در صف → پاسخ سریع به کاربر → اجرای پیامک در پسزمینه
در این معماری، کاربر منتظر ارسال پیامک یا ایمیل نمیماند. سیستم سفارش را ثبت میکند، Job ارسال اعلان را در صف میگذارد و پاسخ موفقیت را سریع برمیگرداند.
چرا از Queue در Laravel استفاده کنیم؟
استفاده از Queue در پروژههای Laravel چند مزیت مهم دارد:
| مزیت | توضیح |
|---|---|
| افزایش سرعت پاسخگویی | کارهای زمانبر از Request اصلی جدا میشوند |
| بهبود تجربه کاربری | کاربر سریعتر نتیجه عملیات را میبیند |
| کاهش Timeout | پردازشهای طولانی باعث قطع شدن Request نمیشوند |
| مقیاسپذیری بهتر | میتوان تعداد Workerها را افزایش داد |
| مدیریت خطا | Jobهای شکستخورده قابل Retry و بررسی هستند |
| جداسازی مسئولیتها | منطق پردازش پسزمینه در Jobهای مستقل قرار میگیرد |
| مناسب سیستمهای پرترافیک | صفها فشار لحظهای روی سرور را کنترل میکنند |
| اجرای زمانبندیشده | Jobها میتوانند با Delay اجرا شوند |
فرض کنید ۵۰۰ کاربر همزمان ثبتنام کنند و بعد از ثبتنام برای هرکدام ایمیل خوشامدگویی ارسال شود. اگر ارسال ایمیل داخل Request انجام شود، سرور تحت فشار قرار میگیرد و کاربران منتظر میمانند. اما اگر ارسال ایمیل به Queue منتقل شود، ثبتنام سریع انجام میشود و Workerها ایمیلها را در پسزمینه ارسال میکنند.
تفاوت Job، Queue، Worker و Driver
برای کار حرفهای با صفها باید چند مفهوم کلیدی را بشناسیم.
| مفهوم | تعریف | مثال |
|---|---|---|
| Job | کلاس انجامدهنده یک کار مشخص | SendWelcomeEmail |
| Queue | صف نگهداری Jobها | emails, reports, default |
| Worker | فرایندی که Jobها را از صف برداشته و اجرا میکند | php artisan queue:work |
| Driver / Connection | Backend ذخیره و مدیریت صف | database, redis, sqs |
| Dispatch | ارسال Job به صف | SendEmailJob::dispatch() |
| Failed Job | Jobی که بعد از چند تلاش شکست خورده است | خطای API پیامک |
| Retry | تلاش دوباره برای اجرای Job | ۳ بار تلاش مجدد |
| Delay | اجرای Job بعد از زمان مشخص | ارسال ایمیل ۱۰ دقیقه بعد |
در فایل config/queue.php، مفهوم Connection و Queue از هم جدا هستند. Connection مشخص میکند Jobها در چه Backendی ذخیره شوند، مثل Redis یا Database، اما Queue نام صفی است که Job در آن قرار میگیرد؛ مثل emails یا reports. مستندات رسمی Laravel نیز روی تفاوت Connections و Queues تأکید میکند و توضیح میدهد Connectionها به Backendهای صف مثل Redis، Amazon SQS یا Database اشاره دارند.
Queue Driverهای رایج در Laravel
Laravel از Driverهای مختلفی برای Queue پشتیبانی میکند. انتخاب Driver به نیاز پروژه، حجم پردازش، زیرساخت و محیط Production بستگی دارد.
| Driver | کاربرد | مزایا | محدودیت |
|---|---|---|---|
| sync | اجرای فوری Job | مناسب توسعه محلی ساده | صف واقعی نیست |
| database | ذخیره Jobها در دیتابیس | راهاندازی آسان | برای حجم خیلی بالا ایدهآل نیست |
| redis | صف سریع و مناسب Production | سرعت بالا، مناسب Horizon | نیاز به Redis |
| sqs | Amazon SQS | مناسب معماری Cloud | وابسته به AWS |
| beanstalkd | Queue Backend مستقل | سبک و سریع | کمتر رایج در پروژههای جدید |
| null | دور ریختن Jobها | تستهای خاص | Job اجرا نمیشود |
برای شروع، Driver دیتابیس ساده و مناسب است. اما برای پروژههای پرترافیک و Production جدی، معمولاً Redis انتخاب بهتری است؛ مخصوصاً اگر بخواهید از Laravel Horizon استفاده کنید.
تنظیم Queue در Laravel
تنظیمات Queue در فایل زیر قرار دارد:
config/queue.php
همچنین مقدار Driver پیشفرض از فایل .env خوانده میشود:
QUEUE_CONNECTION=database
یا برای Redis:
QUEUE_CONNECTION=redis
اگر از Driver دیتابیس استفاده میکنید، باید جدولهای مربوط به Queue را بسازید.
در نسخههای جدید Laravel میتوانید از دستور زیر استفاده کنید:
php artisan make:queue-table
سپس Migration را اجرا کنید:
php artisan migrate
برای Failed Jobs نیز معمولاً جدول جداگانه نیاز است:
php artisan make:queue-failed-table
php artisan migrate
نکته: در برخی نسخهها یا ساختارهای پروژه، فایل Migration مربوط به Failed Jobs ممکن است از قبل وجود داشته باشد. بهتر است وضعیت Migrationهای پروژه خود را بررسی کنید.
ساخت Job در Laravel
برای ساخت Job از Artisan استفاده میشود:
php artisan make:job SendWelcomeEmail
این دستور یک کلاس در مسیر زیر ایجاد میکند:
app/Jobs/SendWelcomeEmail.php
نمونه ساده Job:
<?php
namespace App\Jobs;
use App\Mail\WelcomeMail;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail implements ShouldQueue
{
use Queueable;
public function __construct(
public User $user
) {}
public function handle(): void
{
Mail::to($this->user->email)->send(
new WelcomeMail($this->user)
);
}
}
نکته مهم این است که Job باید Interface زیر را پیادهسازی کند:
Illuminate\Contracts\Queue\ShouldQueue
اگر Job این Interface را پیادهسازی نکند، بهجای رفتن به Queue، ممکن است بهصورت مستقیم اجرا شود.
Dispatch کردن Job
برای ارسال Job به صف از متد dispatch استفاده میشود:
SendWelcomeEmail::dispatch($user);
مثال در Controller:
public function register(RegisterRequest $request)
{
$user = User::create($request->validated());
SendWelcomeEmail::dispatch($user);
return response()->json([
'message' => 'ثبتنام با موفقیت انجام شد.',
], 201);
}
در اینجا کاربر سریع پاسخ ثبتنام را دریافت میکند و ارسال ایمیل در پسزمینه انجام میشود.
اجرای Queue Worker
تا زمانی که Worker اجرا نشود، Jobهای داخل صف پردازش نمیشوند. برای اجرای Worker از دستور زیر استفاده میشود:
php artisan queue:work
این دستور صف را بررسی میکند و Jobها را اجرا میکند.
برای مشخص کردن Queue خاص:
php artisan queue:work --queue=emails
برای مشخص کردن تعداد تلاش:
php artisan queue:work --tries=3
برای مشخص کردن Timeout:
php artisan queue:work --timeout=60
در محیط Development میتوانید این دستور را دستی اجرا کنید؛ اما در محیط Production باید Worker همیشه فعال بماند. برای این کار معمولاً از Supervisor یا Laravel Horizon استفاده میشود.
تفاوت queue:work و queue:listen
در Laravel معمولاً استفاده از queue:work توصیه میشود. دستور queue:work یک Worker پایدار اجرا میکند و برای Production مناسبتر است. queue:listen در هر بار اجرای Job فریمورک را دوباره Boot میکند و معمولاً کندتر است.
در محیط Production، Workerها فرایندهای طولانیمدت هستند. بنابراین بعد از تغییر کد و Deploy باید آنها را Restart کنید تا نسخه جدید کد را بارگذاری کنند:
php artisan queue:restart
این دستور باعث میشود Workerها بعد از پایان Job فعلی بهشکل امن Restart شوند.
Job و Queue در معماری Laravel
در پروژههای حرفهای، Jobها معمولاً مستقیماً همه منطق تجاری را انجام نمیدهند؛ بلکه از Serviceها استفاده میکنند.
جریان پیشنهادی:
Controller → Service → Dispatch Job → Job → Service/API/Mail
مثال:
class OrderController extends Controller
{
public function store(StoreOrderRequest $request)
{
$order = $this->orderService->create($request->validated());
SendOrderCreatedNotification::dispatch($order);
return redirect()->route('orders.show', $order);
}
}
Job:
class SendOrderCreatedNotification implements ShouldQueue
{
use Queueable;
public function __construct(
public Order $order
) {}
public function handle(NotificationService $notificationService): void
{
$notificationService->sendOrderCreated($this->order);
}
}
در این طراحی:
- Controller سبک است.
- منطق ثبت سفارش در Service است.
- Job فقط مسئول اجرای پسزمینه است.
- ارسال اعلان در NotificationService مدیریت میشود.
این ساختار برای پروژههای شرکتی بسیار مناسبتر از نوشتن همه منطق داخل Controller یا خود Job است.
صفهای جداگانه برای کارهای مختلف
در پروژههای واقعی، همه Jobها اهمیت و زمان اجرای یکسانی ندارند. مثلاً ارسال پیامک تایید سفارش فوریتر از تولید گزارش ماهانه است. بنابراین بهتر است از Queueهای جداگانه استفاده شود:
SendSmsJob::dispatch($order)->onQueue('notifications');
GenerateReportJob::dispatch($report)->onQueue('reports');
ProcessImageJob::dispatch($image)->onQueue('media');
اجرای Worker برای چند Queue:
php artisan queue:work --queue=notifications,reports,media
ترتیب Queueها مهم است. Worker ابتدا Queue اول را بررسی میکند و بعد به سراغ بعدی میرود. بنابراین میتوانید Queueهای مهمتر را جلوتر قرار دهید:
php artisan queue:work --queue=high,default,low
ساختار پیشنهادی برای پروژه شرکتی:
| Queue | کاربرد |
|---|---|
| high | عملیات فوری مثل پیامک تایید |
| default | کارهای عادی |
| emails | ارسال ایمیل |
| reports | تولید گزارش |
| media | پردازش تصویر و فایل |
| low | کارهای کماهمیت و زمانبر |
Delay در Jobها
گاهی نمیخواهید Job بلافاصله اجرا شود. برای مثال:
- ارسال ایمیل یادآوری ۳۰ دقیقه بعد
- بررسی پرداخت چند دقیقه بعد
- آزادسازی رزرو در صورت عدم پرداخت
- ارسال پیام پیگیری یک روز بعد
مثال:
SendReminderEmail::dispatch($user)
->delay(now()->addMinutes(30));
یا:
ReleaseUnpaidOrder::dispatch($order)
->delay(now()->addMinutes(15));
Delay برای فرآیندهای زمانبندیشده سبک بسیار کاربردی است. اما برای کارهای تکرارشونده و برنامهریزیشده، بهتر است از Task Scheduling لاراول استفاده شود.
Retry و تعداد تلاش مجدد
گاهی Job به دلایل موقت شکست میخورد؛ مثلاً سرویس پیامک در دسترس نیست یا API خارجی خطای موقت میدهد. در این شرایط، Retry بسیار مهم است.
میتوانید تعداد تلاش را در Job مشخص کنید:
class SendSmsJob implements ShouldQueue
{
use Queueable;
public int $tries = 3;
public function handle(): void
{
//
}
}
یا هنگام اجرای Worker:
php artisan queue:work --tries=3
همچنین میتوانید فاصله بین تلاشها را مشخص کنید:
public function backoff(): array
{
return [10, 60, 300];
}
یعنی تلاش دوم بعد از ۱۰ ثانیه، تلاش سوم بعد از ۶۰ ثانیه و تلاش بعدی بعد از ۳۰۰ ثانیه انجام شود.
Timeout در Jobها
Timeout مشخص میکند یک Job حداکثر چه مدت اجازه اجرا دارد. اگر Job بیشتر از این زمان طول بکشد، Worker آن را متوقف میکند.
در Job:
public int $timeout = 120;
یا در Worker:
php artisan queue:work --timeout=120
برای Jobهای زمانبر مثل تولید گزارش یا پردازش ویدئو، باید Timeout مناسب انتخاب شود. اگر Timeout خیلی کم باشد، Job بیدلیل شکست میخورد. اگر خیلی زیاد باشد، Worker ممکن است مدت زیادی درگیر یک Job مشکلدار بماند.
Failed Jobs در Laravel
اگر Job بعد از تعداد تلاش مشخص همچنان شکست بخورد، بهعنوان Failed Job ثبت میشود. این قابلیت برای بررسی خطاها، Retry دستی و مانیتورینگ بسیار مهم است.
نمایش Jobهای شکستخورده:
php artisan queue:failed
اجرای مجدد یک Failed Job:
php artisan queue:retry JOB_ID
اجرای مجدد همه Failed Jobها:
php artisan queue:retry all
حذف Failed Jobها:
php artisan queue:flush
در پروژههای Production، بررسی Failed Jobs باید بخشی از مانیتورینگ تیم فنی باشد. Jobهای شکستخورده میتوانند نشاندهنده خطای کدنویسی، مشکل سرویس خارجی، قطعی شبکه، داده نامعتبر یا کمبود منابع سرور باشند.
متد failed در Job
در هر Job میتوانید متد failed تعریف کنید تا وقتی Job شکست نهایی خورد، عملیات خاصی انجام شود.
use Throwable;
public function failed(Throwable $exception): void
{
// Log error, notify admin, update database status
}
مثال:
public function failed(Throwable $exception): void
{
report($exception);
$this->order->update([
'notification_status' => 'failed',
]);
}
این متد برای ثبت لاگ، ارسال هشدار به مدیر سیستم، تغییر وضعیت رکورد یا اطلاعرسانی به تیم فنی کاربرد دارد.
Job Chaining در Laravel
گاهی چند Job باید پشت سر هم اجرا شوند. مثلاً:
- پردازش تصویر
- ساخت Thumbnail
- آپلود به Storage
- ارسال اعلان به کاربر
در Laravel میتوان از Job Chaining استفاده کرد:
use Illuminate\Support\Facades\Bus;
Bus::chain([
new ProcessImage($image),
new GenerateThumbnail($image),
new NotifyUserImageReady($user),
])->dispatch();
اگر یکی از Jobهای زنجیره شکست بخورد، Jobهای بعدی اجرا نمیشوند. این قابلیت برای فرآیندهای مرحلهای بسیار مفید است.
Job Batching در Laravel
گاهی لازم است تعداد زیادی Job را بهصورت گروهی اجرا و وضعیت کل مجموعه را پیگیری کنید. مثلاً:
- پردازش ۱۰ هزار رکورد
- ارسال ایمیل انبوه
- Import فایل بزرگ
- تولید چندین گزارش
- پردازش تصاویر زیاد
Laravel از Job Batching پشتیبانی میکند:
use Illuminate\Support\Facades\Bus;
$batch = Bus::batch([
new ImportCustomers($chunk1),
new ImportCustomers($chunk2),
new ImportCustomers($chunk3),
])->dispatch();
برای استفاده از Batch معمولاً باید جدول مربوط به Job Batches ساخته شود:
php artisan make:queue-batches-table
php artisan migrate
Batchها برای پردازشهای بزرگ و قابل مانیتور بسیار کاربردی هستند.
Dispatch بعد از Commit دیتابیس
یکی از نکات بسیار مهم در Laravel این است که اگر داخل Transaction دیتابیس Job را Dispatch کنید، ممکن است Job قبل از Commit شدن Transaction اجرا شود. در این حالت Job ممکن است دادهای را بخواند که هنوز در دیتابیس نهایی نشده است.
مثال مشکلدار:
DB::transaction(function () {
$order = Order::create([...]);
SendOrderCreatedNotification::dispatch($order);
});
روش بهتر:
DB::transaction(function () {
$order = Order::create([...]);
SendOrderCreatedNotification::dispatch($order)->afterCommit();
});
یا Dispatch را بعد از خروج موفق از Transaction انجام دهید:
$order = DB::transaction(function () {
return Order::create([...]);
});
SendOrderCreatedNotification::dispatch($order);
این نکته در پروژههای واقعی بسیار مهم است، چون خطاهای مربوط به اجرای زودهنگام Job معمولاً تصادفی و سختدیباگ هستند.
ShouldQueue در Mail، Notification و Event Listener
در Laravel فقط Jobهای مستقیم نیستند که میتوانند وارد Queue شوند. Mailها، Notificationها و Event Listenerها هم میتوانند Queue شوند.
Queue کردن Mail
اگر Mailable شما Queue شود، ارسال ایمیل در پسزمینه انجام میشود.
Mail::to($user)->queue(new WelcomeMail($user));
Queue کردن Notification
$user->notify(new OrderCreatedNotification($order));
اگر Notification پیادهسازی مناسب Queue داشته باشد، میتواند در صف اجرا شود.
Queue کردن Listener
Listenerها میتوانند ShouldQueue را پیادهسازی کنند تا در پسزمینه اجرا شوند:
class SendOrderNotification implements ShouldQueue
{
public function handle(OrderCreated $event): void
{
//
}
}
این قابلیتها کمک میکنند معماری Event-Driven در Laravel تمیزتر و مقیاسپذیرتر شود.
Supervisor برای اجرای Queue در Production
در محیط Production نباید Worker را دستی در ترمینال اجرا کنید و همانطور رها کنید. اگر سرور Restart شود یا Worker خطا بدهد، پردازش صف متوقف میشود. برای مدیریت Workerها معمولاً از Supervisor استفاده میشود.
نمونه فایل تنظیمات Supervisor:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3 --timeout=120
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stopwaitsecs=3600
فعالسازی:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
در این مثال، numprocs=4 یعنی چهار Worker همزمان اجرا میشوند. تعداد Workerها باید با توجه به منابع سرور، نوع Jobها و حجم صف انتخاب شود.
Laravel Horizon چیست؟
Laravel Horizon ابزار رسمی و قدرتمند Laravel برای مدیریت و مانیتورینگ Queueهای مبتنی بر Redis است. Horizon یک داشبورد زیبا و تنظیمات Code-Driven برای صفهای Redis ارائه میدهد. طبق مستندات رسمی Laravel، Horizon امکان مانیتور کردن معیارهای مهم سیستم Queue مانند Throughput، Runtime و Job Failures را فراهم میکند و تنظیمات Workerها در یک فایل کانفیگ ساده نگهداری میشود. مطالعه مستندات رسمی Laravel Horizon
مزایای Horizon:
| قابلیت | توضیح |
|---|---|
| داشبورد مدیریتی | مشاهده وضعیت صفها و Jobها |
| مانیتورینگ Failed Jobs | بررسی خطاهای Jobها |
| مدیریت Workerها | تنظیم تعداد Processها و Queueها |
| Metrics | مشاهده زمان اجرا و Throughput |
| Auto Scaling | تنظیم Workerها بر اساس بار صف |
| پیکربندی کدنویسیشده | تنظیمات داخل فایل Config |
| مناسب تیمهای DevOps | کنترل بهتر در Production |
نصب Horizon:
composer require laravel/horizon
انتشار فایلهای تنظیمات:
php artisan horizon:install
اجرای Migration:
php artisan migrate
اجرای Horizon:
php artisan horizon
نکته مهم: Horizon برای Queueهای Redis طراحی شده است. اگر از Database Queue استفاده میکنید، Horizon انتخاب مناسبی نیست و باید از Workerهای معمولی و Supervisor استفاده کنید.
Redis Queue در Laravel
Redis یکی از بهترین انتخابها برای Queue در پروژههای Production است. سرعت بالا، سازگاری خوب با Laravel و امکان استفاده از Horizon باعث شده Redis در بسیاری از پروژههای لاراولی انتخاب اصلی باشد.
تنظیم .env:
QUEUE_CONNECTION=redis
اطمینان از تنظیم Redis:
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
برای استفاده بهتر در Production:
- Redis را امن پیکربندی کنید.
- دسترسی بیرونی غیرضروری به Redis را ببندید.
- Memory Policy مناسب انتخاب کنید.
- صفهای مهم را جدا کنید.
- Horizon یا مانیتورینگ مناسب داشته باشید.
- Workerها را با Supervisor یا systemd مدیریت کنید.
Database Queue در Laravel
Database Queue برای شروع، پروژههای کوچک و محیطهایی که Redis در دسترس نیست مناسب است. در این روش، Jobها در جدول دیتابیس ذخیره میشوند.
مزایا:
- راهاندازی ساده
- عدم نیاز به سرویس جداگانه
- مناسب پروژههای کمترافیک
- قابل مشاهده در دیتابیس
معایب:
- فشار بیشتر روی دیتابیس
- سرعت کمتر نسبت به Redis
- مناسب نبودن برای حجم بسیار بالا
- احتمال افزایش Lock و Queryهای زیاد
برای پروژههای کوچک یا متوسط، Database Queue میتواند کافی باشد؛ اما برای پروژههای پرترافیک، Redis معمولاً انتخاب بهتری است.
اولویتبندی Jobها
برای اولویتبندی Jobها میتوانید از Queueهای مختلف استفاده کنید:
CriticalSmsJob::dispatch($data)->onQueue('high');
SendEmailJob::dispatch($data)->onQueue('default');
GenerateReportJob::dispatch($data)->onQueue('low');
Worker:
php artisan queue:work --queue=high,default,low
در این حالت، Worker ابتدا Jobهای Queue high را اجرا میکند، سپس به سراغ default و بعد low میرود.
این روش در سیستمهای واقعی بسیار کاربردی است؛ چون همه کارها اهمیت یکسانی ندارند.
Jobهای Idempotent؛ نکته حیاتی در Queue
یکی از اصول بسیار مهم در طراحی Jobها این است که Job باید تا حد امکان Idempotent باشد. یعنی اگر یک Job به هر دلیل دوباره اجرا شد، باعث ایجاد داده تکراری یا اثر مخرب نشود.
چرا؟ چون ممکن است Job به دلیل Timeout، Retry، خطای شبکه یا Restart Worker دوباره اجرا شود.
مثال بد:
public function handle(): void
{
Invoice::create([
'order_id' => $this->order->id,
'amount' => $this->order->total_price,
]);
}
اگر Job دوبار اجرا شود، دو فاکتور ساخته میشود.
مثال بهتر:
public function handle(): void
{
Invoice::firstOrCreate(
['order_id' => $this->order->id],
['amount' => $this->order->total_price]
);
}
در پروژههای مالی، سفارش، پیامک، پرداخت و انبار، Idempotency بسیار مهم است.
مدیریت همزمانی و جلوگیری از اجرای تکراری Job
گاهی نمیخواهید چند نمونه از یک Job همزمان اجرا شوند. برای مثال، تولید گزارش روزانه نباید دوبار همزمان اجرا شود. Laravel امکاناتی مثل Middlewareهای Job برای کنترل این رفتار دارد.
نمونه مفهومی:
public function middleware(): array
{
return [
new WithoutOverlapping($this->reportId),
];
}
این کار باعث میشود Jobهای مشابه همزمان اجرا نشوند.
برای پروژههایی که پردازشهای حساس دارند، جلوگیری از همپوشانی Jobها بسیار مهم است.
Job Middleware در Laravel
Job Middleware به شما اجازه میدهد قبل یا اطراف اجرای Job منطق مشخصی اعمال کنید. کاربردها:
- جلوگیری از اجرای همزمان Job مشابه
- Rate Limit برای API خارجی
- محدود کردن تعداد تلاش به سرویس پیامک
- جلوگیری از فشار به سرویسهای Third-Party
- کنترل قفلهای توزیعشده
مثال کاربردی:
public function middleware(): array
{
return [
new RateLimited('sms-provider'),
];
}
این روش برای سرویسهایی که محدودیت تعداد درخواست دارند بسیار مفید است.
Queue و APIهای خارجی
یکی از رایجترین کاربردهای Queue، ارتباط با APIهای خارجی است. برای مثال:
- ارسال پیامک
- ارسال ایمیل
- اتصال به CRM
- همگامسازی با نرمافزار حسابداری
- ارسال Webhook
- دریافت وضعیت پرداخت
چرا این کارها باید Queue شوند؟
- API خارجی ممکن است کند باشد.
- ممکن است موقتاً قطع شود.
- ممکن است Rate Limit داشته باشد.
- کاربر نباید منتظر پاسخ سرویس خارجی بماند.
- Retry و Backoff برای خطاهای موقت لازم است.
نمونه:
class SyncCustomerWithCrm implements ShouldQueue
{
use Queueable;
public int $tries = 5;
public function backoff(): array
{
return [30, 120, 600];
}
public function handle(CrmService $crmService): void
{
$crmService->syncCustomer($this->customer);
}
}
Queue و ارسال ایمیل
ارسال ایمیل یکی از بهترین مثالها برای استفاده از Queue است. ارسال ایمیل معمولاً به سرویس SMTP یا API خارجی وابسته است و ممکن است چند ثانیه طول بکشد.
روش نامناسب:
Mail::to($user->email)->send(new WelcomeMail($user));
روش بهتر:
Mail::to($user->email)->queue(new WelcomeMail($user));
یا با Job:
SendWelcomeEmail::dispatch($user)->onQueue('emails');
در پروژههای پرترافیک، Queue کردن ایمیلها باعث افزایش سرعت ثبتنام، خرید و فرمهای سایت میشود.
Queue و پردازش فایل
اگر کاربر تصویر، ویدئو یا فایل بزرگ آپلود کند، پردازش آن نباید داخل Request انجام شود. برای مثال:
- ساخت Thumbnail
- فشردهسازی تصویر
- استخراج متن از فایل
- تبدیل فرمت ویدئو
- اسکن امنیتی فایل
- انتقال فایل به Storage خارجی
نمونه:
ProcessUploadedImage::dispatch($imagePath)->onQueue('media');
در این ساختار، کاربر بعد از آپلود فایل سریع پاسخ میگیرد و پردازش در پسزمینه انجام میشود.
Queue و گزارشگیری
گزارشهای سنگین یکی از دلایل رایج کند شدن سیستم هستند. اگر تولید گزارش مالی، اکسل، PDF یا تحلیل داده زمانبر است، بهتر است با Queue انجام شود.
جریان پیشنهادی:
درخواست گزارش → ثبت رکورد report با status=pending → Dispatch Job → تولید فایل → status=completed → اطلاع به کاربر
نمونه:
$report = Report::create([
'user_id' => auth()->id(),
'status' => 'pending',
]);
GenerateSalesReport::dispatch($report)->onQueue('reports');
Job:
public function handle(ReportService $reportService): void
{
$path = $reportService->generateSalesReport($this->report);
$this->report->update([
'status' => 'completed',
'file_path' => $path,
]);
}
این روش برای نرمافزارهای سازمانی، مالی، CRM و ERP بسیار مهم است.
Queue و Transaction دیتابیس
ترکیب Queue و Transaction باید با دقت انجام شود. اگر Job قبل از Commit اجرا شود، ممکن است داده مورد نیاز هنوز در دیتابیس وجود نداشته باشد. برای همین باید از afterCommit یا Dispatch بعد از Transaction استفاده کرد.
نمونه مناسب:
$order = DB::transaction(function () use ($data) {
return Order::create($data);
});
SendOrderCreatedNotification::dispatch($order);
یا:
SendOrderCreatedNotification::dispatch($order)->afterCommit();
در سیستمهای مالی، سفارش، پرداخت و انبار، این نکته بسیار مهم است.
مانیتورینگ Queue در Production
Queue بدون مانیتورینگ میتواند خطرناک باشد. ممکن است Jobها شکست بخورند، صفها انباشته شوند، Workerها متوقف شوند یا پردازشها کند شوند و تیم فنی متوجه نشود.
مواردی که باید مانیتور شوند:
| شاخص | اهمیت |
|---|---|
| تعداد Jobهای در صف | نشاندهنده فشار سیستم |
| Failed Jobs | نشاندهنده خطاهای پردازش |
| زمان انتظار Job | نشاندهنده کندی Workerها |
| زمان اجرای Job | شناسایی Jobهای سنگین |
| مصرف حافظه Worker | جلوگیری از Crash |
| تعداد Workerهای فعال | اطمینان از پردازش صف |
| خطاهای API خارجی | تشخیص مشکل سرویسهای وابسته |
برای Redis Queue، Laravel Horizon گزینه بسیار خوبی است. برای Database Queue میتوان از لاگ، مانیتورینگ سفارشی، ابزارهای سرور و بررسی جدول Jobها استفاده کرد.
امنیت در Job و Queue
Queueها نیز مانند سایر بخشهای برنامه نیازمند توجه امنیتی هستند.
نکات مهم:
- داده حساس غیرضروری را داخل Job Serialize نکنید.
- بهجای ذخیره کل داده حساس، شناسه رکورد را ارسال کنید.
- دسترسی به Redis یا Queue Backend را محدود کنید.
- Failed Jobs را بررسی کنید چون ممکن است داده حساس در Payload داشته باشند.
- Logهای Job را بدون کنترل پر از اطلاعات محرمانه نکنید.
- Jobهای مربوط به فایل را از نظر مسیر فایل و نوع فایل ایمن طراحی کنید.
- برای APIهای خارجی، Tokenها را در .env نگه دارید، نه داخل Job.
مثال بهتر:
SendInvoiceJob::dispatch($invoice->id);
بهجای:
SendInvoiceJob::dispatch($fullSensitiveInvoiceData);
تست Jobها در Laravel
Laravel امکان تست Queue و Job را بهخوبی فراهم میکند. برای مثال، میتوانید بررسی کنید که یک Job Dispatch شده است، بدون اینکه واقعاً اجرا شود.
use Illuminate\Support\Facades\Queue;
Queue::fake();
$response = $this->post('/orders', $data);
Queue::assertPushed(SendOrderCreatedNotification::class);
یا بررسی کنید Job خاصی با داده مشخص Dispatch شده است:
Queue::assertPushed(SendOrderCreatedNotification::class, function ($job) use ($order) {
return $job->order->id === $order->id;
});
برای تست خود منطق Job نیز میتوانید متد handle را با وابستگیهای Mock شده بررسی کنید.
در پروژههای حرفهای، تست Queue اهمیت زیادی دارد؛ چون بسیاری از عملیات مهم سیستم در پسزمینه انجام میشوند.
خطاهای رایج در استفاده از Job و Queue
1. اجرا نکردن Worker
Job Dispatch میشود اما هرگز اجرا نمیشود، چون Worker فعال نیست.
2. استفاده از Driver sync در Production
اگر QUEUE_CONNECTION=sync باشد، Jobها بلافاصله در همان Request اجرا میشوند و عملاً صف واقعی ندارید.
3. فراموش کردن ShouldQueue
اگر Job یا Listener باید Queue شود اما ShouldQueue را پیادهسازی نکند، ممکن است بهصورت Sync اجرا شود.
4. Dispatch داخل Transaction بدون afterCommit
این کار میتواند باعث اجرای Job قبل از نهایی شدن دادهها شود.
5. نبود Retry و Backoff مناسب
در ارتباط با APIهای خارجی، نبود Retry باعث شکست غیرضروری عملیات میشود.
6. Jobهای غیر Idempotent
اگر Job دوباره اجرا شود و داده تکراری بسازد، سیستم دچار خطا میشود.
7. اجرای عملیات بسیار طولانی بدون Timeout مناسب
Jobهای طولانی باید Timeout، Memory و Retry مناسب داشته باشند.
8. مانیتور نکردن Failed Jobs
Failed Jobs اگر بررسی نشوند، خطاهای مهم سیستم پنهان میمانند.
9. استفاده از یک Queue برای همه کارها
اگر گزارشهای سنگین و پیامکهای فوری در یک صف باشند، کارهای فوری پشت پردازشهای سنگین گیر میکنند.
10. Restart نکردن Worker بعد از Deploy
Workerهای Queue فرایندهای طولانیمدت هستند و بعد از Deploy باید Restart شوند.
بهترین روشهای استفاده از Job و Queue در Laravel
1. کارهای زمانبر را از Request جدا کنید
ارسال ایمیل، پیامک، پردازش تصویر، گزارشگیری و APIهای خارجی گزینههای مناسب Queue هستند.
2. Queueهای جداگانه بسازید
کارهای فوری، عادی و سنگین را در صفهای جدا قرار دهید.
3. Jobها را کوچک و متمرکز نگه دارید
هر Job بهتر است یک مسئولیت مشخص داشته باشد.
4. از Service داخل Job استفاده کنید
Job نباید به God Class تبدیل شود. منطق تجاری را در Service قرار دهید.
5. Retry و Backoff را تنظیم کنید
برای خطاهای موقت API خارجی، Retry ضروری است.
6. Jobها را Idempotent طراحی کنید
اجرای دوباره Job نباید داده تکراری یا اثر مخرب ایجاد کند.
7. Failed Jobs را مانیتور کنید
بررسی Failed Jobs باید بخشی از عملیات نگهداری سیستم باشد.
8. در Production از Supervisor یا Horizon استفاده کنید
Workerها باید همیشه فعال و مدیریتشده باشند.
9. Dispatch بعد از Commit را رعایت کنید
در عملیات دیتابیسی حساس، از afterCommit یا Dispatch بعد از Transaction استفاده کنید.
10. امنیت Payloadها را جدی بگیرید
اطلاعات حساس را بیدلیل داخل Job Payload قرار ندهید.
جدول مقایسه ابزارهای مرتبط با Queue در Laravel
| ابزار / مفهوم | کاربرد | مناسب برای | نکته مهم |
|---|---|---|---|
| Job | تعریف کار پسزمینه | ارسال ایمیل، پردازش فایل | بهتر است کوچک و متمرکز باشد |
| Queue | نگهداری Jobها | اجرای غیرهمزمان | میتواند چند صف جدا داشته باشد |
| Worker | اجرای Jobها | محیط Development و Production | در Production باید مدیریت شود |
| Database Driver | ذخیره Job در دیتابیس | پروژههای کوچک و متوسط | برای ترافیک بالا محدودیت دارد |
| Redis Driver | صف سریع و مقیاسپذیر | Production جدی | مناسب Horizon |
| Horizon | داشبورد و مدیریت Queue | Redis Queue | ابزار رسمی Laravel برای مانیتورینگ |
| Supervisor | مدیریت Workerها | سرور Linux | Worker را همیشه فعال نگه میدارد |
| Failed Jobs | ثبت Jobهای شکستخورده | دیباگ و مانیتورینگ | باید مرتب بررسی شود |
| Retry / Backoff | تلاش مجدد | APIهای خارجی و خطاهای موقت | از فشار زیاد جلوگیری میکند |
| Delay | اجرای با تأخیر | یادآوری، رزرو، پیگیری | برای زمانبندی ساده مناسب است |
نمونه کامل: ارسال اعلان سفارش با Queue
فرض کنید بعد از ثبت سفارش باید پیامک و ایمیل ارسال شود. این کار نباید داخل Request ثبت سفارش انجام شود.
ساخت Job
php artisan make:job SendOrderCreatedNotification
Job
<?php
namespace App\Jobs;
use App\Models\Order;
use App\Services\NotificationService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;
class SendOrderCreatedNotification implements ShouldQueue
{
use Queueable;
public int $tries = 3;
public int $timeout = 60;
public function __construct(
public Order $order
) {}
public function backoff(): array
{
return [10, 60, 180];
}
public function handle(NotificationService $notificationService): void
{
$notificationService->sendOrderCreated($this->order);
}
public function failed(Throwable $exception): void
{
report($exception);
$this->order->update([
'notification_status' => 'failed',
]);
}
}
Dispatch در Service یا Controller
$order = DB::transaction(function () use ($data) {
return $this->orderService->create($data);
});
SendOrderCreatedNotification::dispatch($order)
->onQueue('notifications');
Worker
php artisan queue:work redis --queue=notifications,default --tries=3 --timeout=60
در این ساختار، ثبت سفارش سریع انجام میشود و ارسال اعلان در پسزمینه اجرا خواهد شد.
Job و Queue در پروژههای شرکتی
در پروژههای شرکتی، Queue معمولاً فقط برای ایمیل استفاده نمیشود. کاربردهای جدیتر شامل این موارد هستند:
| نوع پروژه | کاربرد Queue |
|---|---|
| فروشگاه اینترنتی | ارسال پیامک، کاهش موجودی، تولید فاکتور |
| CRM | ارسال یادآوری، همگامسازی مشتریان، اعلانها |
| ERP | پردازش گزارش، انتقال داده، عملیات مالی |
| SaaS | صدور اشتراک، ایمیلهای چرخه عمر کاربر |
| سیستم مالی | گزارشگیری، تطبیق تراکنشها، Export داده |
| سامانه محتوایی | پردازش تصویر، انتشار زمانبندیشده، ساخت Sitemap |
| اپلیکیشن موبایل | Push Notification، Sync داده |
| نرمافزار منابع انسانی | محاسبه کارکرد، ارسال اعلان، تولید خروجی اکسل |
در این نوع پروژهها، طراحی درست Queue میتواند تفاوت زیادی در کارایی و پایداری سیستم ایجاد کند.
تأثیر Queue بر سئو و تجربه کاربری
Job و Queue بهصورت مستقیم ابزار SEO نیستند، اما روی سرعت و تجربه کاربری تأثیر جدی دارند. اگر یک فرم تماس، ثبتنام، سفارش یا درخواست مشاوره به دلیل ارسال ایمیل یا اتصال به سرویس خارجی کند شود، کاربر ممکن است صفحه را ترک کند. کاهش سرعت پاسخگویی میتواند روی نرخ تبدیل، رضایت کاربر و عملکرد کلی سایت اثر منفی بگذارد.
کاربردهای Queue برای سایتهای شرکتی و محتوایی:
- ارسال فرم تماس در پسزمینه
- پردازش تصویر مقالات
- تولید Sitemap
- ارسال ایمیل خبرنامه
- ساخت گزارشهای مدیریتی
- پاکسازی Cacheهای سنگین
- ارسال Webhook به CRM
- بررسی لینکها یا دادههای محتوا
بنابراین Queue بخشی از زیرساخت فنی برای ساخت سایت سریعتر، پایدارتر و حرفهایتر است.
FAQ؛ سوالات متداول درباره Job و Queue در لاراول
1. Job در Laravel چیست؟
Job یک کلاس PHP است که یک کار مشخص را انجام میدهد؛ مثل ارسال ایمیل، ارسال پیامک، پردازش فایل یا تولید گزارش. اگر Job پیادهسازی ShouldQueue داشته باشد، میتواند در Queue اجرا شود.
2. Queue در Laravel چیست؟
Queue صفی برای نگهداری Jobهاست. Jobها در صف قرار میگیرند و Workerها آنها را در پسزمینه اجرا میکنند.
3. چرا باید از Queue استفاده کنیم؟
برای جدا کردن کارهای زمانبر از Request اصلی، افزایش سرعت پاسخگویی، کاهش Timeout، مدیریت بهتر خطاها و مقیاسپذیری بیشتر سیستم.
4. چطور در Laravel یک Job بسازیم؟
با دستور Artisan زیر:
php artisan make:job SendWelcomeEmail
سپس Job را با dispatch به صف ارسال میکنید.
5. Queue Worker چیست؟
Worker فرایندی است که Jobها را از صف برمیدارد و اجرا میکند. دستور رایج اجرای Worker:
php artisan queue:work
6. بهترین Queue Driver برای Production چیست؟
برای پروژههای جدی و پرترافیک، Redis معمولاً انتخاب مناسبی است؛ مخصوصاً اگر بخواهید از Laravel Horizon استفاده کنید. برای پروژههای کوچک، Database Queue هم میتواند کافی باشد.
7. Laravel Horizon چیست؟
Laravel Horizon ابزار رسمی Laravel برای مدیریت و مانیتورینگ Queueهای Redis است. Horizon داشبورد، Metrics، مدیریت Workerها و مشاهده Failed Jobs را فراهم میکند.
8. Failed Job چیست؟
Failed Job یعنی Job بعد از تعداد تلاش مجاز همچنان با خطا مواجه شده و در لیست Jobهای شکستخورده ثبت شده است.
9. چطور Job شکستخورده را دوباره اجرا کنیم؟
با دستور زیر:
php artisan queue:retry JOB_ID
برای همه Failed Jobها:
php artisan queue:retry all
10. آیا ارسال ایمیل باید Queue شود؟
در بیشتر پروژههای حرفهای، بله. ارسال ایمیل ممکن است کند باشد یا به سرویس خارجی وابسته باشد؛ بنابراین بهتر است در Queue اجرا شود.
11. آیا Queue جایگزین Cron Job است؟
خیر. Queue برای اجرای کارهای پسزمینه و غیرهمزمان است. Cron یا Scheduler برای اجرای کارهای زمانبندیشده استفاده میشود. البته Scheduler میتواند Job را Dispatch کند.
12. آیا باید بعد از Deploy، Worker را Restart کنیم؟
بله. چون Workerها فرایندهای طولانیمدت هستند و ممکن است کد قدیمی را در حافظه داشته باشند. بعد از Deploy بهتر است php artisan queue:restart اجرا شود.
13. آیا Job ممکن است دوبار اجرا شود؟
بله، در شرایطی مثل Retry، Timeout یا خطای Worker ممکن است Job دوباره اجرا شود. به همین دلیل Jobها باید تا حد امکان Idempotent طراحی شوند.
14. آیا میتوان چند Queue جدا داشت؟
بله. میتوانید Queueهایی مثل high، default، emails، reports و low داشته باشید و Workerها را بر اساس اولویت تنظیم کنید.
جمعبندی
Job و Queue در لاراول یکی از مهمترین ابزارها برای ساخت نرمافزارهای سریع، پایدار و مقیاسپذیر هستند. با استفاده از Queue میتوان پردازشهای زمانبر را از Request اصلی جدا کرد و به Workerهای پسزمینه سپرد. این کار باعث میشود کاربر سریعتر پاسخ بگیرد، سرور بهتر مدیریت شود و عملیاتهای سنگین با کنترل بیشتری اجرا شوند.
در پروژههای حرفهای Laravel، Queue فقط برای ارسال ایمیل نیست. پردازش تصویر، تولید گزارش، ارسال پیامک، اتصال به API خارجی، همگامسازی داده، Webhookها، Notificationها و عملیات مالی میتوانند با Job و Queue بهتر مدیریت شوند. با این حال، استفاده درست از Queue نیازمند رعایت اصولی مانند Retry، Backoff، Timeout، Failed Job Monitoring، Idempotency، تفکیک Queueها، Dispatch بعد از Commit و مدیریت Workerها در Production است.
برای پروژههای کوچک، Database Queue میتواند شروع خوبی باشد؛ اما برای پروژههای پرترافیک و شرکتی، Redis همراه با Laravel Horizon انتخاب قدرتمندتری است. Horizon امکان مانیتورینگ، مشاهده خطاها، بررسی Runtime و مدیریت Workerها را فراهم میکند و برای تیمهای فنی یک ابزار بسیار ارزشمند محسوب میشود.
اگر معماری Queue درست طراحی شود، سیستم شما سریعتر، منعطفتر، قابل مانیتورتر و آمادهتر برای رشد خواهد بود. اما اگر Queue بدون مانیتورینگ، بدون Retry مناسب یا بدون مدیریت Worker در Production استفاده شود، ممکن است خطاهای پنهان و مشکلات عملیاتی ایجاد کند. بنابراین Job و Queue باید بهعنوان بخشی جدی از معماری نرمافزار طراحی و نگهداری شوند. ⚙️
CTA
اگر پروژه Laravel شما با ارسال پیامک و ایمیل، پردازش فایل، تولید گزارش، اتصال به API خارجی، پرداخت، سفارش یا عملیاتهای زمانبر سروکار دارد، طراحی درست Queue میتواند سرعت و پایداری سیستم را بهطور جدی افزایش دهد. تیم ما میتواند در پیادهسازی Job و Queue، راهاندازی Redis و Horizon، تنظیم Supervisor، بهینهسازی Workerها، مانیتورینگ Failed Jobs و بازطراحی پردازشهای پسزمینه Laravel به شما کمک کند. برای بررسی فنی پروژه خود با ما تماس بگیرید و زیرساخت نرمافزار خود را سریعتر، پایدارتر و مقیاسپذیرتر کنید. 🚀
منابع رسمی
- مستندات رسمی Laravel درباره Queues؛ برای مطالعه Queue Connections، ساخت Job، اجرای Worker، Retry، Failed Jobs، Delay، Job Chaining و سایر قابلیتهای صف در لاراول.
مطالعه مستندات رسمی Laravel درباره Queues - مستندات رسمی Laravel Horizon؛ برای آشنایی با داشبورد مانیتورینگ Queue، تنظیم Workerها، مشاهده Runtime، Throughput و Job Failures در صفهای Redis.
مطالعه مستندات رسمی Laravel Horizon