Lanțuri secvențiale
Cel mai frecvent model de flux de lucru este un lanț liniar de pași. Fiecare pas rulează după finalizarea celui anterior, iar starea acumulată este transmisă mai departe.
Metoda ->then()
Folosiți ->then() pentru a adăuga pași secvențiali la un flux de lucru:
use Queuety\Queuety;
Queuety::workflow( 'onboarding' )
->then( CreateAccountHandler::class )
->then( SendWelcomeEmailHandler::class )
->then( NotifyAdminHandler::class )
->dispatch( [ 'email' => 'user@example.com' ] );
Pașii se execută în ordinea în care sunt adăugați. Fluxul de lucru avansează numai după finalizarea cu succes a pasului curent.
Interfața Step
Gestionarii pașilor fluxului de lucru implementează interfața Queuety\Step:
use Queuety\Step;
class CreateAccountHandler implements Step {
public function handle( array $state ): array {
$user_id = wp_create_user( $state['email'], wp_generate_password() );
return [ 'user_id' => $user_id ];
}
public function config(): array {
return [
'max_attempts' => 3,
];
}
}
Diferențe importante față de interfața Handler:
Handler (joburi) |
Step (fluxuri de lucru) |
|
|---|---|---|
| Semnătura metodei | handle(array $payload): void |
handle(array $state): array |
| Intrare | Datele jobului | Starea acumulată a fluxului de lucru |
| Ieșire | Nimic (void) | Date de îmbinat în stare |
Fluxul stării
Fiecare pas primește întreaga stare acumulată și returnează o listă de perechi cheie-valoare noi. Datele returnate sunt îmbinate în stare pentru pașii următori:
class FetchUserHandler implements Step {
public function handle( array $state ): array {
// $state contains: ['user_id' => 42]
$user = get_user_by( 'ID', $state['user_id'] );
return [ 'user_name' => $user->display_name, 'user_email' => $user->user_email ];
}
public function config(): array {
return [];
}
}
class GenerateReportHandler implements Step {
public function handle( array $state ): array {
// $state contains: ['user_id' => 42, 'user_name' => 'Alice', 'user_email' => 'alice@example.com']
$report = build_report( $state['user_name'] );
return [ 'report_url' => $report->url ];
}
public function config(): array {
return [];
}
}
Configurarea pașilor
Metoda config() acceptă următoarele chei:
| Cheie | Tip | Valoare implicită | Descriere |
|---|---|---|---|
max_attempts |
int |
3 |
Numărul maxim de încercări pentru acest pas |
backoff |
string |
exponential |
Strategia de așteptare între reîncercări |
Exemplu de flux LLM
Un caz de utilizare obișnuit este înlănțuirea apelurilor LLM API cu procesarea datelor:
use Queuety\Step;
class BuildPromptHandler implements Step {
public function handle( array $state ): array {
$user = get_user_by( 'ID', $state['user_id'] );
$posts = get_posts( [ 'author' => $user->ID, 'numberposts' => 10 ] );
$context = implode( "\n", array_map( fn( $p ) => $p->post_content, $posts ) );
return [
'prompt' => "Summarize this author's recent work:\n\n{$context}",
];
}
public function config(): array {
return [];
}
}
class CallOpenAIHandler implements Step {
public function handle( array $state ): array {
$response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
'timeout' => 120,
'headers' => [
'Authorization' => 'Bearer ' . OPENAI_API_KEY,
'Content-Type' => 'application/json',
],
'body' => json_encode( [
'model' => 'gpt-4',
'messages' => [ [ 'role' => 'user', 'content' => $state['prompt'] ] ],
] ),
] );
$body = json_decode( wp_remote_retrieve_body( $response ), true );
return [ 'summary' => $body['choices'][0]['message']['content'] ];
}
public function config(): array {
return [ 'max_attempts' => 5 ];
}
}
class SaveSummaryHandler implements Step {
public function handle( array $state ): array {
$post_id = wp_insert_post( [
'post_title' => "Summary for user #{$state['user_id']}",
'post_content' => $state['summary'],
'post_status' => 'publish',
] );
return [ 'summary_post_id' => $post_id ];
}
public function config(): array {
return [];
}
}
Porniți fluxul:
Queuety::workflow( 'summarize_author' )
->then( BuildPromptHandler::class )
->then( CallOpenAIHandler::class )
->then( SaveSummaryHandler::class )
->on_queue( 'llm' )
->max_attempts( 5 )
->dispatch( [ 'user_id' => 42 ] );
Dacă apelul OpenAI expiră, lucrătorul reîncearcă doar acel pas. Promptul creat la pasul 0 este deja stocat în siguranță în starea fluxului de lucru.