templave v1
This commit is contained in:
275
docs/queues.md
Normal file
275
docs/queues.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# Queues & Background Jobs
|
||||
|
||||
This template includes Redis-powered queues for background processing.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Start queue worker
|
||||
make queue-start
|
||||
|
||||
# View queue logs
|
||||
make queue-logs
|
||||
|
||||
# Stop queue worker
|
||||
make queue-stop
|
||||
|
||||
# Restart after code changes
|
||||
make queue-restart
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Queue is configured to use Redis in `.env`:
|
||||
|
||||
```env
|
||||
QUEUE_CONNECTION=redis
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
```
|
||||
|
||||
## Creating Jobs
|
||||
|
||||
```bash
|
||||
php artisan make:job ProcessOrder
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Order;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ProcessOrder implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
public Order $order
|
||||
) {}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
// Process the order
|
||||
$this->order->update(['status' => 'processing']);
|
||||
|
||||
// Send notification, generate invoice, etc.
|
||||
}
|
||||
|
||||
public function failed(\Throwable $exception): void
|
||||
{
|
||||
// Handle failure - log, notify admin, etc.
|
||||
logger()->error('Order processing failed', [
|
||||
'order_id' => $this->order->id,
|
||||
'error' => $exception->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dispatching Jobs
|
||||
|
||||
```php
|
||||
// Dispatch immediately to queue
|
||||
ProcessOrder::dispatch($order);
|
||||
|
||||
// Dispatch with delay
|
||||
ProcessOrder::dispatch($order)->delay(now()->addMinutes(5));
|
||||
|
||||
// Dispatch to specific queue
|
||||
ProcessOrder::dispatch($order)->onQueue('orders');
|
||||
|
||||
// Dispatch after response sent
|
||||
ProcessOrder::dispatchAfterResponse($order);
|
||||
|
||||
// Chain jobs
|
||||
Bus::chain([
|
||||
new ProcessOrder($order),
|
||||
new SendOrderConfirmation($order),
|
||||
new NotifyWarehouse($order),
|
||||
])->dispatch();
|
||||
```
|
||||
|
||||
## Job Queues
|
||||
|
||||
Use different queues for different priorities:
|
||||
|
||||
```php
|
||||
// High priority
|
||||
ProcessPayment::dispatch($payment)->onQueue('high');
|
||||
|
||||
// Default
|
||||
SendEmail::dispatch($email)->onQueue('default');
|
||||
|
||||
// Low priority
|
||||
GenerateReport::dispatch($report)->onQueue('low');
|
||||
```
|
||||
|
||||
Run workers for specific queues:
|
||||
|
||||
```bash
|
||||
# Process high priority first
|
||||
php artisan queue:work --queue=high,default,low
|
||||
```
|
||||
|
||||
## Scheduled Jobs
|
||||
|
||||
Add to `app/Console/Kernel.php` or `routes/console.php`:
|
||||
|
||||
```php
|
||||
// routes/console.php (Laravel 11+)
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
|
||||
Schedule::job(new CleanupOldRecords)->daily();
|
||||
Schedule::job(new SendDailyReport)->dailyAt('08:00');
|
||||
Schedule::job(new ProcessPendingOrders)->everyFiveMinutes();
|
||||
|
||||
// With queue
|
||||
Schedule::job(new GenerateBackup)->daily()->onQueue('backups');
|
||||
```
|
||||
|
||||
Start scheduler:
|
||||
|
||||
```bash
|
||||
make scheduler-start
|
||||
```
|
||||
|
||||
## Module Jobs
|
||||
|
||||
When creating module jobs, place them in the module's directory:
|
||||
|
||||
```
|
||||
app/Modules/Inventory/
|
||||
├── Jobs/
|
||||
│ ├── SyncStock.php
|
||||
│ └── GenerateInventoryReport.php
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Inventory\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SyncStock implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $tries = 3;
|
||||
public $backoff = [60, 300, 900]; // Retry after 1min, 5min, 15min
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
// Sync stock levels
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Job Middleware
|
||||
|
||||
Rate limit jobs:
|
||||
|
||||
```php
|
||||
use Illuminate\Queue\Middleware\RateLimited;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
|
||||
class ProcessOrder implements ShouldQueue
|
||||
{
|
||||
public function middleware(): array
|
||||
{
|
||||
return [
|
||||
new RateLimited('orders'),
|
||||
new WithoutOverlapping($this->order->id),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### View Failed Jobs
|
||||
|
||||
```bash
|
||||
php artisan queue:failed
|
||||
```
|
||||
|
||||
### Retry Failed Jobs
|
||||
|
||||
```bash
|
||||
# Retry specific job
|
||||
php artisan queue:retry <job-id>
|
||||
|
||||
# Retry all failed jobs
|
||||
php artisan queue:retry all
|
||||
```
|
||||
|
||||
### Clear Failed Jobs
|
||||
|
||||
```bash
|
||||
php artisan queue:flush
|
||||
```
|
||||
|
||||
## Production Setup
|
||||
|
||||
For production, use Supervisor instead of Docker:
|
||||
|
||||
```ini
|
||||
# /etc/supervisor/conf.d/laravel-worker.conf
|
||||
[program:laravel-worker]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
user=www-data
|
||||
numprocs=2
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/www/html/storage/logs/worker.log
|
||||
stopwaitsecs=3600
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo supervisorctl reread
|
||||
sudo supervisorctl update
|
||||
sudo supervisorctl start laravel-worker:*
|
||||
```
|
||||
|
||||
## Testing Jobs
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
|
||||
it('dispatches order processing job', function () {
|
||||
Queue::fake();
|
||||
|
||||
$order = Order::factory()->create();
|
||||
|
||||
// Trigger action that dispatches job
|
||||
$order->markAsPaid();
|
||||
|
||||
Queue::assertPushed(ProcessOrder::class, function ($job) use ($order) {
|
||||
return $job->order->id === $order->id;
|
||||
});
|
||||
});
|
||||
|
||||
it('processes order correctly', function () {
|
||||
$order = Order::factory()->create(['status' => 'pending']);
|
||||
|
||||
// Run job synchronously
|
||||
(new ProcessOrder($order))->handle();
|
||||
|
||||
expect($order->fresh()->status)->toBe('processing');
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user