Generated code - Transient Error Recovery

Preface

The LLBLGen Pro Runtime Framework supports basic Transient Error Recover, or Connection Resilience, during operations. This release contains strategy classes which implement a recovery strategy and are to be used together with the action you'd like to perform on the database. This means the strategies are not 'set-and-forget' but require you to add code to be able to recover a given database action.

This section describes the strategies available to you, how to write your own and how to use the strategies to make database work transient-error robust.

Transient errors

Transient errors are errors which are recoverable: a connection was temporarily not available, timeouts etc.. Some strategies check for transient errors, and if such an error occurs, they will retry, and otherwise fail. Other strategies will always retry, no matter what the error is. Currently LLBLGen Pro supports dedicated transient error checking for SQL Server, however it's easy to add your own for additional databases.

Strategies

To use the transient error recovery, we have implement a set of strategies. A strategy is a definition how work is retried. A strategy has three parameters:

A strategy is asked to execute a piece of code through a lambda (which does or doesn't return a value and which is executed asynchronously or synchronously). If that piece of code fails and the error causing that failure is a transient error, the code is retried till the maximum number of retries is reached or the maximum delay is reached.

The period of inactivity between retry attempts is calculated with the recovery delay object specified with the strategy. The recovery delay object works with a delay parameter, which is used in the calculations. There are a couple of different delay period calculations possible: (attempt is the attempt number)

The next delay value calculated will be the minimum value of the maximum delay specified on the recovery delay object and the new calculated value.

Different strategies provided

The following strategies are provided, which are classes available in the ORMSupportClasses assembly and located in the SD.LLBLGen.Pro.ORMSupportClasses namespace. They all derive from the base class RecoveryStrategyBase.

There are others possible, you can implement your own using the classes provided.

Exceptions gathered

When errors occur during the execution and they're transient errors, they're still collected within the strategy used. To obtain the exceptions, read the CollectedExceptions property of the strategy after the execution of the work, which contains the collected exceptions. These exceptions are the wrapping exceptions, and are of type ORMException.

Recovery failure

If after the maximum number of attempts or the maximum delay the work still fails, the strategies will report this with an ORMTransientRecoveryFailedException exception. It can be used to perform other ways to recover from the errors. It contains all exceptions collected during the execution and retry phase of the strategy.

Thread safety and strategies

It's tempting to re-use a strategy object across code and across threads. This won't work, as a strategy object is a controller of the recovery process and can handle one batch of work at a time.

Tracing and recovery

Recovery strategies use tracing to signal what they're doing. The tracer used is ORMQueryExecution with two levels:

Usage

Using a strategy is straightforward. The example below contains all the overhead to use a strategy with a call. It's recommended to create a generic method which wraps the calls so you don't have to add the overhead with each call: simply call your wrapper method to perform work and apply a strategy in one go.

var q = from c in metaData.Customer
        where c.Country=="USA"
        select c;
var strategy = new SqlAzureRecoveryStrategy(); // use defaults
var l = strategy.Execute(()=>q.ToList());

// async usage
var l2 = strategy.ExecuteAsync(()=>q.ToListAsync());


The lambda passed in to execute is the work which is retried if it fails, using the strategy parameters.

It is key to wrap the complete work to re-try in a single anonymous method/lambda, so retrying the work can succeed: it's not sufficient to start a transaction outside the Execute call and then try to retry inserts within the transaction: a batch of work that is meant to be retried has to start its own transaction and commit its own work.

Rule of thumb: it should be able to succeed by opening its own connection and close it afterwards.


LLBLGen Pro Runtime Framework v4.1 documentation. ©2013 Solutions Design bv