Przejdź do głównej zawartości

Chaos: deterministyczne środowisko dla scenariuszy odporności

Moduł Chaos to kompaktowe środowisko do testowania odporności. Rejestrujesz scenariusze wstrzykiwania błędów, które implementują interfejs z jedną metodą, uruchamiasz je i otrzymujesz ustrukturyzowany raport pass/fail. Celowo pozostaje niewielki — liczy pięć klas — i jest przeznaczony do zestawów testów odporności oraz ćwiczeń chaos-day, a nie do produkcyjnej ścieżki tworzenia dokumentów.

Stabilność: eksperymentalna. To powierzchnia narzędzi do testów odpornościowych, a nie podstawowy interfejs programowania aplikacji (API) dla formatu Portable Document Format (PDF). Interfejs dostawcy usług (SPI) jest niewielki, a jego kształt stabilny, ale zakres modułu i dołączone do niego scenariusze ewoluują. Nie buduj na nim produkcyjnego przepływu sterowania.

Okno terminala
composer require nextpdf/core:^3

Test odporności sprawdza, czy silnik poprawnie degraduje działanie, gdy zawiedzie zależność. Moduł Chaos nadaje temu testowi strukturę. ChaosScenarioInterface to kontrakt scenariusza: name() identyfikuje scenariusz, a simulate() zwraca ChaosOutcome. Każdy scenariusz kapsułkuje jeden błąd, taki jak podział sieci lub seria odpowiedzi 5xx z zaplecza pobierania, i raportuje, co się wydarzyło.

ChaosScenarioRunner koordynuje przebieg. Rejestrujesz scenariusze za pomocą register(), wywołujesz run(), aby wykonać je sekwencyjnie w kolejności rejestracji, a następnie odczytujesz wynik zbiorczy za pomocą outcomes(), allPassed(), passCount() i failCount(). Mechanizm uruchamiający nigdy nie zgłasza wyjątku z powodu niepowodzenia scenariusza: niepowodzenie to dane zapisane w ChaosOutcome, a nie wyjątek. Zgłasza wyjątek tylko wtedy, gdy uszkodzona jest jego własna infrastruktura, na przykład przy nieprawidłowej rejestracji scenariusza lub niemożności zapisania pliku raportu (ChaosReportWriteException). Scenariusz, który nie może dotrzeć do testowanego zasobu, sygnalizuje RetrievalUnavailableException. Moduł jest oznaczony jako @since 3.2.0.

ChaosOutcome przechowuje wynik danego scenariusza: status pass/fail, czas trwania oraz dane wyjściowe toArray() na potrzeby ustrukturyzowanego raportu. Ponieważ wynik zapisuje czas trwania zmierzony zegarem ściennym, profil odtwarzalności raportu jest structural, a nie bitwise.

TypKluczowe elementyRola
ChaosScenarioInterfacename(): string, simulate(): ChaosOutcomeKontrakt scenariusza (@since 3.2.0)
ChaosScenarioRunnerregister(), run(), outcomes(), allPassed(), passCount(), failCount()Sekwencyjny orkiestrator scenariuszy (@since 3.2.0)
ChaosOutcomedurationSeconds(), toArray()Wynik pass/fail dla danego scenariusza (@since 3.2.0)
RetrievalUnavailableExceptionTestowany zasób był nieosiągalny
ChaosReportWriteExceptionNie udało się zapisać pliku raportu

Uruchom composer docs:generate-api-php -- --module=Chaos, aby wygenerować pełną tabelę PHPDoc.

Zarejestruj scenariusz, a następnie uruchom zestaw.

<?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";

Steruj środowiskiem z poziomu zadania odpornościowego i zwracaj niezerowy kod wyjścia przy każdym niepowodzeniu, nie dopuszczając, aby niepowodzenie scenariusza wydostało się jako wyjątek.

<?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;
}
}
  • run() nigdy nie zgłasza wyjątku z powodu niepowodzenia scenariusza. Niepowodzenie jest zapisane w ChaosOutcome. Jeśli opakujesz run() w blok try/catch, spodziewając się wychwycić tam niepowodzenia, nie zobaczysz ich. Zamiast tego odczytaj failCount() / allPassed().
  • Mechanizm uruchamiający zgłasza wyjątek tylko w przypadku błędów infrastruktury: nieprawidłowej rejestracji lub wyjątku ChaosReportWriteException, gdy ścieżka raportu nie pozwala na zapis. Obsługuj te błędy oddzielnie od wyników scenariuszy.
  • Scenariusze są uruchamiane sekwencyjnie w kolejności rejestracji. Nie ma tu żadnej równoległości. Kolejność może mieć znaczenie, gdy scenariusze współdzielą stan zewnętrzny.
  • Ten moduł służy do testowania odporności. Nie importuj mechanizmu uruchamiającego do produkcyjnej ścieżki tworzenia dokumentów jako mechanizmu sterującego.

Mechanizm uruchamiający dodaje pomijalny narzut. O koszcie decyduje zachowanie scenariusza. Ponieważ scenariusze wstrzykują błędy i mogą oczekiwać na przekroczenia limitu czasu, przebieg chaosu może być z założenia powolny. Wartość performance_budget jest tutaj punktem odniesienia dla silnika, a nie ograniczeniem czasu trwania scenariusza. Profil odtwarzalności jest structural: raport zapisuje czasy trwania mierzone zegarem ściennym, więc te pola różnią się między przebiegami.

Scenariusze wstrzykują błędy i mogą uruchamiać ścieżki awarii w zależnościach. Uruchamiaj to środowisko wyłącznie w środowisku testowym lub przejściowym, z poświadczeniami i punktami końcowymi ograniczonymi do tego środowiska. Nigdy nie uruchamiaj go w systemach produkcyjnych. Raport może zawierać szczegółowe informacje diagnostyczne o trybach awarii. Traktuj go jako wewnętrzny i przed udostępnieniem zastosuj obowiązujące w projekcie zasady czyszczenia logów. Zobacz model zagrożeń silnika w /modules/core/security/.

Ten moduł nie formułuje żadnego normatywnego twierdzenia dotyczącego specyfikacji PDF. To narzędzia do testowania odporności. Nie implementuje żadnego standardowego protokołu, którego klauzule trzeba by przytaczać. Zestawy oracle i golden opisane w /modules/core/conformance/ weryfikują zgodność silnika.