Ugrás a tartalomhoz

Jobok

A jobok a Queuety alapvető munkavégzési egységei. Indítson egy jobot kezelőnévvel és payloaddal; egy worker felveszi, majd a háttérben végrehajtja.

Jobok indítása

PHP
use Queuety\Queuety;

Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] );

A dispatch() egy PendingJob buildert ad vissza. Az automatikus indítás előtt láncolhat hozzá beállításokat:

PHP
use Queuety\Enums\Priority;

Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] )
    ->on_queue( 'emails' )
    ->with_priority( Priority::High )
    ->delay( 300 )
    ->max_attempts( 5 );

A job ID-jának azonnali lekéréséhez hívja meg a ->id() metódust:

PHP
$job_id = Queuety::dispatch( 'send_email', $payload )->id();

Kezelők írása

Kezelő lehet bármely osztály, amely megvalósítja a Queuety\Handler interfészt:

PHP
use Queuety\Handler;

class SendEmailHandler implements Handler {
    public function handle( array $payload ): void {
        wp_mail( $payload['to'], $payload['subject'], $payload['body'] );
    }

    public function config(): array {
        return [
            'queue'           => 'emails',
            'max_attempts'    => 5,
            'backoff'         => 'exponential',
        ];
    }
}

A handle() metódus megkapja a job payloadját, és elvégzi a munkát. A config() metódus opcionális alapértékeket ad vissza:

Kulcs Típus Leírás
queue string Alapértelmezett sornév
max_attempts int A futtatások maximális száma az elsőt is beleszámítva, mielőtt a job a parkolóba kerül
backoff string Újrapróbálkozási késleltetési stratégia: exponential, linear vagy fixed
rate_limit array Sebességkorlát [max_executions, window_seconds] formában
concurrency_group string Megosztott workerfelvételi csoport költséges kezelőkhöz
concurrency_limit int A csoporton belül egyidejűleg feldolgozható jobok maximális száma
cost_units int Relatív végrehajtási költség a súlyozott sor- vagy szolgáltatói keretekhez, munkafolyamat-keretekhez és felvételi heurisztikákhoz

Ezek az erőforráskulcsok a Queuety tágabb Erőforrás-kezelési modelljének részei, amelyben a jobok metaadatai, a munkafolyamat-keretek és a workerfelvétel együtt működnek.

Regisztrálja a kezelőt:

PHP
Queuety::register( 'send_email', SendEmailHandler::class );

Vagy használja az PHP attribútumokat az automatikus regisztrációhoz.

Prioritás

A joboknak négy prioritási szintjük van. A workerek először a magasabb prioritású jobokat veszik fel.

PHP
use Queuety\Enums\Priority;

Queuety::dispatch( 'handler', $payload )->with_priority( Priority::Urgent );
Szint Érték Leírás
Priority::Low 0 Alapértelmezett. Háttérmunka, amely várhat.
Priority::Normal 1 Szokásos prioritás.
Priority::High 2 A Low és Normal szintű jobok előtt kerül feldolgozásra.
Priority::Urgent 3 Elsőként kerül feldolgozásra. Használja takarékosan.

Késleltetés

Késleltesse a jobot, hogy csak a megadott számú másodperc elteltével váljon elérhetővé:

PHP
Queuety::dispatch( 'send_reminder', $payload )->delay( 3600 ); // 1 hour

A job azonnal bekerül, de a workerek csak a késleltetés letelte után veszik fel.

Egyedi jobok

Akadályozza meg ugyanazon kezelő és payload többszöri indítását. Ha már létezik azonos kezelőjű és payloadú, függőben lévő vagy feldolgozás alatt álló job, az új létrehozása helyett annak meglévő ID-ja kerül visszaadásra.

PHP
Queuety::dispatch( 'sync_inventory', [ 'sku' => 'ABC-123' ] )->unique();

Jobfüggőségek

Egy job függhet egy másik jobtól. A worker csak a függőség befejezése után veszi fel.

