Chaos: arnés determinista para escenarios de resiliencia
De un vistazo
Sección titulada «De un vistazo»El módulo Chaos es un pequeño arnés para pruebas de resiliencia. Permite registrar escenarios de inyección de fallos que implementan una interfaz de un solo método, ejecutarlos y recopilar un informe estructurado con resultados pass/fail. Es deliberadamente minimalista —cinco clases— y está pensado para suites de resiliencia y ejercicios de día de caos, no para la ruta de producción de documentos.
Estabilidad: experimental. Esta es una superficie de utilidades de prueba y resiliencia, no una API PDF del núcleo. La SPI es pequeña y estable en su forma, pero el alcance del módulo y los escenarios incluidos evolucionan. No construir flujos de control de producción sobre ella.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Descripción conceptual
Sección titulada «Descripción conceptual»Una prueba de resiliencia plantea una pregunta: cuando una dependencia falla, ¿el motor se degrada correctamente? El módulo Chaos aporta estructura a esa prueba. ChaosScenarioInterface es el contrato que implementa un escenario: un name() y un simulate() que devuelve un ChaosOutcome. Un escenario encapsula un único fallo (una partición de red, una ráfaga de respuestas 5xx del backend de recuperación) e informa de lo ocurrido.
ChaosScenarioRunner es el orquestador. Se registran escenarios con register(), se llama a run() para ejecutarlos secuencialmente en orden de registro y se consulta el agregado resultante: outcomes(), allPassed(), passCount(), failCount(). El ejecutor nunca lanza una excepción ante el fallo de un escenario: un fallo es un dato capturado en un ChaosOutcome, no una excepción. Solo lanza una excepción cuando falla su propia infraestructura: un registro de escenario no válido, o la imposibilidad de escribir el archivo de informe (ChaosReportWriteException). Un escenario que no puede alcanzar el recurso que está probando expone una RetrievalUnavailableException. Todo el módulo es @since 3.2.0.
ChaosOutcome es el resultado de cada escenario: pass/fail, una duración y un toArray() para el informe estructurado. Como un resultado registra la duración de reloj de pared, el perfil de reproducibilidad del informe es structural, no bitwise.
Superficie de API
Sección titulada «Superficie de API»| Tipo | Miembros clave | Función |
|---|---|---|
ChaosScenarioInterface | name(): string, simulate(): ChaosOutcome | El contrato del escenario (@since 3.2.0) |
ChaosScenarioRunner | register(), run(), outcomes(), allPassed(), passCount(), failCount() | Orquestador secuencial de escenarios (@since 3.2.0) |
ChaosOutcome | durationSeconds(), toArray() | Resultado pass/fail por escenario (@since 3.2.0) |
RetrievalUnavailableException | — | No se pudo alcanzar un recurso probado |
ChaosReportWriteException | — | No se pudo escribir el archivo de informe |
Ejecutar composer docs:generate-api-php -- --module=Chaos para obtener la tabla completa de PHPDoc.
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»Registrar un escenario y ejecutar la suite.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Chaos\ChaosOutcome;use NextPDF\Chaos\ChaosScenarioInterface;use NextPDF\Chaos\ChaosScenarioRunner;
final class TimeoutScenario implements ChaosScenarioInterface{ public function name(): string { return 'dependency-timeout'; }
public function simulate(): ChaosOutcome { // Inject the fault, observe the engine's degradation, return the verdict. return new ChaosOutcome(/* name, passed, durationSeconds, details */); }}
$runner = new ChaosScenarioRunner();$runner->register(new TimeoutScenario());$runner->run();
echo $runner->allPassed() ? "Resilient.\n" : "{$runner->failCount()} scenario(s) failed.\n";Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Controlar el arnés desde un trabajo de resiliencia y tratar cualquier fallo como una salida distinta de cero, sin dejar que el fallo de un escenario se propague como una excepción.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Chaos\ChaosScenarioRunner;use NextPDF\Chaos\Exception\ChaosReportWriteException;use Psr\Log\LoggerInterface;
final readonly class ChaosJob{ /** @param list<\NextPDF\Chaos\ChaosScenarioInterface> $scenarios */ public function __construct( private array $scenarios, private LoggerInterface $logger, ) {}
public function run(string $reportPath): int { $runner = new ChaosScenarioRunner();
foreach ($this->scenarios as $scenario) { $runner->register($scenario); }
$runner->run(); // never throws on scenario failure
try { $runner->writeReport($reportPath); } catch (ChaosReportWriteException $e) { $this->logger->error('Chaos report could not be written.', ['error' => $e->getMessage()]);
return 2; }
return $runner->allPassed() ? 0 : 1; }}Casos límite y trampas
Sección titulada «Casos límite y trampas»run()nunca lanza una excepción porque un escenario haya fallado. Un fallo reside enChaosOutcome. Si se envuelverun()en un try/catch con la expectativa de capturar allí los fallos, no aparecerán: leerfailCount()/allPassed()en su lugar.- El ejecutor lanza una excepción solo ante fallos de infraestructura: un registro incorrecto, o una
ChaosReportWriteExceptioncuando la ruta del informe no se puede escribir. Gestionarlos de forma diferenciada de los resultados de los escenarios. - Los escenarios se ejecutan secuencialmente en orden de registro. No hay paralelismo. El orden puede importar si los escenarios comparten estado externo.
- Este módulo es para pruebas de resiliencia. No importar el ejecutor en la ruta de producción de documentos como mecanismo de control.
Rendimiento
Sección titulada «Rendimiento»La sobrecarga del ejecutor es insignificante. El coste está en lo que hagan los escenarios. Como los escenarios inyectan fallos y pueden esperar a que se agoten tiempos de espera, una ejecución de caos puede ser lenta por diseño. El performance_budget aquí es la cifra de referencia del motor, no un límite para la duración del escenario. El perfil de reproducibilidad es structural: el informe registra duraciones de reloj de pared, por lo que dos ejecuciones difieren en esos campos.
Notas de seguridad
Sección titulada «Notas de seguridad»Los escenarios inyectan fallos y pueden ejercitar rutas de fallo en las dependencias. Ejecutar el arnés únicamente en un entorno de prueba o de preproducción con credenciales y endpoints acotados a ese entorno; nunca contra sistemas de producción. El informe puede contener detalles de diagnóstico sobre los modos de fallo. Tratarlo como información interna y aplicar el requisito del proyecto sobre depuración de registros antes de compartirlo. Consultar el modelo de amenazas del motor en /modules/core/security/.
Conformidad
Sección titulada «Conformidad»Este módulo no formula ninguna afirmación normativa sobre la especificación PDF. Es una utilidad de resiliencia. No implementa ningún protocolo estandarizado cuyas cláusulas deban citarse. La conformidad del motor se valida mediante las suites de oráculo y de referencia (golden) descritas en /modules/core/conformance/.
Véase también
Sección titulada «Véase también»- Módulo Observability — la superficie de estado en tiempo de ejecución que observa un escenario.
- Módulo Accelerator — un objetivo común para los escenarios de fallo de dependencias.
- Descripción general de conformidad
- Modelo de seguridad del motor