Configure a circuit breaker for xConnect

Version: 10.4

The circuit breaker design pattern prevents a malfunctioning service or application from building up a crippling backlog of unanswered requests. With a circuit breaker configured, the service can signal that it is currently unavailable, and the circuit breaker temporarily responds to all request with the last known error message.

Tip

The circuit breaker concept comes from electrical engineering: In an electrical circuit, an open circuit breaker stops the flow of electricity. When a circuit breaker is closed, electricity can flow freely.

A software circuit breaker can be in the following states:

  • Closed - The service is available and responding to requests as expected.

  • Open - The service is unavailable, and the circuit breaker responds to each request with an error message.

  • Half-open - The circuit breaker is limiting the requests to the service to see if it is available.

You configure circuit breakers collectively or individually by specifying the CircuitBreakerType:

CircuitBreakerType

Client configured

General

Configures the Collection, Search, and Configuration clients collectively, but is overriden by individual client circuit breaker configurations.

Collection

Configures the CollectionWebApiClient only.

Search

Configures the SearchWebApiClient only.

Configuration

Configures the ConfigurationWebApiClient only.

Sitecore uses the Polly Circuit Breaker library and has added a Polly.IAsyncPolicy<HttpResponseMessage> type field to to the Sitecore.Xdb.Common.Web.CommonWebApiClient<TRoutes> class. This allows you to do a dependency injection of the Polly.CircuitBreaker class, which is an implementation of Polly.IAsyncPolicy.

Circuit breakers have the following configuration options:

  • handledEventsAllowedBeforeBreaking - The maximum number of service failures allowed before the circuit breaker shifts into open state.

  • durationOfBreak - The number of seconds that the circuit breaker stays in open state before shifting into half-open state.

Circuit breakers have the following state change handlers:

  • onBreak() - Called when the circuit breaker shifts into open state.

  • onReset() - Called when the circuit breaker shifts into closed state.

You can enable circuit breakers in the following ways:

You can disable a circuit breaker by simply removing or commenting out the corresponding configuration section.

Enable a CircuitBreaker configuration by patch file

You use CircuitBreaker configurations to manage xConnect requests from the Content Management role. You do not need to write custom code to enable circuit breakers by CircuitBreaker configuration, but you also cannot specify state change handlers.

To create a CircuitBreaker configuration:

  1. Go to the <wwwroot>/App_Config/Include/ folder of your Sitecore instance.

  2. Create a patch file named, for example, CircuitBreakerCommon.config with the following content:

    RequestResponse
    <CircuitBreaker
      name="CircuitBreakerCommon"
      type="Sitecore.XConnect.Client.WebApi.Policies.CircuitBreakerInfo, Sitecore.XConnect.Client" >
        <param desc="Key">General</param>
        <param desc="handledEventsAllowedBeforeBreaking">2</param>
        <param desc="durationOfBreak">15</param>
    </CircuitBreaker>  
  3. Save the patch file.

Enable a CircuitBreakerInfos configuration by patch file

You use CircuitBreakerInfos configurations to manage xConnect requests from roles other than Content Management, such as Marketing Automation. You do not need to write custom code to enable circuit breakers by CircuitBreakerInfos configuration, but you also cannot specify state change handlers.

To create a CircuitBreakerInfos configuration:

  1. Go to the <wwwroot>/App_Config/Include/ folder of your Sitecore instance.

  2. Create a patch file named, for example, CircuitBreakerInfos.config with the following content:

    RequestResponse
    <CircuitBreakerInfos>
      <General>
        <HandledEventsAllowedBeforeBreaking>3</HandledEventsAllowedBeforeBreaking>
        <CircuitBreakerType>General</CircuitBreakerType>
        <DurationOfBreak>15</DurationOfBreak>
      </General>
    
      <Collection>
        <HandledEventsAllowedBeforeBreaking>3</HandledEventsAllowedBeforeBreaking>
        <CircuitBreakerType>Collection</CircuitBreakerType>
        <DurationOfBreak>35</DurationOfBreak>
      </Collection>
    
      <Search>
        <HandledEventsAllowedBeforeBreaking>3</HandledEventsAllowedBeforeBreaking>
        <CircuitBreakerType>Search</CircuitBreakerType>
        <DurationOfBreak>25</DurationOfBreak>
      </Search>
    
      <Configuration>
        <HandledEventsAllowedBeforeBreaking>1</HandledEventsAllowedBeforeBreaking>
        <CircuitBreakerType>Configuration</CircuitBreakerType>
        <DurationOfBreak>25</DurationOfBreak>
      </Configuration>
    </CircuitBreakerInfos>
  3. Save the patch file.

