IFailureClassifier
Decides what kind of failure an exception represents, so Trax records a FailureClass on every failed run. Optional: with none registered, every failure records Unclassified.
Signature
namespace Trax.Effect.Services.FailureClassifier;
public interface IFailureClassifier
{
FailureClass? Classify(Exception exception);
}| Parameter | Type | Description |
|---|---|---|
exception | Exception | The original exception the run failed with, not a wrapper, so you can type-check it and read its structured data |
Returns: FailureClass?. One of Transient, Conflict, Permanent (or Unclassified), or null to leave the failure unclassified. FailureClass lives in Trax.Core.Exceptions.
Registration
There is no builder method. Register it in the container:
services.AddSingleton<IFailureClassifier, NetSuiteFailureClassifier>();Trax resolves one IFailureClassifier from the train's service provider, so the last registration wins. For runs executed on a remote worker, register it in the worker process.
Behavior
| Situation | What is recorded |
|---|---|
| No classifier registered, or it returns null | Unclassified |
| The classifier throws | Unclassified; the classifier's exception is logged and the run's failure is unaffected |
| The run was asked to stop (its token was cancelled, or its cancel flag was set) | Cancelled state; the classifier is not called |
An OperationCanceledException nothing asked for, such as an HttpClient timeout (TaskCanceledException) | Failed state; the classifier's answer, or Transient when it has none |
| The failure already carries a class (a remote worker sent one, or a calling-side junction preserved it) | The carried class; it wins over the local classifier |
Another exception type, including a subclass of TrainException, whose message is JSON shaped like a failure record | Its message is not read for a class; only an exception whose type is exactly TrainException carries one there, so the classifier decides as usual |
| A carried class outside the vocabulary | Unclassified |
| The failure was rebuilt from a serialized record (a remote failure) and carries no class | Unclassified; a rebuilt exception is never passed to the local classifier, because its original type is gone |
| The scheduler recorded the failure (dispatch failure, stale-run reaping) | Unclassified |
| A failure raised outside any junction | The classifier's answer |
The recorded class is Metadata.FailureClass, readable in OnFailed, persisted in the failure_class column, and exposed over GraphQL as failureClass.
Example
public class NetSuiteFailureClassifier : IFailureClassifier
{
public FailureClass? Classify(Exception exception) =>
exception is NetSuiteRestException { StatusCode: HttpStatusCode.BadRequest } ex
&& ex.ErrorDetails.Any(d => d.Detail.Contains("Record has been changed"))
? FailureClass.Conflict
: null;
}See Classifying failures for the concepts.
Package
dotnet add package Trax.Effect