Skip to content
reisenberger edited this page Oct 15, 2016 · 1 revision

Fallback Policy

Purpose

To provide a substitute value (or substitute action to be actioned) in the event of failure.

Premise: 'If all else fails, degrade gracefully'

Outright failures will still occur: plan for what you will do when that happens.

Syntax

TResult-returning calls

Return a specific fallback result:

Policy
   .Handle<Whatever>()
   .Fallback<UserAvatar>(UserAvatar.Blank)

Run a function to provide a fallback result:

Policy
   .Handle<Whatever>()
   .Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) 

void-returning calls

A FallbackPolicy may also be used on void-returning calls. In this case, it specifies an alternate Action to be run (rather than substitute return value), if the policy handles a fault.

Policy
   .Handle<Whatever>()
   .Fallback(() => DoFallbackAction()) 

Operation

  • executes the supplied delegate
  • if the delegate throws a handled exception or returns a handled result:
    • calls any configured onFallback/Async delegate
    • then calls the configured fallback Func/Action

Interacting with policy operation

OnFallback

An optional onFallback / onFallbackAsync delegate allows specific code to be executed (for example for logging) before the fallback Func/Action is invoked.

// Specify a substitute value or func, calling an action (eg for logging) if the fallback is invoked.
Policy
   .Handle<Whatever>()
   .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) => 
    {
        logger.Error($"{context.PolicyKey} at {context.ExecutionKey}: fallback value substituted, due to: {t.Exception}.");
    });

Thread safety and policy reuse

Thread safety

FallbackPolicy is thread-safe: multiple calls may safely be placed concurrently through a policy instance.

Policy reuse

FallbackPolicy instances may be re-used across multiple call sites.

When reusing policies, use an ExecutionKey to distinguish different call-site usages within logging and metrics.