
## Alur kerja satu file

Alur kerja dapat sepenuhnya mandiri dalam satu file PHP. Definisikan kelas langkah dan builder bersama-sama, letakkan file di sebuah direktori, lalu muat direktori tersebut dengan `Queuety::load_workflows()` (ditunjukkan di bawah). Queuety tidak memindai direktori apa pun dengan sendirinya.

```php
// workflows/onboard-user.php
use Queuety\Queuety;

class CreateAccount implements \Queuety\Step {
    public function handle(array $state): array {
        $user = create_user($state['email']);
        return ['user_id' => $user->id, 'user_name' => $user->name];
    }
    public function config(): array {
        return ['max_attempts' => 3];
    }
}

class SendWelcome implements \Queuety\Step {
    public function handle(array $state): array {
        wp_mail($state['email'], 'Welcome ' . $state['user_name'], '...');
        return ['welcomed' => true];
    }
    public function config(): array {
        return [];
    }
}

return Queuety::define_workflow('onboard_user')
    ->then(CreateAccount::class, 'create_account')
    ->then(SendWelcome::class, 'send_welcome');
```

File tersebut mengembalikan `WorkflowBuilder`. Setiap kelas langkah didefinisikan secara inline. Saat file dimuat, kelas-kelas itu tersedia dan alur kerja didaftarkan sebagai templat.

## Memuat alur kerja

Muat semua file alur kerja dari sebuah direktori:

```php
// Load all .php files from the workflows directory
$count = Queuety::load_workflows(__DIR__ . '/workflows/');
```

Atau muat satu file:

```php
$template = Queuety::load_workflow_file(__DIR__ . '/workflows/onboard-user.php');
```

Lalu jalankan berdasarkan nama:

```php
$workflow_id = Queuety::run_workflow('onboard_user', ['email' => 'user@example.com']);
```

## Pemuatan rekursif

Berikan `true` sebagai argumen kedua untuk memindai subdirektori:

```php
Queuety::load_workflows(__DIR__ . '/workflows/', recursive: true);
```

Ini memungkinkan pengorganisasian alur kerja ke dalam folder:

```
workflows/
├── onboarding/
│   ├── new-user.php
│   └── trial-upgrade.php
├── reports/
│   ├── daily-summary.php
│   └── weekly-digest.php
└── notifications/
    └── digest-email.php
```

## Menggunakan semua fitur alur kerja

Alur kerja berkas mendukung semua yang didukung builder, kecuali `idempotency_key()`, yang tidak disimpan dalam templat; berikan per dispatch dengan `Queuety::run_workflow( $name, $payload, [ 'idempotency_key' => '...' ] )`. Penundaan, sinyal, langkah paralel, percabangan bersyarat, run-workflows, handler pembatalan, dan pemangkasan status semuanya berfungsi:

```php
// workflows/approval-flow.php
use Queuety\Queuety;

class SubmitRequest implements \Queuety\Step {
    public function handle(array $state): array {
        return ['submitted_at' => date('Y-m-d H:i:s')];
    }
    public function config(): array { return []; }
}

class ProcessApproval implements \Queuety\Step {
    public function handle(array $state): array {
        return [
            'approved_by' => $state['approved_by'],
            'processed' => true,
        ];
    }
    public function config(): array { return []; }
}

class CleanupRequest implements \Queuety\Handler {
    public function handle(array $payload): void {
        delete_pending_request($payload['request_id']);
    }
    public function config(): array { return []; }
}

return Queuety::define_workflow('approval_flow')
    ->then(SubmitRequest::class)
    ->delay(hours: 24)
    ->wait_for_signal('approved')
    ->then(ProcessApproval::class)
    ->on_cancel(CleanupRequest::class)
    ->prune_state_after(2);
```

## Kapan menggunakan alur kerja berkas

Alur kerja berkas ideal ketika:

- LLM atau generator kode membuat alur kerja secara terprogram
- Alur kerja cukup sederhana untuk dimuat dalam satu file
- Anda ingin menjaga logika langkah tetap dekat dengan definisi alur kerja
- Anda sedang membuat prototipe dan menginginkan iterasi cepat

Untuk alur kerja yang lebih besar dengan kelas langkah bersama, middleware kompleks, atau langkah yang digunakan ulang di beberapa alur kerja, pendekatan standar dengan file kelas terpisah dan autoloading PSR-4 lebih mudah dipelihara.

## Cara kerjanya

Di balik layar, alur kerja berkas menggunakan mesin yang sama persis dengan builder API. Setiap langkah adalah tugas terpisah di basis data. Status mengalir melalui tabel `queuety_workflows`. Tidak ada replay, persyaratan determinisme, atau perbedaan performa.

Setiap pemanggilan load `require` file (bukan `require_once`), jadi muat setiap file sekali per permintaan; memuatnya dua kali akan mendeklarasikan ulang kelasnya dan gagal. `WorkflowBuilder` yang dikembalikan dikonversi menjadi `WorkflowTemplate` dan disimpan di `WorkflowRegistry`. Dispatch dan eksekusinya sama seperti alur kerja lainnya.