PHP
$first_id = Queuety::dispatch( 'import_data', $payload )->id();

Queuety::dispatch( 'send_notification', [ 'import_id' => $first_id ] )
    ->after( $first_id );

Kötegelt indítás

Indítson több jobot egyetlen, több soros INSERT utasítással a maximális áteresztőképességért:

PHP
$job_ids = Queuety::batch( [
    [ 'handler' => 'send_email', 'payload' => [ 'to' => 'a@example.com' ] ],
    [ 'handler' => 'send_email', 'payload' => [ 'to' => 'b@example.com' ] ],
    [ 'handler' => 'send_email', 'payload' => [ 'to' => 'c@example.com' ] ],
] );

Minden elem opcionálisan tartalmazhatja a következő kulcsokat: queue, priority, delay, max_attempts.

Újrapróbálkozás és késleltetés

Ha egy job kivételt dob, a Queuety visszateszi azt a pending sorba, és késleltetett available_at-t állít be, amíg összesen max_attempts alkalommal le nem futott (az első futás is számít, így a max_attempts( 3 ) legfeljebb két újrapróbálkozást jelent). Az egyes próbálkozások előtti késleltetést a késleltetési stratégia határozza meg; a attempt az éppen sikertelen futás sorszáma:

Stratégia Késleltetési képlet Példa (az 1., 2., 3. futás után)
exponential 2^attempt * 30 másodperc, legfeljebb 3600 60s, 120s, 240s
linear attempt * 60 másodperc 60s, 120s, 180s
fixed 60 másodperc 60s, 60s, 60s

Állítsa be a globális alapértéket itt: wp-config.php:

PHP
define( 'QUEUETY_RETRY_BACKOFF', 'linear' );

Vagy kezelőnként itt: config():

PHP
public function config(): array {
    return [ 'backoff' => 'exponential', 'max_attempts' => 5 ];
}

Vagy indításonként:

PHP
Queuety::dispatch( 'handler', $payload )->max_attempts( 10 );

Eltemetett feladatok

Az újrapróbálkozási kísérletek kimerítése után a job parkol. A parkolt jobok vizsgálat céljából az adatbázisban maradnak, de nem kerülnek feldolgozásra. Manuálisan újrapróbálhatja őket. Ilyenkor a job ismét pending lesz, próbálkozásszámlálója azonban nem áll vissza, ezért a parkolt job még egyszer lefut, és újabb hiba esetén ismét parkolásra kerül:

PHP
// Retry a specific buried job
Queuety::retry( $job_id );

// Retry all buried jobs
$count = Queuety::retry_buried();

Vagy a CLI használatával:

Shell
wp queuety retry 42
wp queuety retry-buried

Időkorlát

