Belajar RoadRunner - Temporal Workflow Plugin
Episode 19 of 26

Belajar RoadRunner - Temporal Workflow Plugin

Mengintegrasikan Temporal ke RoadRunner untuk durable execution: memahami konsep workflow dan activity, menulis workflow PHP dengan SDK Temporal, mengonfigurasi plugin temporal, dan membangun contoh sistem order-payment yang tahan kegagalan.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 18 kita mengelola dependensi, pada episode kali ini kita masuk ke puncak ekosistem: Temporal workflow plugin. Queue biasa (episode 11) memproses satu job yang berjalan beberapa menit. Tapi bagaimana dengan proses bisnis yang berlangsung berhari-hari — order menunggu pembayaran, kemudian verifikasi, lalu pengiriman — dan harus selamat dari server crash di tengah jalan? Itulah masalah yang dipecahkan Temporal.

Mengapa episode ini penting? Karena durable execution adalah pembeda RoadRunner dari app server lain: bukan sekadar menjalankan PHP lebih cepat, tetapi mengeksekusi proses bisnis yang tidak akan pernah kehilangan state meski mesin mati. Ini yang membuat RoadRunner cocok untuk sistem transaksional nyata.

Konsep Temporal: Workflow, Activity, Durable Execution

Temporal adalah platform durable execution. Tiga konsep intinya:

100%
KonsepArti
WorkflowOrkestrasi langkah-langkah — kode yang mencatat setiap keputusan
ActivityEksekusi aktual (memanggil API, mengirim email, menulis DB)
Durable executionState workflow tersimpan di Temporal server; crash tidak menghapus progres
WorkerProses yang menjalankan workflow/activity — di sini, worker RoadRunner

Keajaibannya: jika server mati di tengah Activity, Temporal server mengingat posisinya dan melanjutkan saat worker hidup lagi — tanpa kehilangan state.

Setup Plugin Temporal

Blok temporal
temporal:
  address: 127.0.0.1:7233
  activities:
    num_workers: 4
    max_worker_memory: 128
  codec: json
  cache_size: 512
KeyFungsi
addressAlamat Temporal server
activitiesPool worker untuk menjalankan workflow/activity
codecEncoding payload (json/proto)
cache_sizeCache workflow context per worker

Worker PHP Temporal memakai package spiral/roadrunner-temporal:

Install package Temporal
composer require spiral/roadrunner-temporal temporal/sdk

Activity adalah pekerjaan aktual. Contoh untuk sistem order-payment:

OrderActivities.php
<?php
 
declare(strict_types=1);
 
use Temporal\Activity\ActivityInterface;
use Temporal\Activity\ActivityMethod;
 
#[ActivityInterface(prefix: 'order')]
final class OrderActivities
{
    #[ActivityMethod(name: 'CreateOrder')]
    public function createOrder(array $data): string
    {
        // Simpan order ke DB, kembalikan order id
        return $this->db->insert('orders', $data);
    }
 
    #[ActivityMethod(name: 'VerifyPayment')]
    public function verifyPayment(string $orderId): bool
    {
        return $this->paymentProvider->check($orderId);
    }
 
    #[ActivityMethod(name: 'SendConfirmation')]
    public function sendConfirmation(string $orderId, string $email): void
    {
        $this->mailer->send($email, 'Konfirmasi Order ' . $orderId);
    }
}

Setiap activity sebaiknya idempoten (bisa diulang tanpa efek ganda) — Temporal dapat mengulang activity saat worker restart.

Workflow mengorkestrasi activity. Workflow PHP adalah kelas dengan atribut:

OrderWorkflow.php
<?php
 
declare(strict_types=1);
 
use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;
use Temporal\Workflow\Workflow;
 
#[WorkflowInterface]
final class OrderWorkflow
{
    #[WorkflowMethod(name: 'OrderFlow')]
    public function run(array $order): array
    {
        $orderId = yield Workflow::executeActivity(
            OrderActivities::class . '::CreateOrder',
            $order,
        );
 
        // Tunggu pembayaran — bisa berjam-jam, tahan terhadap restart
        $paid = yield Workflow::executeActivity(
            OrderActivities::class . '::VerifyPayment',
            $orderId,
        );
 
        if (!$paid) {
            yield Workflow::executeActivity(
                OrderActivities::class . '::SendConfirmation',
                $orderId,
                $order['email'],
            );
 
            return ['status' => 'pending', 'order_id' => $orderId];
        }
 
        yield Workflow::executeActivity(
            OrderActivities::class . '::SendConfirmation',
            $orderId,
            $order['email'],
        );
 
        return ['status' => 'confirmed', 'order_id' => $orderId];
    }
}

Aturan emas workflow: jangan pernah memanggil I/O langsung di dalam workflow — semua efek samping harus lewat activity. Workflow harus deterministic, karena setiap eksekusi ulang (replay) harus menghasilkan keputusan yang sama. Hanya activity yang boleh berinteraksi dengan dunia luar.

Warning

Hindari time(), rand(), koneksi DB, atau HTTP langsung di dalam workflow. RoadRunner + Temporal me-replay logika workflow untuk memulihkan state; kode nondeterministik akan membuat replay menghasilkan hasil berbeda — sumber bug yang sangat sulit dilacak.

Menjalankan Worker dan Memulai Workflow

Daftarkan workflow/activity di worker:

temporal-worker.php
use Spiral\RoadRunner\Temporal\TemporalWorker;
use Temporal\WorkerFactory;
 
$worker = WorkerFactory::create();
 
$worker->registerWorkflowTypes(OrderWorkflow::class);
$worker->registerActivityImplementations(new OrderActivities($db));
 
$factory = TemporalWorker::create($worker);
$factory->run();

Memulai workflow dari aplikasi (misal setelah checkout):

Mulai workflow dari PHP
use Temporal\Client\WorkflowClient;
 
$client = WorkflowClient::create();
$handle = $client->newWorkflowStub(OrderWorkflow::class);
$promise = $client->start($handle, ['email' => 'user@example.com', 'total' => 150000]);

Kapan Memakai Temporal vs Queue Biasa

KebutuhanQueue (ep. 11)Temporal
Pekerjaan sekali jalan dalam detik-menitYaBerlebihan
Proses multi-langkah dengan state antar langkahSulitIdeal
Menunggu kondisi eksternal berjam-jam/hariManualBawaan
Retry dan sagasManualBawaan
Timeline/audit eksekusiTidakYa

Penutup

Pada episode 19 ini, kalian telah membuka kekuatan durable execution.

Inti yang harus dibawa pulang:

  • Temporal = durable execution: state workflow tersimpan, tahan crash.
  • Workflow mengorkestrasi; Activity mengeksekusi efek samping.
  • Workflow harus deterministic — I/O hanya di activity.
  • Plugin temporal mengelola worker; SDK PHP menulis workflow/activity.
  • Cocok untuk proses bisnis multi-langkah: order, payment, approval.

Di episode 20 selanjutnya, kita belajar worker pool tuning & performance — menyetel num_workers, max_jobs, max_worker_memory, supervisor, opcache dan JIT, lalu membandingkan RoadRunner dengan PHP-FPM dan FrankenPHP. Sampai jumpa di episode 20!

Belajar RoadRunner - Temporal Workflow Plugin | Belajar RoadRunner