
## Flujos de trabajo en un solo archivo

Un flujo de trabajo puede estar completamente contenido en un único archivo PHP. Defina las clases de pasos y el constructor en el mismo archivo, colóquelo en un directorio y cargue ese directorio con `Queuety::load_workflows()` (como se muestra abajo). Queuety no explora ningún directorio por sí solo.

```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');
```

El archivo devuelve un `WorkflowBuilder`. Cada clase de paso se define en línea. Al cargar el archivo, las clases quedan disponibles y el flujo de trabajo se registra como plantilla.

## Cargar flujos de trabajo

Cargue todos los archivos de flujos de trabajo de un directorio:

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

O cargue un solo archivo:

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

Después, despache por nombre:

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

## Carga recursiva

Pase `true` como segundo argumento para explorar los subdirectorios:

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

Esto permite organizar los flujos de trabajo en carpetas:

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

## Usar todas las funciones de los flujos de trabajo

Los flujos de trabajo en archivos admiten todo lo que admite el constructor, excepto `idempotency_key()`, que no se almacena en la plantilla; páselo en cada despacho con `Queuety::run_workflow( $name, $payload, [ 'idempotency_key' => '...' ] )`. Las demoras, las señales, los pasos paralelos, las ramificaciones condicionales, la ejecución de flujos de trabajo, los controladores de cancelación y la poda del estado funcionan:

```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);
```

## Cuándo usar flujos de trabajo en archivos

Los flujos de trabajo en archivos son ideales cuando:

- Un LLM o generador de código crea flujos de trabajo mediante programación
- Un flujo de trabajo es lo bastante sencillo como para caber en un archivo
- Quiere mantener la lógica de los pasos cerca de la definición del flujo de trabajo
- Está creando un prototipo y quiere iterar rápidamente

Para flujos de trabajo más grandes con clases de pasos compartidas, middleware complejo o pasos reutilizados en varios flujos de trabajo, resulta más fácil de mantener el enfoque estándar de usar archivos de clase separados con carga automática PSR-4.

## Cómo funciona

Internamente, los flujos de archivos usan exactamente el mismo motor que el generador API. Cada paso es un trabajo independiente en la base de datos. El estado se transmite a través de la tabla `queuety_workflows`. No hay repetición, no se exige determinismo ni hay diferencias de rendimiento.

Cada llamada a load `require` el archivo (no `require_once`), así que carga cada archivo una vez por solicitud; si lo cargas dos veces, se vuelven a declarar sus clases y se produce un error. El `WorkflowBuilder` devuelto se convierte en `WorkflowTemplate` y se almacena en `WorkflowRegistry`. El envío y la ejecución son idénticos a los de cualquier otro flujo de trabajo.