Enable a CircuitBreaker factory by constructor parameter

You use CircuitBreaker factories passed as constructor parameters to create customized request handling and state change handlers.

The XConnectClientConfigurationConfigurator constructor accepts an IConfiguration instance and an optional CircuitBreaker factory as parameters:

  • The IConfiguration instance contains various parameters and can also contain CircuitBreaker parameters.

  • The optional CircuitBreaker factory is based on the Sitecore.Reflection.IFactory interface and can also be passed by dependency injection.

If you only pass the IConfiguration instance, XConnectClientConfigurationConfigurator uses the CircuitBreaker parameters of the IConfiguration instance:

RequestResponse
XConnectClientConfigurationConfigurator(<IConfiguration instance>);

If you pass the IConfiguration instance and a CircuitBreaker factory, XConnectClientConfigurationConfigurator ignores the CircuitBreaker parameters of the IConfiguration instance and uses the CircuitBreaker factory only:

RequestResponse
XConnectClientConfigurationConfigurator(<IConfiguration instance>, <CircuitBreaker factory>);

To enable a CircuitBreaker factory by constructor parameter:

  1. In Visual Studio, in any file, enter the following:

    RequestResponse
    IConfiguration config = <define this in code or read it from an XML file>
    
    public class TestCircuitBreakerFactoryCreatorStub : ICircuitBreakerFactoryCreator
    {
      public CircuitBreakerFactoryCreatorStub()
      {
      }
    
      public CircuitBreakerFactory CreateCircuitBreakerConfiguration()
      {
        return CircuitBreakerFactory.DefaultFactory;
      }
    }
    
    var configurator = new XConnectClientConfigurationConfigurator(
      config,
      new TestCircuitBreakerFactoryCreatorStub()
    );
  2. Compile, test, and deploy the factory.

Enable a CircuitBreaker factory by patch file

You use CircuitBreaker factories configured by patch file to gain increased flexibility, because you can change the configuration without having to recompile the factory.

To enable a CircuitBreaker factory by patch file:

  1. In Visual Studio, create a new class file named, for example, TestCircuitBreakerInfoFactoryStub.cs with the following content:

    RequestResponse
    public class TestCircuitBreakerInfoFactoryStub : IFactory
    {
      public object GetObject(string identifier)
      {
        switch (identifier)
        {
          case "Collection":
            return new CircuitBreakerInfo(1, 10, CircuitBreakerType.Collection,
              (x, y) => {/*log.Write("OnBreak")*/ },
              () => { /*log.Write("OnReset")*/} );
          case "Search":
            return new CircuitBreakerInfo(2, 20, CircuitBreakerType.Search,
              (x, y) => { }, () => { });
          case "Config":
            return new CircuitBreakerInfo(3, 30, CircuitBreakerType.Configuration,
              (x, y) => { }, () => { });
        }
        return null;
      }
    }
  2. Go to the <wwwroot>/App_Config/Include/ folder of your Sitecore instance and create a patch file named, for example, TestCircuitBreakerInfoFactoryStub.config with the following content:

    RequestResponse
    <CircuitBreaker name="CircuitBreakerCollection" factory="TestCircuitBreakerInfoFactoryStub" ref="Collection"/>

    The CircuitBreaker configuration declares that the CircuitBreakerCollection circuit breaker created by the TestCircuitBreakerInfoFactoryStub factory is used by the Collection client. Always declare the factory early in the configuration as demonstrated in the complete sample circuit breaker configuration.

  3. Compile, test, and deploy the factory.

Complete sample circuit breaker configuration

