Перейти к содержимому

Chaos: детерминированный набор сценариев проверки устойчивости

Модуль Chaos — компактный набор средств для тестирования устойчивости. Вы регистрируете сценарии внедрения сбоев, которые реализуют интерфейс с одним методом, запускаете их и собираете структурированный отчёт со статусами pass/fail. Модуль намеренно остаётся небольшим — пять классов — и предназначен для наборов проверки устойчивости и учений chaos-day, а не для промышленного контура генерации документов.

Стабильность: экспериментальная. Это инструментарий для тестирования и проверки устойчивости, а не основной API для формата Portable Document Format (PDF). Интерфейс поставщика услуг (SPI) невелик и стабилен по форме, но область применения модуля и поставляемые с ним сценарии развиваются. Не используйте его как основу промышленного потока управления.

Окно терминала
composer require nextpdf/core:^3

Тест устойчивости проверяет, корректно ли деградирует движок при отказе зависимости. Модуль Chaos придаёт такому тесту структуру. ChaosScenarioInterface — это контракт сценария: name() идентифицирует сценарий, а simulate() возвращает ChaosOutcome. Каждый сценарий инкапсулирует один сбой, например сетевое разделение или всплеск ответов 5xx от бэкенда извлечения, и сообщает, что произошло.

ChaosScenarioRunner управляет выполнением. Вы регистрируете сценарии методом register(), вызываете run(), чтобы выполнить их последовательно в порядке регистрации, а затем читаете агрегированный результат с помощью outcomes(), allPassed(), passCount() и failCount(). Раннер никогда не выбрасывает исключение при сбое сценария: сбой — это данные, зафиксированные в ChaosOutcome, а не исключение. Он выбрасывает исключение только тогда, когда отказывает его собственная инфраструктура, например при попытке зарегистрировать недопустимый сценарий или невозможности записать файл отчёта (ChaosReportWriteException). Сценарий, который не может достичь тестируемого ресурса, выбрасывает RetrievalUnavailableException. Модуль доступен начиная с @since 3.2.0.

ChaosOutcome хранит результат отдельного сценария: статус pass/fail, длительность и вывод toArray() для структурированного отчёта. Поскольку результат фиксирует длительность по wall-clock-времени, профиль воспроизводимости отчёта — structural, а не bitwise.

ТипКлючевые членыРоль
ChaosScenarioInterfacename(): string, simulate(): ChaosOutcomeКонтракт сценария (@since 3.2.0)
ChaosScenarioRunnerregister(), run(), outcomes(), allPassed(), passCount(), failCount()Последовательный оркестратор сценариев (@since 3.2.0)
ChaosOutcomedurationSeconds(), toArray()Результат pass/fail для отдельного сценария (@since 3.2.0)
RetrievalUnavailableExceptionТестируемый ресурс был недоступен
ChaosReportWriteExceptionФайл отчёта не удалось записать

Выполните composer docs:generate-api-php -- --module=Chaos, чтобы сгенерировать полную таблицу PHPDoc.

Зарегистрируйте сценарий, затем запустите набор.

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

Пример кода — промышленное использование

Заголовок раздела «Пример кода — промышленное использование»

Запускайте набор из задания проверки устойчивости и возвращайте ненулевой код выхода при любом сбое, не позволяя сбою сценария выйти наружу в виде исключения.

<?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() никогда не выбрасывает исключение из-за того, что сценарий завершился сбоем. Сбой содержится в ChaosOutcome. Если вы обернёте run() в try/catch, ожидая поймать там сбои, вы их не увидите. Вместо этого читайте failCount() / allPassed().
  • Раннер выбрасывает исключение только при инфраструктурных сбоях: из-за некорректной регистрации или при ChaosReportWriteException, когда путь к отчёту недоступен для записи. Обрабатывайте эти сбои отдельно от результатов сценариев.
  • Сценарии выполняются последовательно в порядке регистрации. Параллельного выполнения нет. Порядок может иметь значение, когда сценарии используют общее внешнее состояние.
  • Этот модуль предназначен для тестирования устойчивости. Не импортируйте раннер в промышленный контур генерации документов как механизм управления.

Раннер добавляет пренебрежимо малые накладные расходы. Затраты определяются поведением сценария. Поскольку сценарии внедряют сбои и могут ожидать истечения тайм-аутов, запуск chaos может быть медленным сам по себе. Здесь performance_budget — это ориентир для движка, а не ограничение на длительность сценария. Профиль воспроизводимости — structural: отчёт фиксирует длительности по wall-clock-времени, поэтому эти поля различаются между запусками.

Сценарии внедряют сбои и могут задействовать пути отказа в зависимостях. Запускайте набор только в тестовой или промежуточной среде, с учётными данными и конечными точками, ограниченными этой средой. Никогда не запускайте его против промышленных систем. Отчёт может содержать диагностические сведения о режимах отказа. Считайте его внутренним и выполните принятые в проекте требования к очистке логов, прежде чем им делиться. См. модель угроз движка в /modules/core/security/.

Этот модуль не заявляет о соответствии нормативным требованиям спецификации PDF. Это инструментарий для проверки устойчивости. Он не реализует стандартизированный протокол, чьи положения нужно было бы цитировать. Наборы oracle и golden, описанные в /modules/core/conformance/, проверяют соответствие движка.