-
Notifications
You must be signed in to change notification settings - Fork 298
Error Handling & Compensation
Andrey Zaytsev edited this page Aug 4, 2022
·
2 revisions
Any exception thrown in the TaskActivity code is marshaled back and thrown as a TaskFailedException in the TaskOrchestration code. Users can write the appropriate error handling and compensation code that suits their needs around this.
public class DebitCreditOrchestration :
TaskOrchestration<object, DebitCreditOperation>
{
public override async Task<object> RunTask(OrchestrationContext context,
DebitCreditOperation operation)
{
bool failed = false;
bool debited = false;
try
{
await context.ScheduleTask<object>(typeof (DebitAccount),
new Tuple<string, float>(operation.SourceAccount, operation.Amount));
debited = true;
await context.ScheduleTask<object>(typeof(CreditAccount),
new Tuple<string, float>(operation.TargetAccount, operation.Amount));
}
catch (TaskFailedException exception)
{
if (debited)
{
// can build a try-catch around this as well, in which case the
// orchestration may either retry a few times or log the inconsistency for review
await context.ScheduleTask<object>(typeof(CreditAccount),
new Tuple<string, float>(operation.SourceAccount, operation.Amount));
}
}
return null;
}
}
Note that pre-dotnet 6.0, the await keyword cannot be used within a catch block due to a CLR limitation. In that case, we can modify the snipped above to set up a failed
flag and perform a compensation before returning a result:
# ... orchestration code here
catch (TaskFailedException exception)
{
failed = true;
}
if (failed)
{
if (debited)
{
// can build a try-catch around this as well, in which case the
// orchestration may either retry a few times or log the inconsistency for review
await context.ScheduleTask<object>(typeof(CreditAccount),
new Tuple<string, float>(operation.SourceAccount, operation.Amount));
}
}
return null;
}
}