Skip to content

[Operation] FailSafeConfig: allow skipping a permanently-failed item instead of aborting the whole run #81

Description

@oliverde8

Problem

FailSafe's docs (docs/doc/10-examples/190-error-handling.md, "Continue Processing on Failure") claim: "One of the most powerful features of FailSafe is that it allows the chain to continue processing other items even if one fails." This isn't true today.

FailSafeOperation::repeatOnItem() re-throws once nbAttempts is exhausted. That propagates through ChainProcessor::process(), which has no per-item recovery — it logs and re-throws, aborting the entire run. Confirmed by the library's own test, FailSafeOperationTest::testToManyFail(): given 2 permanently-failing items in the input iterator, the second item is never even attempted — the first item's exhausted retries kill the whole process() call.

Proposed solution

Give FailSafeConfig an optional onFailure: ?ChainConfig sub-chain, the same pattern IfConfig already uses for then/else — not a boolean flag, not a new item type. When retries are exhausted:

  • No onFailure configured (default null) → re-throw, exactly like today. Fully backward compatible.
  • onFailure configured → the failed item runs through that chain instead of aborting the run. It's a normal ChainConfig, so it can do anything — write it to a reject file, alert, log richly — not just a fixed "drop with a reason" behavior.
new FailSafeConfig(
    chainConfig: $apiChain,
    exceptionsToCatch: [\Exception::class],
    nbAttempts: 3,
    onFailure: (new ChainConfig())->addLink(new CsvFileWriterConfig('rejects.csv')),
);

FailSafeOperation builds $onFailureProcessor from it (when present) the same way it already builds $chainProcessor, and on final failure runs the item through $onFailureProcessor->processGenerator(...) instead of re-throwing. This also means FailSafeOperation::getChainProcessors() (see #74) should return both $chainProcessor and $onFailureProcessor when present, so the failure branch shows up in Mermaid diagrams too.

Compatibility

No V3. New optional parameter defaulting to null; existing configs behave identically.

Scope

  • FailSafeConfig, FailSafeOperation
  • Tests: extend/mirror testToManyFail for the onFailure case — assert the second item does get processed, and that the failed item reaches the onFailure chain
  • Docs: 190-error-handling.md's "Continue Processing on Failure" section needs to actually match reality once this ships
  • Related: [Output] Mermaid - Show Repeat/FailSafe sub-chains in the static diagram #74 (Mermaid support for Repeat/FailSafe sub-chains)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions