Chaos:確定性韌性情境測試框架
Chaos 模組是一個用於韌性測試的小型框架。你會註冊實作單一方法介面的故障注入情境、執行它們,並收集一份結構化的 pass/fail 報告。它刻意維持極簡——僅五個類別——用於韌性測試套件與混沌演練(chaos-day),而非文件產製路徑。
穩定度:實驗性。 這是一個測試暨韌性工具面, 並非核心 PDF API。其 SPI 規模小、形態穩定,但本模組的範圍與隨附情境仍在演進。請勿以它建構正式環境的控制流程 。
composer require nextpdf/core:^3概念總覽
標題為「概念總覽」的區段韌性測試關心的是:當某個相依項失效時,引擎是否會正確降級?Chaos 模組為這項測試提供結構。ChaosScenarioInterface 是情境要實作的契約:一個 name(),以及一個會回傳 ChaosOutcome 的 simulate()。一個情境會封裝單一故障(網路分割、一連串擷取後端的 5xx 回應),並回報實際發生的狀況。
ChaosScenarioRunner 是協調者。你會用 register() 註冊情境、呼叫 run() 按註冊順序循序執行它們,並讀回彙整結果:outcomes()、allPassed()、passCount()、failCount()。此 runner 絕不會因為情境失敗就拋出例外——失敗會被擷取為 ChaosOutcome 裡的資料,而不是例外。它只會在自身基礎設施出問題時拋出例外:無效的情境註冊,或無法寫入報告檔(ChaosReportWriteException)。無法觸及其所測試資源的情境,會讓 RetrievalUnavailableException 浮出。本模組整體為 @since 3.2.0。
ChaosOutcome 代表每個情境的結果:pass/fail、一段持續時間,以及供結構化報告使用的 toArray()。由於 outcome 會記錄牆鐘(wall-clock)持續時間,該報告的可重現性設定檔為 structural,而非 bitwise。
API 介面
標題為「API 介面」的區段| 型別 | 主要成員 | 角色 |
|---|---|---|
ChaosScenarioInterface | name(): string、simulate(): ChaosOutcome | 情境契約(@since 3.2.0) |
ChaosScenarioRunner | register()、run()、outcomes()、allPassed()、passCount()、failCount() | 循序情境協調者(@since 3.2.0) |
ChaosOutcome | durationSeconds()、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";程式碼範例——正式環境
標題為「程式碼範例——正式環境」的區段由韌性工作(resilience job)驅動此框架,並將任何失敗視為非零離開碼,同時不讓情境失敗以例外形式逸出。
<?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()。- 此 runner 只會因基礎設施故障而拋出例外:錯誤註冊,或報告路徑不可寫入時的
ChaosReportWriteException。請將這些與情境結果分開處理。 - 情境會依註冊順序循序執行。沒有平行處理。如果多個情境共用外部狀態,順序可能會有影響。
- 本模組用於韌性測試。請勿將此 runner 當作控制機制放進文件產製路徑。
此 runner 的額外負擔可忽略不計。成本取決於情境實際做了什麼。由於情境會注入故障並可能等待逾時,一次混沌執行依設計本就可能很慢。此處的 performance_budget 是引擎的參考數值,並非情境持續時間的上限。其可重現性設定檔為 structural:報告會記錄牆鐘持續時間,因此兩次執行在這些欄位上會有所不同。
安全性注意事項
標題為「安全性注意事項」的區段情境會注入故障,並可能觸發相依項中的失敗路徑。請只在測試或預備(staging)環境中執行此框架,且其憑證與端點都限定於該環境——絕不可針對正式環境系統執行。報告可能包含失敗模式相關診斷細節。請將其視為內部資料,並在分享前套用本專案的日誌清理(log-scrubbing)要求。請參閱 /modules/core/security/ 中的引擎威脅模型。
符合性
標題為「符合性」的區段本模組未對任何 PDF 規範提出規範性宣告。它是韌性工具,也未實作任何必須引用其條款的標準化協定。引擎符合性由 /modules/core/conformance/ 中所述的 oracle 與黃金套件(golden suites)驗證。
另請參閱
標題為「另請參閱」的區段- Observability 模組 — 情境觀察的執行期狀態面。
- Accelerator 模組 — 相依項失效情境的常見目標。
- 符合性總覽
- 引擎安全模型