To give a better contextual understanding, this sample circuit breaker configuration patch file shows the different ways of configuring circuit breakers:

RequestResponse
<factories>

  <!-- Factory for CircuitBreakerInfo -->
  <factory id="TestCircuitBreakerInfoFactoryStub" type="Sitecore.XConnect.Client.Configuration.IntegrationTests.Infrastructure.CircuitBreakerInfoFactoryStub, Sitecore.XConnect.Client.Configuration.IntegrationTests" />
</factories>

<xconnect>
  <runtime type="Sitecore.XConnect.Client.Configuration.RuntimeModelConfiguration, Sitecore.XConnect.Client.Configuration">
    <schemas hint="list:AddModelConfiguration">
      <schema name="collectionmodel" type="Sitecore.XConnect.Client.Configuration.StaticModelConfiguration, Sitecore.XConnect.Client.Configuration">
        <param desc="modeltype">Sitecore.XConnect.Collection.Model.CollectionModel, Sitecore.XConnect.Collection.Model</param>
      </schema>
    </schemas>
  </runtime>

  <CircuitBreakersConfiguration type="Sitecore.XConnect.Client.WebApi.Policies.CircuitBreakerFactory, Sitecore.XConnect.Client">
    <CircuitBreakers hint="list:AddCircuitBreakerSetting">

      <!-- The General circuit breaker configuration -->
      <CircuitBreaker name="CircuitBreakerCommon"  type="Sitecore.XConnect.Client.WebApi.Policies.CircuitBreakerInfo, Sitecore.XConnect.Client" >
        <param desc="handledEventsAllowedBeforeBreaking">2</param>
        <param desc="durationOfBreak">15</param>
        <param desc="Key">General</param>
      </CircuitBreaker>

      <!--  Individual circuit breakers implemented by factories -->
      <CircuitBreaker name="CircuitBreakerCollection"  factory="TestCircuitBreakerInfoFactoryStub" ref="Collection"/> 
      <CircuitBreaker name="CircuitBreakerSearch"  factory="TestCircuitBreakerInfoFactoryStub" ref="Search"/>
      <CircuitBreaker name="CircuitBreakerConfig"  factory="TestCircuitBreakerInfoFactoryStub" ref="Config"/>
    </CircuitBreakers>
  </CircuitBreakersConfiguration>

  <clientconfig name="collectionsearch" type="Sitecore.XConnect.Client.Configuration.IntegrationTests.Infrastructure.InstanceControlledTestSitecoreXConnectClientConfiguration, Sitecore.XConnect.Client.Configuration.IntegrationTests" singleInstance="true" role:require="Standalone or ContentManagement">
    <param desc="clientModel" ref="xconnect/runtime" />
    <param desc="collectionConnectionStringName">xconnect.collection</param>
    <param desc="searchConnectionStringName">xconnect.collection</param>
    <param desc="configurationConnectionStringName">xconnect.collection</param>

    <!-- Send CircuitBreakerFactory to Configuration -->
    <param desc="CircuitBreakerFactory" ref="xconnect/CircuitBreakersConfiguration"/>
  </clientconfig>

   <!-- Collection only XConnect Client configuration for Content Delivery, Processing, or Reporting but not Content Management or Standalone -->
  <clientconfig name="collectiononly" type="Sitecore.XConnect.Client.Configuration.IntegrationTests.Infrastructure.InstanceControlledTestSitecoreXConnectClientConfiguration, Sitecore.XConnect.Client.Configuration.IntegrationTests" singleInstance="true" role:require="ContentDelivery or Processing or Reporting and !ContentManagement and !Standalone">
    <param desc="clientModel" ref="xconnect/runtime" />
    <param desc="collectionConnectionStringName">xconnect.collection</param>
    <param desc="configurationConnectionStringName">xconnect.collection</param>

    <!--Send CircuitBreakerFactory to Configuration -->
    <param desc="CircuitBreakerFactory" ref="xconnect/CircuitBreakersConfiguration"/>
  </clientconfig>
</xconnect>

Do you have some feedback for us?

If you have suggestions for improving this article,