Fáze požadavku: 11. FrankenPHP & Produkční běh
Modul 9 · Lekce 2

Jak v produkci běží fronty (queue:work) a plánovač (schedule:work)

💡 Shrnutí lekce

Pochopte, jak Laravel 12 plánuje úlohy přes routes/console.php a jak v produkčním Docker kontejneru zajistit periodické spouštění scheduleru a zpracování front bez cron démona na hostiteli.

Asynchronní zpracování a plánovač v Laravelu 12

Produkční webové aplikace nesmí zdržovat uživatele dlouhotrvajícími operacemi (jako je odesílání e-mailů, generování PDF reportů, náročné audity nebo synchronizace externích API). Laravel nabízí dva integrované pilíře pro běh úloh na pozadí:

  1. Fronty (Queues): Asynchronní zpracování zpráv na vyžádání (dispatch).
  2. Plánovač úloh (Task Scheduler): Periodické spouštění úloh podle časového harmonogramu.

Zjednodušení v Laravelu 12: Plánovač v routes/console.php

V předchozích verzích Laravelu se plánované úlohy registrovaly v třídě app/Console/Kernel.php v metodě schedule(). Laravel 12 tento zastaralý kernel odstranil a sjednotil veškerou konzolovou logiku do souboru routes/console.php.

Pomocí fasády Illuminate\Support\Facades\Schedule můžete plánovat Artisan příkazy, anonymní funkce i frontové joby:

// Spuštění našeho Zero-Hallucination auditu každou noc ve 3:00
Schedule::command('curriculum:verify')->dailyAt('03:00');

// Spuštění promazání neaktivních anonymních profilů jednou týdně
Schedule::call(function () {
    // ...
})->weekly();

Jak plánovač reálně funguje v operačním systému

Plánovač v Laravelu není samostatný démon, který by sám od sebe trvale běžel na pozadí. V klasickém Linuxovém prostředí se spoléhá na jediný systémový cron záznam na hostiteli, který se spouští každou minutu:

* * * * * cd /cesta-k-projektu && php artisan schedule:run >> /dev/null 2>&1

Při každém zavolání schedule:run Laravel vyhodnotí aktuální čas proti všem naplánovaným úlohám v routes/console.php a spustí pouze ty, jejichž čas právě nastal.

V Dockerizovaných a kontejnerových prostředích (jako je naše architektura s FrankenPHP) však často nechceme instalovat cron démona do kontejneru. Laravel proto nabízí příkaz:

php artisan schedule:work

Tento příkaz udržuje dlouhotrvající proces v paměti a každou minutu sám interně vyvolá schedule:run.


Produkční provoz asynchronních front (queue:work)

Když do fronty odešlete Job (MyJob::dispatch()), Laravel jej uloží do zvoleného backendu (PostgreSQL tabulka jobs, Redis, Amazon SQS atd.).

Ke zpracování zpráv slouží konzolový worker:

php artisan queue:work --tries=3 --timeout=90

Zásadní pravidlo pro produkční nasazení workerů:

Příkaz queue:work načte celou aplikaci (včetně všech PHP tříd a konfigurace) do paměti RAM a drží ji tam pro dosažení maximální rychlosti. Při nasazení nové verze kódu worker sám o sobě změněné soubory na disku nenačte!

Proto je v deployment skriptu (deploy.sh) nebo při restartu kontejneru nezbytné poslat signál restartu:

php artisan queue:restart

Tento příkaz zapíše do mezipaměti pokyn pro všechny aktivní workery, aby po dokončení právě běžící úlohy korektně ukončili svůj proces. Docker supervisor (nebo orchestrátor) je pak automaticky nastartuje znovu již s novým kódem.

💻 Klíčová konstrukce z praxe
// routes/console.php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;

Artisan::command('inspire', function (): void {
    $this->comment('Anatomie Laravelu 12 & PHP 8.4 — Živá výuková platforma na laravel.heatsharing.cz');
})->purpose('Zobrazí motto výukové platformy');

// Pravidelný noční audit osnovy a souborů kurzu každé ráno ve 3:00
Schedule::command('curriculum:verify')->dailyAt('03:00');

🎯 Ověření znalostí z lekce

Kvíz otestuje pochopení architektury a reálného kódu probíraného v této lekci.

Otázka 1 z 3

Kde se v Laravelu 12 standardně definují naplánované úlohy (Scheduled Tasks)?

Otázka 2 z 3

Jaký je rozdíl mezi příkazy schedule:run a schedule:work?

Otázka 3 z 3

Proč je nutné po nasazení nové verze kódu do produkce provést příkaz php artisan queue:restart?

Zodpovězeno: 0 / 3
🔬 Živá anatomie v této aplikaci
2 soubory
Na co se v kódu zaměřit: V routes/console.php si všimni řádku Schedule::command("curriculum:verify")->dailyAt("03:00"), kde Laravel 12 přímo registruje plánované úlohy bez nutnosti starého souboru Kernel.php.
cesta: routes/console.php
12 řádků · 0.4 KB
Soubor aplikační architektury v modulu HTTP Routing.
1 <?php
2
3 declare(strict_types=1);
4
5 use Illuminate\Support\Facades\Artisan;
6 use Illuminate\Support\Facades\Schedule;
7
8 Artisan::command('inspire', function (): void {
9 $this->comment('Anatomie Laravelu 12 & PHP 8.4 — Živá výuková platforma na laravel.heatsharing.cz');
10 })->purpose('Zobrazí motto výukové platformy');
11
12 Schedule::command('curriculum:verify')->dailyAt('03:00');
13
cesta: compose.prod.yaml
37 řádků · 0.7 KB
Produkční Docker Compose pro nasazení na Hetzner serveru s připojením na sdílenou síť db a caddy.
1 name: agylaravel
2
3 services:
4 app:
5 image: agylaravel/course:prod
6 build:
7 context: .
8 dockerfile: docker/Dockerfile
9 target: prod
10 env_file: .env
11 restart: unless-stopped
12 environment:
13 PHP_OPCACHE_VALIDATE_TIMESTAMPS: "0"
14 RUN_MIGRATIONS: "1"
15 RUN_SEEDERS: "1"
16 volumes:
17 - storage:/app/storage
18 networks:
19 db: {}
20 web:
21 aliases:
22 - agy-laravel
23 healthcheck:
24 test: ["CMD-SHELL", "curl -fsS http://localhost/up >/dev/null || exit 1"]
25 interval: 30s
26 timeout: 5s
27 start_period: 60s
28 retries: 3
29
30 networks:
31 db:
32 external: true
33 web:
34 external: true
35
36 volumes:
37 storage:
38
Zdroj: skutečné soubory této aplikace Plný průzkumník anatomie →