Sinyal Alur Kerja
Alur kerja dapat dijeda dan menunggu input eksternal menggunakan sinyal. Metode builder wait_for_signal() dan wait_for_signals() menyisipkan langkah yang memblokir alur kerja hingga aplikasi Anda, operator, atau sistem lain mengirim sinyal yang diharapkan melalui Queuety::signal().
Untuk alur kerja yang melibatkan manusia, Queuety juga mencakup:
wait_for_approval()untuk payload persetujuan dengan namespacewait_for_input()untuk input manusia yang terstrukturwait_for_decision()untuk hasil setuju/tolak yang eksplisit
Untuk contoh menyeluruh yang lebih besar, yang menggabungkan eksekusi agen dengan gerbang tinjauan manusia, lihat Orkestrasi Agen.
Metode ->wait_for_signal()
Tambahkan langkah penantian sinyal ke alur kerja:
use Queuety\Queuety;
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Saat alur kerja mencapai langkah wait_for_signal, statusnya diatur menjadi waiting_for_signal dan alur kerja dijeda. Tidak ada tugas yang berjalan dan tidak ada sumber daya yang digunakan selama menunggu.
Secara default, satu payload sinyal digabungkan ke status alur kerja tingkat teratas. Jika Anda ingin payload diberi namespace, berikan result_key:
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved', 'approval' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Setelah sinyal tiba, $state['approval'] berisi array payload sinyal.
Menunggu beberapa sinyal
Gunakan wait_for_signals() saat alur kerja harus dilanjutkan setelah salah satu dari beberapa sinyal yang mungkin diterima, atau saat semua sinyal yang diperlukan harus dikumpulkan sebelum melanjutkan.
use Queuety\Enums\WaitMode;
$workflow_id = Queuety::workflow( 'moderation_gate' )
->then( SubmitForReviewHandler::class )
->wait_for_signals(
[ 'editor_approved', 'legal_approved' ],
WaitMode::All,
'approvals'
)
->then( PublishContentHandler::class )
->dispatch();
WaitMode::Allmenunggu hingga setiap sinyal yang dikonfigurasi tercatat.WaitMode::Anydilanjutkan segera setelah sinyal pertama yang dikonfigurasi tiba.
Dengan result_key, penantian multi-sinyal menyimpan array asosiatif dengan nama sinyal sebagai kuncinya:
[
'editor_approved' => [ 'by' => 'editor@example.com' ],
'legal_approved' => [ 'by' => 'legal@example.com' ],
]
Tanpa result_key, payload sinyal yang cocok digabungkan ke status tingkat teratas sesuai urutan konfigurasi langkah.
Pencocokan dan korelasi
Penantian sinyal dapat mengabaikan peristiwa yang tidak terkait dengan mencocokkan konten payload atau mengorelasikannya berdasarkan kunci bersama.
$workflow_id = Queuety::workflow( 'review_gate' )
->wait_for_signal(
name: 'review_ready',
result_key: 'review',
match_payload: [ 'source' => 'editorial' ],
correlation_key: 'task_id',
)
->dispatch( [ 'task_id' => 'task-42' ] );
Dalam contoh tersebut, penantian hanya dilanjutkan jika:
- nama sinyalnya adalah
review_ready - payload berisi
source: editorial - payload
task_idcocok dengan$state['task_id']
Ini berguna ketika beberapa sistem eksternal atau agen menerbitkan nama peristiwa yang sama, tetapi hanya satu payload yang terkait dengan eksekusi alur kerja saat ini.
Helper persetujuan dan input manusia
wait_for_approval() dan wait_for_input() adalah pembungkus praktis untuk penantian sinyal. Keduanya berperilaku seperti wait_for_signal(), tetapi secara default menggunakan kunci hasil dengan namespace.
$workflow_id = Queuety::workflow( 'blog_review' )
->then( GenerateDraftHandler::class )
->wait_for_approval()
->wait_for_input()
->then( HandleDecisionHandler::class )
->dispatch();
Setelah sinyal approval, $state['approval'] berisi payload persetujuan. Setelah sinyal input, $state['input'] berisi payload input.
Gunakan wait_for_decision() jika Anda ingin satu langkah dilanjutkan saat menerima persetujuan atau penolakan:
$workflow_id = Queuety::workflow( 'legal_review' )
->then( DraftContractHandler::class )
->wait_for_decision( result_key: 'review' )
->then( HandleReviewDecisionHandler::class )
->dispatch();
Setelah sinyal tiba, $state['review'] berisi:
[
'outcome' => 'approved', // or 'rejected'
'signal' => 'approved', // or 'rejected'
'data' => [ 'reviewer' => 'ops@example.com' ],
]
Mengirim sinyal
Kirim sinyal ke alur kerja menggunakan Queuety::signal():
Queuety::signal( $workflow_id, 'approved' );
Saat sinyal cocok dengan sinyal yang sedang ditunggu alur kerja, alur kerja dilanjutkan dan berpindah ke langkah berikutnya.
Untuk alur kerja yang melibatkan manusia, facade juga menyediakan helper semantik:
Queuety::approve_workflow( $workflow_id, [ 'reviewer' => 'editor@example.com' ] );
Queuety::reject_workflow( $workflow_id, [ 'reason' => 'needs citations' ] );
Queuety::submit_workflow_input( $workflow_id, [ 'notes' => 'Ship after copy edit' ] );
Data sinyal
Anda dapat mengirim array data bersama sinyal. Data tersebut digabungkan ke status alur kerja sehingga tersedia untuk langkah-langkah berikutnya:
Queuety::signal( $workflow_id, 'approved', [
'approved_by' => 'admin@example.com',
'approved_at' => time(),
] );
Pada langkah berikutnya:
class PublishContentHandler implements Step {
public function handle( array $state ): array {
// $state['approved_by'] is 'admin@example.com'
// $state['approved_at'] is the timestamp
// $state['post_id'] is 99
wp_update_post( [
'ID' => $state['post_id'],
'post_status' => 'publish',
] );
return [ 'published' => true ];
}
public function config(): array {
return [];
}
}
Kunci yang diawali dengan _ (garis bawah) dicadangkan untuk penggunaan internal dan tidak digabungkan ke dalam status.
Sinyal yang sudah ada
Sinyal dapat dikirim sebelum alur kerja mencapai langkah penantian. Saat sinyal tiba, sinyal dicatat di tabel queuety_signals tanpa memedulikan status alur kerja saat itu. Ketika alur kerja kemudian mencapai langkah wait_for_signal, alur kerja memeriksa sinyal yang sudah ada dan langsung melanjutkan jika menemukannya.
Artinya, urutannya tidak menjadi masalah:
// Dispatch workflow
$workflow_id = Queuety::workflow( 'order_fulfillment' )
->then( PrepareOrderHandler::class )
->wait_for_signal( 'payment_confirmed' )
->then( ShipOrderHandler::class )
->dispatch( [ 'order_id' => 123 ] );
// Signal arrives before the workflow reaches the wait step
Queuety::signal( $workflow_id, 'payment_confirmed', [ 'transaction_id' => 'txn_abc' ] );
// When the workflow finishes PrepareOrderHandler and reaches the wait step,
// it sees the pre-existing signal and continues immediately.
Status alur kerja selama menunggu sinyal
Saat menunggu sinyal, status alur kerja adalah WorkflowStatus::WaitingForSignal (waiting_for_signal):
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value; // 'waiting_for_signal'
echo $state->wait_type; // 'signal'
echo $state->wait_mode; // 'all' or 'any'
print_r( $state->waiting_for ); // ['approved']
print_r( $state->wait_details ); // matched/remaining, correlation info, result key, ...
Kasus penggunaan: persetujuan manusia
Buat alur persetujuan ketika peninjau manusia harus menyetujui konten sebelum ditayangkan:
$workflow_id = Queuety::workflow( 'blog_review' )
->then( GenerateDraftHandler::class )
->then( NotifyReviewerHandler::class )
->wait_for_decision( result_key: 'review' )
->then( HandleDecisionHandler::class )
->dispatch( [ 'topic' => 'PHP middleware patterns' ] );
NotifyReviewerHandler mengirim email atau pesan Slack dengan tautan setujui/tolak. Tautan tersebut memanggil controller Anda, yang mengirim sinyal:
// In your approval controller
Queuety::approve_workflow(
$workflow_id,
[
'reviewer' => $current_user->user_email,
'reviewed_at' => time(),
],
'approved'
);
Langkah HandleDecisionHandler membaca $state['review']['outcome'] lalu menerbitkan atau mengarsipkan draf.
Kasus penggunaan: callback API eksternal
Tunggu webhook dari layanan eksternal:
$workflow_id = Queuety::workflow( 'generate_video' )
->then( SubmitToRenderServiceHandler::class )
->wait_for_signal( 'render_complete' )
->then( DownloadVideoHandler::class )
->then( NotifyUserHandler::class )
->dispatch( [ 'template_id' => 'promo_v2', 'user_id' => 42 ] );
Saat layanan eksternal mengirim permintaan ke endpoint webhook Anda:
// In your webhook handler
$payload = json_decode( file_get_contents( 'php://input' ), true );
$workflow_id = (int) $payload['metadata']['workflow_id'];
Queuety::signal( $workflow_id, 'render_complete', [
'video_url' => $payload['output_url'],
'duration' => $payload['duration_seconds'],
] );
Beberapa gerbang sinyal dalam satu alur kerja
Alur kerja dapat menunggu sinyal di beberapa titik:
Queuety::workflow( 'multi_approval' )
->then( CreateProposalHandler::class )
->wait_for_signal( 'manager_approval' )
->then( EscalateToDirectorHandler::class )
->wait_for_signal( 'director_approval' )
->then( ExecuteProposalHandler::class )
->dispatch( [ 'proposal_id' => 7 ] );
Setiap langkah penantian sinyal berdiri sendiri. Anda dapat menggabungkan wait_for_signal(), wait_for_signals(), wait_for_approval(), wait_for_input(), dan wait_for_decision() dalam alur kerja yang sama.