Troubleshoot workflow errors in SharePoint 2013

Очередная встреча Ukrainian SharePoint User Group.
Тема - Отслеживание и исправление ошибок в рабочих процессах платформы SharePoint 2013.
На встрече детально пройдемся по:
1. Структура баз данных Workflows Manager.
2. Тонкости в написании собственных активностей.
3. Методы исправления подвисших процессов.
4. Распространенные ошибки 429, 423, 500 и т.д. Как с ними бороться.

Информация о встрече - https://www.facebook.com/events/1298149856878288/

Презентацию можно скачать здесь - WorkflowManager

Также предоставляю ряд SQL скриптов, которые помогут Вам в получении нужной информации о проблемных рабочих процессах:

Получение повисших экземпляров процессов

USE [WFInstanceManagementDB]
GO
SELECT i.WorkflowStatus, i.WorkflowStatusDetails, m.Value, i.InstanceId, i.InstanceCounter, ',', i.SequenceNumber
FROM [dbo].[Instances] i
inner join [WFInstanceManagementDB].[dbo].[MappedVariables] m ON m.InstanceId = i.InstanceId
where i.WorkflowStatus = 'SystemSuspended' and m.Name = 'Microsoft.SharePoint.ActivationProperties.CurrentItemUrl'
order by m.Value
         GO

Получение состояния запущенных экземпляров процессов

SELECT mm.BodyId, ',', mm.SessionId, mm.SequenceNumber, ',', i.WorkflowStatus, m.Value, i.WorkflowStatusDetails, i.InstanceId
FROM [SBMessageContainer01].[dbo].[MessageReferencesTable] mm
inner join [WFInstanceManagementDB].[dbo].[Instances] i ON i.SessionId = mm.SessionId
inner join [WFInstanceManagementDB].[dbo].[MappedVariables] m ON m.InstanceId = i.InstanceId
--inner join [SBMessageContainer01].[dbo].ScheduledMessagesTable s ON mm.BodyId = s.SequenceNumber
where m.Name = 'Microsoft.SharePoint.ActivationProperties.CurrentItemUrl'
--and i.WorkflowStatus = 'SystemSuspended'
order by i.WorkflowStatus

Получение экземпляров процессов с ошибкой 429

DECLARE @ftable TABLE (RecordNumber int, InstanceId nvarchar(50))
DECLARE @stable TABLE (RecordNumber int, InstanceId nvarchar(50))
insert into @stable
select MAX(d.RecordNumber) as 'RecordNumber', i.InstanceId from DebugTraces d
inner join Instances i ON i.InstanceId = d.InstanceId
where d.Name = 'HttpRequestSucceeded' and i.WorkflowStatus = 'Started'
group by i.InstanceId
insert into @ftable
select MAX(d.RecordNumber) as 'RecordNumber', i.InstanceId from DebugTraces d
inner join Instances i ON i.InstanceId = d.InstanceId
where d.Message like '%429%' and i.WorkflowStatus = 'Started'
group by i.InstanceId
select s.InstanceId, m.Value from @stable s
inner join @ftable f ON f.InstanceId = s.InstanceId
inner join [WFInstanceManagementDB].[dbo].[MappedVariables] m ON m.InstanceId = s.InstanceId
where f.RecordNumber > s.RecordNumber and m.Name = 'Microsoft.SharePoint.ActivationProperties.CurrentItemUrl'

И также предоставляю часть исходного кода, с помощью которого можно остановить или восстановить работу рабочего процесса

using (var clientContext =
                    TokenHelper.GetClientContextWithAccessToken(
                        siteUri.ToString(), accessToken))
                {
                    string mass = @"a4e09588-da44-4ade-8417-1f5dcf5154e2";
                    var result = mass.Replace("\r\n", "").Split(',');
                    Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager spWorkflowServicesManager = new Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager(clientContext, clientContext.Web);
                    foreach (string str in result)
                    {
                        if (str != "")
                        {
                           Microsoft.SharePoint.Client.WorkflowServices.WorkflowInstance spWorkflownInstance = spWorkflowServicesManager.GetWorkflowInstanceService().GetInstance(new Guid(str));
                            spWorkflowServicesManager.GetWorkflowInstanceService().TerminateWorkflow(spWorkflownInstance);
                            clientContext.ExecuteQuery();
                        }
                    }
}