Naplánované úlohy#
Všechno, co se v systému děje samo od sebe. Seznam se generuje z kódu, takže vyjmenovává přesně ty úlohy, které v repozitáři opravdu jsou.
Jak se úloha volá#
| Věc | Jak to funguje |
|---|---|
| Ověření | dotaz musí nést ?token= shodný s nastavením cron.token (skupina 1) |
| Odpověď | vždy JSON — {"status":"ok",…}, {"status":"error",…} nebo {"status":"skipped"} |
| Souběh | druhá instance téže úlohy skončí skipped, nečeká se |
Bez tokenu vrací 403 — a prázdný token nepustí NIKOHO
Kontrola porovnává očekávanou a poslanou hodnotu; když cron.token v nastavení
chybí, neprojde ani prázdný dotaz. Po nasazení na nový server je to první věc
k vyplnění, jinak neběží vůbec nic a nikde to nekřičí.
Zámek souběhu je fail-open
Dokud tabulka zámků neexistuje, skipped se nikdy nevrátí a úlohy se můžou
překrývat. Je to schválně — chybějící tabulka nemá zastavit provoz — ale
znamená to, že „nikdy jsem skipped neviděl“ není důkaz, že zámek funguje.
Jak poznat, že úloha běžela
Podle odpovědi, ne podle toho, že „nic nespadlo“. {"status":"ok"} vrací
i úloha, která neudělala nic — počty jsou v dalších klíčích odpovědi.
Plánovač — jedna adresa místo padesáti#
Úloh je kolem sedmdesáti. Zadávat je na hostingu po jedné se při každé nové úloze zapomene, proto je volá plánovač: hosting volá jedinou adresu
a plánovač podle tabulky cms_system_cron_jobs rozhodne, které úlohy jsou právě na řadě, a volá
je jednu po druhé HTTP na vlastní adresu se stejným tokenem — žádná úloha se nepřepisuje.
Správce ho spravuje v administraci (Nastavení → Cron, viz Plánovač úloh).
| Věc | Jak to funguje |
|---|---|
| Katalog | atribut #[CronJob(frequency: …, outbound: …, query: […])] na veřejné action*() cron presenteru — zdroj pravdy; docblock (URL:, Frekvence:) zůstává kvůli tomuto přehledu |
| Nová úloha | bez atributu ji plánovač nezná — test CronJobCatalogTest shodí každou action* bez něj. Do tabulky se doplní sama při dalším volání plánovače (bez migrace) |
| Frekvence | text every:N · daily:HH:MM · weekly:D@HH:MM · monthly:D@HH:MM · manual (CronFrequency); „jednorázově po nasazení“ a opravné úlohy = manual |
outbound |
povinný argument (bez výchozí hodnoty): true = posílá e-maily/SMS, vystavuje doklady, maže/anonymizuje data uživatelů, volá platební brány nebo notifikuje hlídací psy. Odchozí úloha je po objevení vypnutá. Při nejistotě true |
query |
pevné parametry volání (např. sitemapy ['save' => '1'] — bez save vrací jen náhled) |
| Moduly | cms_system_cron_jobs.module_id z cesty /cron/<modul>/… (cms_system_modules); úlohy modulu s activated = 0 se nezobrazují ani nespouštějí, modul system je vždy |
| Běh | rozpočet 45 s, nejdéle neběžící první; chyba nebo timeout = stav error a další pokus až v dalším termínu; „skipped“ (zámek úlohy) se zkusí při dalším volání. Odpověď se ukládá zkrácená (≤ 500 znaků) a token se do ní ani do logu nikdy nedostane |
| Souběh | dva plánovače: druhý skončí skipped na zámku (cron.system.scheduler.run) jako každý cron |
| Plánovač není úloha | SchedulerPresenter katalog vynechává (CronJobCatalog::EXCLUDED_PRESENTERS) |
Plánovač volá úlohy po HTTP na vlastní adresu
Na jednovláknovém php -S (lokální dev server) se takové volání zasekne a skončí timeoutem —
server nemůže obsloužit druhý požadavek, dokud nedoběhl první. Ověřuj s více procesy:
PHP_CLI_SERVER_WORKERS=4 php -S ….
Přidáváš novou cron akci?
- Přidej
#[CronJob(frequency: '…', outbound: true|false)]nadaction*()(aquery, pokud jsou potřeba). - Doplň název úlohy do překladů
admin.system.presenters.cronJob.jobs.<modul>.<presenter>.<akce>(cs/en/sk); bez překladu se v administraci ukáže jen adresa. - Ostatní (tabulka, výpis, plánování) se dělá samo.
Nasazení#
Sloupec Doporučený interval je návrh ze zdrojového kódu — z něj se skládá crontab. Například:
*/1 * * * * curl -s "https://web.cz/cron/system/email-queue/send?token=TOKEN"
*/5 * * * * curl -s "https://web.cz/cron/store/reservation/expire?token=TOKEN"
15 3 * * * curl -s "https://web.cz/cron/blog/sitemap/article?token=TOKEN"
Nezapojená úloha NIKDY neběží — a nic se nerozbije
Nespuštěná úloha nevyhodí chybu. Jen se přestane dít to, co měla dělat: nevyprší košíky, nevygenerují se faktury, neuklidí se data. Odhalí se to obvykle až tím, že něco „nějak narostlo“. Proto po instalaci projděte celý seznam níž, ne jen to, co zrovna používáte.
Ne všechno je periodické
Několik úloh je opravných nebo jednorázových — mají v intervalu napsané „ručně“. Do crontabu nepatří; pustí se, když je potřeba.
Sitemap index až po ostatních sitemapách
Skládá rozcestník z už vygenerovaných souborů. Když poběží první, sestaví ho z toho, co zbylo po minulém běhu.
Přehled úloh#
Sdílené#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/base/newsletter/dispatch |
Dispatches executing newsletters into the e-mail queue in batches ; the queue cron sends them | every 5 minutes |
/cron/base/rating/recalc |
Self-heal přepočet agregátu rating threadů | periodicky, např. jednou denně (drift je výjimečný, ne hot-path) |
Inzerce#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/bazaar/advert/notice-expiration |
Pošle BZ_ADVERT_EXPIRATION_NOTICE inzerátům, kterým do N dní vyprší expirace (N = setting 5/advert.expiration.noticeDays) | denně (např. v noci) |
/cron/bazaar/advert/delete-expired |
Tiše označí deleted=1 inzeráty, jimž od expirace uplynulo víc než M dní (M = setting 5/advert.expiration.deleteDays) | denně |
/cron/bazaar/advert/recount-prices |
Přepočítá denormalizovaný sloupec price u všech inzerátů z parametru price |
periodicky, např. každých 10–15 minut |
/cron/bazaar/category/recount |
Přepočítá denormalizovaný advert_count u všech kategorií | periodicky, např. každých 10–15 minut |
/cron/bazaar/elastic/reindex |
Full reindex inzerátů do nové verze indexů + atomický alias swap (bezvýpadkově, Redis lock proti souběhu) | 1× denně v noci |
/cron/bazaar/elastic/sync |
Inkrementální sync: doindexuje inzeráty vložené od watermarku (Redis es: |
každých 10 minut |
/cron/bazaar/sitemap/category |
Sitemapa všech aktivních kategorií Bazaaru s hreflang variantami | denně v noci |
/cron/bazaar/sitemap/advert |
Sitemapa aktivních inzerátů, automaticky rozdělená na soubory podle rozsahů ID (velikost podle počtu jazyků) | denně v noci |
/cron/bazaar/watchdog-email/send |
Mód 1 — okamžité posílání | průběžně, např. každých 5–10 minut |
/cron/bazaar/watchdog-email/digest |
Mód 2 — denní digest | jednou denně, např. ve 23:00 |
/cron/bazaar/watchdog-email/purge-old |
Retence fronty hlídacího psa (PERF-8): smaže ODESLANÉ a ZRUŠENÉ řádky _watchdog_email_rel starší než N dní a e-maily (_watchdog_emails + texty), na které už žádný řádek neukazuje |
denně |
Blog#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/blog/elastic/reindex |
Full reindex článků do nové verze indexů + atomický alias swap (bezvýpadkově, Redis lock proti souběhu) | 1× denně v noci |
/cron/blog/elastic/sync |
Inkrementální sync: doindexuje články změněné od watermarku (Redis es: |
každých 10 minut |
/cron/blog/sitemap/article |
— | denně v noci |
/cron/blog/sitemap/event |
— | denně v noci |
/cron/blog/sitemap/news |
— | denně v noci |
/cron/blog/sitemap/article-category |
— | denně v noci |
/cron/blog/sitemap/event-category |
— | denně v noci |
/cron/blog/sitemap/news-category |
— | denně v noci |
Katalog firem#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/comcat/advert/notice-expiration |
Pošle CC_ADVERT_EXPIRATION_NOTICE inzerátům, kterým do N dní vyprší expirace (N = setting 5/advert.expiration.noticeDays) | denně (např. v noci) |
/cron/comcat/advert/delete-expired |
Tiše označí deleted=1 inzeráty, jimž od expirace uplynulo víc než M dní (M = setting 5/advert.expiration.deleteDays) | denně |
/cron/comcat/category/recount |
Přepočítá denormalizovaný advert_count u všech kategorií | periodicky, např. každých 10–15 minut |
/cron/comcat/elastic/reindex |
Full reindex firemních profilů (Comcat Advert) do nové verze indexů + atomický alias swap (bezvýpadkově, Redis lock proti souběhu) | 1× denně v noci |
/cron/comcat/elastic/sync |
Inkrementální sync: doindexuje inzeráty vložené od watermarku (Redis es: |
každých 10 minut |
/cron/comcat/sitemap/category |
Sitemapa všech aktivních kategorií Comcatu s hreflang variantami | denně v noci |
/cron/comcat/sitemap/advert |
Sitemapa aktivních inzerátů, automaticky rozdělená na soubory podle rozsahů ID (velikost podle počtu jazyků) | denně v noci |
/cron/comcat/watchdog-email/send |
Mód 1 — okamžité posílání | průběžně, např. každých 5–10 minut |
/cron/comcat/watchdog-email/digest |
Mód 2 — denní digest | jednou denně, např. ve 23:00 |
/cron/comcat/watchdog-email/purge-old |
Retence fronty hlídacího psa (PERF-8): smaže ODESLANÉ a ZRUŠENÉ řádky _watchdog_email_rel starší než N dní a e-maily (_watchdog_emails + texty), na které už žádný řádek neukazuje |
denně |
Company#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/company/sitemap/service |
Sitemap of the company service detail pages (Front:Company:Service:detail) |
daily, at night (before the sitemap index at 04:30) |
Diskuze#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/discussion/elastic/reindex |
Full reindex kořenů vláken (level=1) do nové verze indexu + atomický alias swap | 1× denně v noci |
/cron/discussion/elastic/sync |
Inkrementální sync: doindexuje nová vlákna od watermarku (Redis es: |
každých 10 minut |
/cron/discussion/sitemap/message |
Sitemapa top-level (level=1) aktivních zpráv, automaticky rozdělená podle rozsahů ID (velikost podle počtu jazyků) | denně v noci |
/cron/discussion/sitemap/category |
Sitemapa všech kategorií Diskuze | denně v noci |
E-shop#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/eshop/cart/cleanup |
Maže opuštěné košíky, kterým vypršela retenční lhůta | denně v noci |
/cron/eshop/complaint/expire |
Uzavírá reklamace, kterým vypršela lhůta na vyřízení | denně (lhůty se počítají ve dnech) |
/cron/eshop/elastic/reindex |
Full reindex prodejních karet do nové verze indexů + atomický alias swap (bezvýpadkově, Redis lock proti souběhu) | 1× denně v noci |
/cron/eshop/elastic/sync |
Inkrementální sync: doindexuje karty změněné od watermarku (Redis es: |
každých 10 minut |
/cron/eshop/feed/generate |
Generuje XML feedy pro srovnávače zboží | à hodinu (nebo dle požadavku srovnávače) |
/cron/eshop/order/expire |
Ruší nezaplacené objednávky a dogeneruje chybějící doklady | à hodinu |
/cron/eshop/order/cancel-unpaid |
Cancels unpaid orders and generates missing invoices | daily (the period is counted in days) |
/cron/eshop/order/invoice |
Ruší nezaplacené objednávky a dogeneruje chybějící doklady | à 15 minut |
/cron/eshop/price/recalc |
Aktivuje naplánované ceny a srovná denormalizovaný sloupec ceny | à 15 minut (aktivuje naplánované ceny — delší interval je oddálí) |
/cron/eshop/product-import/run |
Spustí nejstarší job ve frontě | každou minutu |
/cron/eshop/sitemap/category |
Sitemapa všech kategorií e-shopu s hreflang variantami | denně v noci |
/cron/eshop/sitemap/product |
Sitemapa viditelných produktů (prodejních karet), automaticky rozdělená na soubory podle rozsahů ID (velikost podle počtu jazyků) | denně v noci |
Fakturace#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/invoicer/payment/generate |
Vystavuje doklady k zaplaceným platbám podle pravidel modulu | často (např. každých 15 min) — doklady vzniknou krátce po změně stavu platby, ale MIMO |
/cron/invoicer/schedule/generate |
Vystavuje opakované faktury podle rozvrhů, kterým nastalo datum | denně |
Sklad#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/store/batch/expiry-alert |
Upozorňuje na šarže, kterým se blíží expirace | denně ráno |
/cron/store/reservation/expire |
Uvolňuje skladové rezervace, kterým vypršela platnost | à 5 minut |
/cron/store/stock/recount |
Noční přepočet skladu — srovná rezervovaná množství, šarže a ceny karet | denně v noci |
/cron/store/stock/low-stock-alert |
Upozornění na karty pod minimální zásobou — jeden souhrnný e-mail na stock.lowStock.email, karta se ohlásí jen jednou, dokud se nevrátí na minimum |
denně ráno |
Systém#
| Endpoint | Co dělá | Doporučený interval |
|---|---|---|
/cron/system/asset-thumbnail-catchup/generate |
Doplní image varianty (poster z prvního framu) pro video Assety, kterým varianty zatím nebyly fyzicky vygenerovány — typicky když v době uploadu ffmpeg chyběl nebo selhal | denně v noci |
/cron/system/asset-thumbnail-catchup/backfill-meta |
Doplní Asset.meta (reálné rozměry variant) assetům, kterým chybí (meta IS NULL) — tj. nahraným před zavedením meta sloupce | jednorázově po nasazení, pak už netřeba |
/cron/system/asset-variant-regenerate/default |
Dogenerování chybějících variant uložených obrázků : totéž co tlačítko „Dogenerovat" na záložce Použití, jen pro VŠECHNA použití najednou | po nasazení opakovaně, dokud odpověď neříká remaining: 0; pak stačí denně v noci |
/cron/system/auth-log/purge-old |
Periodický cleanup persistentního audit logu (cms_system_auth_log) | denně — |
/cron/system/dropzone-temp/clean |
Úklid dočasných složek dropzone (temp/dropzone) — soubory a prázdné složky starší než 24 h |
denně |
/cron/system/elastic/status |
Health ES clusteru + počty dokumentů per index — monitoring / smoke check | ručně (kontrola stavu) |
/cron/system/elastic/watch |
Hlídá dostupnost vyhledávání a hlásí problémy e-mailem | à 15 minut |
/cron/system/email-queue/send |
Postupné odeslání emailů z fronty | à minutu |
/cron/system/email-queue/purge-old |
Úklid vyřízených e-mailů (odeslané/zastavené) starších než N dní, newsletterové řádky zůstávají | denně |
/cron/system/file-system/sanitize |
Cron pro sanitizaci názvů souborů/složek v uploads adresáři — projde celý strom a přejmenuje položky s nevyhovujícím názvem (diakritika, mezery, nepovolené znaky) na bezpečný tvar | ručně, po hromadném nahrání souborů (není periodická) |
/cron/system/jwt-deny-list/cleanup-expired |
Cleanup expirovaných řádků z cms_system_jwt_denylist (DB-backed JtiDenyList) | denně v noci (při useRedis: true je to no-op) |
/cron/system/log/purge-old |
Retence adresáře log/ |
denně |
/cron/system/notification/clean-orphans |
Odpojení osiřelých admin notifikací od cíle (cílový záznam — objednávka, uživatel, platba… — už neexistuje): notifikace se NEMAŽE, jen se vynuluje odkaz na cíl (id), rozhodnutí 1 průchodu administrace |
denně |
/cron/system/notification/purge-read |
Odpojení osiřelých admin notifikací od cíle (cílový záznam — objednávka, uživatel, platba… — už neexistuje): notifikace se NEMAŽE, jen se vynuluje odkaz na cíl (id), rozhodnutí 1 průchodu administrace |
denně |
/cron/system/page-tree/rebuild |
Regeneruje nested-set indexy (lft, rgt, level) stromu stránek v cms_system_pages z adjacency (parent_id) | ručně, po hromadné změně stromu stránek (není periodická) |
/cron/system/payment/activation-audit |
Sonda „zaplaceno, ale neaktivováno" — platba je COMPLETED, ale položky modulu nejsou aktivní (pád uprostřed callbacku nebo neúspěch handleru) | každých 15 minut |
/cron/system/payment/purge-notifications |
Payment maintenance jobs: the activation audit and the retention of the gateway notification history | every 15 minutes |
/cron/system/rate-limit/purge-old |
Cleanup expirovaných řádků z cms_system_rate_limit (DB-backed RateLimit) | denně v noci (při useRedis: true je to no-op) |
/cron/system/scheduler/run |
Plánovač cronu — jediná adresa, kterou musí hosting volat | každých 5 minut (jediná adresa, kterou hosting volá) |
/cron/system/sitemap/generate |
Vygeneruje XML sitemapu pro System stránky se všemi jazykovými variantami (hreflang) | denně v noci |
/cron/system/sitemap/index |
Vygeneruje sitemap index (rozcestník) odkazující na všechny vygenerované sitemap- .xml soubory v adresáři |
denně v noci, AŽ PO ostatních sitemapách |
/cron/system/user/anonymize-deleted |
Account deletion — anonymizes the accounts whose grace period (account.deletion.graceDays, default 7 days) has passed |
daily |
/cron/system/user-refresh-token/purge-old |
Periodický cleanup expirovaných refresh tokenů (cms_system_user_refresh_tokens) | denně |