A(z) Queuety élesít egy pcntl_alarm()-t a maximális végrehajtási időre, és a próbálkozás meghiúsítására szolgál egy TimeoutException-val, ha az időkorlát lejár. Ez az időkorlát jelenleg nincs érvényesítve (#10): a worker nem engedélyezi az aszinkron jelzéseket, ezért a hosszan futó kezelő a végéig fut, az sleep()-ban blokkolt kezelő pedig megszakad, amikor megszólal a riasztás, majd befejezettként lesz megjelölve. Az időkorlát globális beállítása:

PHP
define( 'QUEUETY_MAX_EXECUTION_TIME', 300 ); // 5 minutes

A processing állapotban a megadott QUEUETY_STALE_TIMEOUT másodpercnél tovább elakadt jobok automatikusan helyreállításra kerülnek:

PHP
define( 'QUEUETY_STALE_TIMEOUT', 600 ); // 10 minutes

Az elakadt feladatok kézi helyreállítása:

Shell
wp queuety recover

Várólisták

A jobok névvel ellátott sorokba kerülnek. Minden worker egy sort vagy sorok rendezett listáját dolgozza fel (lásd: Workerek):

PHP
Queuety::dispatch( 'handler', $payload )->on_queue( 'emails' );
Shell
wp queuety work --queue=emails

Az alapértelmezett sor a default. A munkaterhelések elkülönítéséhez külön workerfolyamatokat futtathat az egyes sorokhoz.

Sebességkorlátozás

Korlátozza, hogy egy kezelő milyen gyakran hajtható végre egy időablakon belül:

PHP
Queuety::dispatch( 'call_api', $payload )
    ->rate_limit( 10, 60 ); // max 10 executions per 60 seconds

Részletekért lásd: Sebességkorlátozás.

Indítható jobosztályok

A Queuety v0.6.0 osztályalapú job API rendszert vezet be. A kezelő nevének, a payloadnak és a kezelőosztálynak a külön tárolása helyett egyetlen, mindent összefogó osztályt definiál: ez tartalmazza a payloadot (típusos publikus tulajdonságokként), a végrehajtási logikát és az opcionális middleware-t.

A Contracts\Job interfész

PHP
use Queuety\Contracts\Job;

interface Job {
    public function handle(): void;
}

Egy Job osztály publikus tulajdonságokként tárolja a payloadját, és a saját logikáját a handle() metódusban hajtja végre. Nincs szükség külön config() metódusra vagy kezelőregisztrációra.

A Dispatchable trait

Adja hozzá a Dispatchable traitet, hogy statikus dispatch() metódus kerüljön a jobosztályba:

PHP
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public readonly string $to,
        public readonly string $subject,
        public readonly string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

Indítsa el konstruktorargumentumok megadásával:

PHP
SendEmailJob::dispatch( 'user@example.com', 'Welcome!', 'Hello there.' )
    ->on_queue( 'emails' )
    ->with_priority( Priority::High );

A Dispatchable trait belsőleg meghívja a Queuety::dispatch() metódust, ezért minden PendingJob beállítás (queue, priority, delay, max_attempts, unique, after) ugyanúgy működik.

A szerializálás működése

Egy Job példány indításakor a Queuety JobSerializer metódusa a teljesen minősített osztálynevet használja kezelőként, az összes publikus tulajdonságot pedig payloadként. A worker oldalán a szerializáló a payloadkulcsokat a konstruktor paraméterneveihez rendelve állítja vissza a példányt. A backed enumok az alapul szolgáló értékükre szerializálódnak, majd automatikusan visszaállításra kerülnek.

A feladat tulajdonságai

A jobosztályok deklarálhatnak publikus tulajdonságokat az újrapróbálkozások és az időtúllépés viselkedésének szabályozására. A worker reflexióval olvassa ki ezeket, és automatikusan alkalmazza őket.

PHP
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

class ImportProductsJob implements Job {
    use Dispatchable;

    public int $tries = 5;
    public int $timeout = 120;
    public array $backoff = [ 10, 30, 60, 120 ];
    public string $concurrency_group = 'imports';
    public int $concurrency_limit = 2;
    public int $cost_units = 4;

    public function __construct(
        public readonly int $supplier_id,
    ) {}

    public function handle(): void {
        // Import products...
    }
}
Tulajdonság Típus Leírás
$tries int A próbálkozások maximális száma, mielőtt a job a parkolóba kerül. Felülírja az indításkor megadott max_attempts értéket.
$timeout int Maximális végrehajtási idő másodpercben. Felülírja a globális QUEUETY_MAX_EXECUTION_TIME konstans értékét. pcntl szükséges hozzá, de még nincs érvényesítve (lásd: Időtúllépés).
$backoff array Késleltetési értékek tömbje az egyes újrapróbálkozásokhoz, másodpercben. A későbbi próbálkozások az utolsó értéket használják.
$concurrency_group string Megosztott workerfelvételi csoport költséges jobokhoz.
$concurrency_limit int A csoporton belüli, egyidejű processing jobok maximális száma. $concurrency_group nélkül figyelmen kívül marad.
$cost_units int Relatív végrehajtási költség a munkafolyamat-keretek és a workerfelvétel számára.

A $backoff tömb növekvő újrapróbálkozási késleltetéseket ad meg. Például a [10, 30, 60, 120] azt jelenti, hogy az első újrapróbálkozás 10 másodpercet, a második 30 másodpercet, a harmadik 60 másodpercet vár, a további próbálkozások pedig 120 másodpercet.

Az erőforrással kapcsolatos tulajdonságok akkor hasznosak, ha a jobosztályok eltérő költségprofilokat képviselnek. Egy gyors gyorsítótár-frissítés és egy nagy szolgáltatói hívás egyaránt lehet „egy job”, de nem feltétlenül kell azonos súllyal számítaniuk, amikor a munkafolyamat-keret vagy a workerfelvétel célja a folyamat biztonságos keretek között tartása.

A teljes modellért, beleértve a munkafolyamat-kereteket és a workeroldali felvételt, lásd: Erőforrás-kezelés.

Sikertelen hook

Ha a job az összes újrapróbálkozási kísérlet kimerítése után a parkolóba kerül, a Queuety meghívja a jobpéldány failed() metódusát, ha az definiálva van. Használja takarításhoz, riasztáshoz vagy naplózáshoz.

PHP
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

class ProcessPaymentJob implements Job {
    use Dispatchable;

    public int $tries = 3;

    public function __construct(
        public readonly int $order_id,
    ) {}

    public function handle(): void {
        // Process the payment...
    }

    public function failed( \Throwable $exception ): void {
        // Notify the team that payment processing failed permanently.
        error_log( "Payment failed for order {$this->order_id}: {$exception->getMessage()}" );
    }
}

A failed() metódus megkapja a végleges hibát okozó kivételt. A jobpéldány az eredeti payloaddal szerializálódik vissza, így minden publikus tulajdonság elérhető.

Feltételes indítás

A Dispatchable trait a feltételes indításhoz a dispatch_if() és a dispatch_unless() metódust biztosítja. Mindkettő első argumentuma egy logikai feltétel, amelyet a job konstruktorának argumentumai követnek.

PHP
// Only dispatch if the user has opted in to notifications.
SendEmailJob::dispatch_if( $user->wants_notifications, $user->email, 'Update', $body );

// Dispatch unless the feature flag is disabled.
SyncInventoryJob::dispatch_unless( $maintenance_mode, $sku );

A dispatch_if() akkor indítja el a jobot, ha a feltétel true, és a PendingJob értéket adja vissza. Ha a feltétel false, akkor null értéket ad vissza.

A dispatch_unless() akkor indítja el a jobot, ha a feltétel false, és a PendingJob értéket adja vissza. Ha a feltétel true, akkor null értéket ad vissza.

Mindkét metódus támogatja a PendingJob beállítások láncolását indításkor:

PHP
SendEmailJob::dispatch_if( $should_send, $to, $subject, $body )
    ?->on_queue( 'emails' )
    ?->with_priority( Priority::High );

Szinkron indítás

A Queuety::dispatch_sync() használatával a jobot azonnal, a jelenlegi folyamatban hajthatja végre anélkül, hogy hozzáadná a sorhoz. Ez teszteléshez és olyan jobokhoz hasznos, amelyeket közvetlenül kell futtatni.

PHP
use Queuety\Queuety;

// With a Job instance
Queuety::dispatch_sync( new SendEmailJob( to: 'user@example.com', subject: 'Hello', body: 'Hi!' ) );

// With a handler name and payload
Queuety::dispatch_sync( 'send_email', [ 'to' => 'user@example.com' ] );

A feladat handle() metódusa közvetlenül hívódik meg. Nem jön létre adatbázissor, nincs szükség munkásra, és a köztes szoftverek sem futnak le.

Jobok láncolása

A jobok láncolása egymás után hajt végre egy sorozatot. A lánc minden jobja az előző job sikeres befejezésétől függ. Ha bármelyik job meghiúsul, a lánc további jobjai függőben maradnak.

A Queuety::chain() használata

PHP
use Queuety\Queuety;

$first_job_id = Queuety::chain( [
    new FetchDataJob( $url ),
    new ProcessDataJob(),
    new NotifyCompleteJob(),
] )
    ->on_queue( 'pipeline' )
    ->catch( ChainFailedHandler::class )
    ->dispatch();

A Queuety::chain() egy ChainBuilder objektumot ad vissza, amely folyékony metódusokat biztosít a sor beállításához és egy hibakezelő megadásához. A dispatch() metódus minden jobot egymást követő depends_on kapcsolatokkal hoz létre, és az első job ID-ját adja vissza.

A with_chain() használata

A Dispatchable trait egy with_chain() metódust biztosít. Ez jelenleg egyenértékű a Queuety::chain( $jobs ) metódussal: a hívás címzettje nem kerül be a láncba (#13), ezért az első jobot is sorolja fel a tömbben:

PHP
FetchDataJob::with_chain( [
    new FetchDataJob(),
    new ProcessDataJob(),
    new NotifyCompleteJob(),
] )
    ->on_queue( 'pipeline' )
    ->dispatch();

Lánchibák kezelése

Regisztráljon hibakezelő osztályt a catch() használatával. Az osztálynak rendelkeznie kell handle() metódussal. Ez akkor hívódik meg, amikor a lánc bármelyik jobja véglegesen a parkolóba kerül. A worker a következőket támogatja: handle(), handle( Job $job ) és handle( Job $job, \Throwable $exception ).

PHP
class ChainFailedHandler {
    public function handle(): void {
        // Alert, clean up, etc.
    }
}

Middleware hozzáadása

A jobosztályok definiálhatnak egy middleware() metódust, amely a végrehajtást körülvevő middleware-t ad vissza:

PHP
use Queuety\Contracts\Job;
use Queuety\Dispatchable;
use Queuety\Middleware\RateLimited;
use Queuety\Middleware\Timeout;

class CallOpenAIJob implements Job {
    use Dispatchable;

    public function __construct(
        public readonly string $prompt,
    ) {}

    public function handle(): void {
        // Call the API...
    }

    public function middleware(): array {
        return [
            new RateLimited( max: 60, window: 60 ),
            new Timeout( seconds: 120 ),
        ];
    }
}

A beépített middleware-ekről és az egyéni middleware írásáról lásd: Middleware.

Összehasonlítás a kezelőalapú jobokkal

Kezelőalapú (v0.1+) Osztályalapú (v0.6+)
Elküldés Queuety::dispatch( 'send_email', $payload ) SendEmailJob::dispatch( $to, $subject )
Kezelő Külön osztály, amely megvalósítja a(z) Handler interfészt Ugyanaz az osztály valósítja meg a(z) Contracts\Job interfészt
Adattartalom Típus nélküli array $payload Típusos nyilvános tulajdonságok
Regisztráció Queuety::register() vagy #[QueuetyHandler] Nem szükséges (FQCN-t használ)
Köztesréteg Nem érhető el Választható middleware() metódus
Konfiguráció config() metódus Feladattulajdonságok + PendingJob lánc

Mindkét megközelítés teljes mértékben támogatott. A meglévő, kezelőalapú feladatok változtatás nélkül tovább működnek. A két stílust ugyanabban a projektben is vegyítheti.

A feladat életciklusa

Kód
dispatch() -> pending -> processing -> completed
                  |           |
                  |           +-> exception -> pending (retry after backoff)
                  |                       |
                  |                       +-> buried (max attempts reached)
                  |
                  +-> delayed (available_at in the future)
Állapot Leírás
pending Arra vár, hogy egy feldolgozó lefoglalja
processing Végrehajtás alatt áll
completed Sikeresen befejeződött
failed Fenntartott állapot; a feldolgozó jelenleg nem állítja be. A sikertelen, újrapróbálandó kísérlet visszakerül a(z) pending állapotba
buried Az összes újrapróbálkozás elfogyott