The Sitecore Messaging library can be configured to retry connecting to the SQL database in case a connection error occurs. The Sitecore.Framework.TransientFaultHandling library is used to provide the retry functionality. The following steps are required to configure Messaging to use the connection retrying behavior.
The following example defines an Exponential Retryer that will fail after retrying to connect to the database 10 times.
The DefaultSqlPolicyRetryerFactory creates a retryer that, by default, can handle SQL Always On and SQL Azure transient errors. Additional error codes can be added under the CustomErrorCodes section:
<Settings> <Sitecore> <XConnect> <Services> <TransientFaultHandling> <Type>Sitecore.Framework.TransientFaultHandling.RetryerRegistry, Sitecore.Framework.TransientFaultHandling</Type> <As>Sitecore.Framework.TransientFaultHandling.IRetryerRegistry, Sitecore.Framework.TransientFaultHandling.Abstractions</As> <Options> <Retryers> <Messaging.ExponentialRetryer> <Type>Sitecore.Framework.TransientFaultHandling.Sql.DefaultSqlPolicyRetryerFactory, Sitecore.Framework.TransientFaultHandling.Sql</Type> <Options> <CustomErrorCodes> <ConnectionError>19</ConnectionError> </CustomErrorCodes> <ExponentialRetry> <MaxAttempts>10</MaxAttempts> <MinBackoff>00:00:01</MinBackoff> <MaxBackoff>00:00:30</MaxBackoff> <DeltaBackoff>00:00:10</DeltaBackoff> </ExponentialRetry> </Options> </Messaging.ExponentialRetryer> </Retryers> </Options> </TransientFaultHandling> </Services> </XConnect> </Sitecore> </Settings>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <TransientFaultHandling> <Retryers> <Messaging.ExponentialRetryer> <Type>Sitecore.Framework.TransientFaultHandling.Sql.DefaultSqlPolicyRetryerFactory, Sitecore.Framework.TransientFaultHandling.Sql</Type> <Options> <CustomErrorCodes> <ConnectionError>19</ConnectionError> </CustomErrorCodes> <ExponentialRetry> <MaxAttempts>10</MaxAttempts> <MinBackoff>00:00:01</MinBackoff> <MaxBackoff>00:00:30</MaxBackoff> <DeltaBackoff>00:00:10</DeltaBackoff> </ExponentialRetry> </Options> </Messaging.ExponentialRetryer> </Retryers> </TransientFaultHandling> </sitecore> </configuration>
<Settings> <Sitecore> <Processing> <Services> <RetryerRegistry> <Options> <Retryers> <ExponentialRetryer> <Type>Sitecore.Framework.TransientFaultHandling.Sql.DefaultSqlPolicyRetryerFactory, Sitecore.Framework.TransientFaultHandling.Sql</Type> <Options> <CustomErrorCodes> <ConnectionError>19</ConnectionError> </CustomErrorCodes> <ExponentialRetry> <MaxAttempts>10</MaxAttempts> <MinBackoff>00:00:01</MinBackoff> <MaxBackoff>00:00:30</MaxBackoff> <DeltaBackoff>00:00:10</DeltaBackoff> </ExponentialRetry> </Options> </ExponentialRetryer> </Retryers> </Options> </RetryerRegistry> </Services> </Processing> </Sitecore> </Settings>
In order to configure a Messaging Bus to use TransientFaultHandling retryers, the Messaging transport needs to explicitly specify the retryer in its configuration. This can be done via the following configuration:
<Sitecore.Processing.Engine.Buses.TaskProgressConsumer> <Transport> <SqlServer> <OneWay>false</OneWay> <ConnectionStringOrName>messaging</ConnectionStringOrName> <TableName>Sitecore_Transport</TableName> <InputQueueName>SitecoreProcessingTaskProgressConsumer</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> <Logging Type="Sitecore.Framework.Messaging.Rebus.DotNetLoggerFactory, Sitecore.Framework.Messaging.Rebus" /> </Sitecore.Processing.Engine.Buses.TaskProgressConsumer>
<Sitecore.Processing.Engine.Buses.TaskRegistrationConsumer> <Transport> <SqlServer> <OneWay>false</OneWay> <ConnectionStringOrName>messaging</ConnectionStringOrName> <TableName>Sitecore_Transport</TableName> <InputQueueName>SitecoreProcessingTaskRegistrationConsumer</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> <Logging Type="Sitecore.Framework.Messaging.Rebus.DotNetLoggerFactory, Sitecore.Framework.Messaging.Rebus" /> </Sitecore.Processing.Engine.Buses.TaskRegistrationConsumer>
<Sitecore.Processing.Engine.Abstractions.Buses.TaskStatusBus> <Transport> <SqlServer> <OneWay>false</OneWay> <!--Set of credentials for proper connection to database--> <ConnectionStringOrName>messaging</ConnectionStringOrName> <!--The name of the table which holds messages until they are handled--> <TableName>Sitecore_Transport</TableName> <!--The name of MSMQ queue which publisher uses for publishing message to the bus--> <InputQueueName>TaskStatus</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> <Subscriptions> <SqlServer> <!--Set of credentials for proper connection to database--> <ConnectionStringOrName>messaging</ConnectionStringOrName> <!--The name of the table which saves the information about the relationships between queues and messages--> <TableName>Sitecore_Subscriptions</TableName> <!--Means that both subscribers and publishers have access to the same central subscription storage--> <IsCentralized>true</IsCentralized> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Subscriptions> <Logging Type="Sitecore.Framework.Messaging.Rebus.DotNetLoggerFactory, Sitecore.Framework.Messaging.Rebus" /> </Sitecore.Processing.Engine.Abstractions.Buses.TaskStatusBus>
<Sitecore.Processing.Tasks.Messaging.Buses.TaskRegistrationProducer> <Transport> <SqlServer> <OneWay>false</OneWay> <ConnectionStringOrName>messaging</ConnectionStringOrName> <TableName>Sitecore_Transport</TableName> <!-- InputQueueName should be unique for CM/CD instance to handle response messages on the correct instance. --> <InputQueueName>SitecoreProcessingTaskRegistrationProducer_${MachineName}_${ProcessId}</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> <Routing> <TypeBasedMappings> <TypeMappings> <RegisterDistributedTaskMap> <Type>Sitecore.Processing.Engine.Abstractions.Messages.RegisterDistributedTask, Sitecore.Processing.Engine.Abstractions</Type> <DestinationQueue>SitecoreProcessingTaskRegistrationConsumer</DestinationQueue> </RegisterDistributedTaskMap> <RegisterDeferredTaskMap> <Type>Sitecore.Processing.Engine.Abstractions.Messages.RegisterDeferredTask, Sitecore.Processing.Engine.Abstractions</Type> <DestinationQueue>SitecoreProcessingTaskRegistrationConsumer</DestinationQueue> </RegisterDeferredTaskMap> </TypeMappings> </TypeBasedMappings> </Routing> <Logging Type="Sitecore.Messaging.SitecoreLoggerFactory,Sitecore.Messaging"/> </Sitecore.Processing.Tasks.Messaging.Buses.TaskRegistrationProducer>
In order to configure EXM to use retryers, Sitecore.EmailExperience.Messaging.config files on corresponding servers should be updated.
For example:
<Sitecore.EmailCampaign.Model.Messaging.Buses.UpdateListSubscriptionMessagesBus role:require="!DedicatedDispatch"> <Transport> <SqlServer> <OneWay role:require="(Standalone or ContentManagement) and !ContentDelivery">false</OneWay> <OneWay role:require="ContentDelivery">true</OneWay> <ConnectionStringOrName>messaging</ConnectionStringOrName> <TableName>Sitecore_Transport</TableName> <InputQueueName>UpdateListSubscriptionMessagesQueue</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> </Sitecore.EmailCampaign.Model.Messaging.Buses.UpdateListSubscriptionMessagesBus>
For example:
<Sitecore.EmailCampaign.Model.Messaging.Buses.AutomatedMessagesBus> <Transport> <SqlServer> <OneWay>true</OneWay> <ConnectionStringOrName>messaging</ConnectionStringOrName> <TableName>Sitecore_Transport</TableName> <InputQueueName>AutomatedMessagesQueue</InputQueueName> <RetryerName>ExponentialRetryer</RetryerName> </SqlServer> </Transport> <Sitecore.EmailCampaign.Model.Messaging.Buses.AutomatedMessagesBus>