Skip to content

Commit

Permalink
fix: activation failures due to process dependencies (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
ewingjm authored Jan 31, 2022
1 parent 86e5d36 commit e89ac6e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Polly;

/// <summary>
/// Deployment functionality relating to processes.
Expand Down Expand Up @@ -103,7 +104,55 @@ private void SetStates(IEnumerable<Entity> processes, IEnumerable<string> proces
this.logger.LogInformation($"Activating processes as {user}.");
}

var requests = this.GetSetStateRequests(processes, processesToDeactivate);

if (!requests.Any())
{
return;
}

this.ExecuteSetStateRequests(requests, user);
}

private void ExecuteSetStateRequests(IEnumerable<OrganizationRequest> requests, string user = null)
{
// Due to unpredictable process dependencies we should retry failed requests until there are zero successful responses.
var remainingRequests = new List<OrganizationRequest>(requests);
IEnumerable<ExecuteMultipleResponseItem> successfulResponses;
IEnumerable<ExecuteMultipleResponseItem> failedResponses;

do
{
var timeout = 120 + (remainingRequests.Count * 10);
var executeMultipleRes = string.IsNullOrEmpty(user) ?
this.crmSvc.ExecuteMultiple(remainingRequests, true, true, timeout) : this.crmSvc.ExecuteMultiple(remainingRequests, user, true, true, timeout);

successfulResponses = executeMultipleRes.Responses
.Where(r => r.Fault == null)
.ToList();
failedResponses = executeMultipleRes.Responses
.Except(successfulResponses)
.ToList();
remainingRequests = failedResponses
.Select(r => remainingRequests[r.RequestIndex])
.ToList();
}
while (successfulResponses.Any() && remainingRequests.Count > 0);

if (!successfulResponses.Any() && remainingRequests.Any())
{
foreach (var failedResponse in failedResponses)
{
var failedRequest = (SetStateRequest)remainingRequests[failedResponse.RequestIndex];
this.logger.LogError($"Failed to set state for process {failedRequest.EntityMoniker.Name} with the following error: {failedResponse.Fault.Message}.");
}
}
}

private List<OrganizationRequest> GetSetStateRequests(IEnumerable<Entity> processes, IEnumerable<string> processesToDeactivate)
{
var requests = new List<OrganizationRequest>();

foreach (var deployedProcess in processes)
{
var stateCode = new OptionSetValue(Constants.Workflow.StateCodeActive);
Expand Down Expand Up @@ -133,24 +182,7 @@ private void SetStates(IEnumerable<Entity> processes, IEnumerable<string> proces
});
}

if (!requests.Any())
{
return;
}

var timeout = 120 + (requests.Count * 10);
var executeMultipleRes = string.IsNullOrEmpty(user) ?
this.crmSvc.ExecuteMultiple(requests, true, true, timeout) : this.crmSvc.ExecuteMultiple(requests, user, true, true, timeout);

if (executeMultipleRes.IsFaulted)
{
this.logger.LogError("Error(s) encountered when setting process states.");
foreach (var failedResponse in executeMultipleRes.Responses.Where(r => r.Fault != null))
{
var failedRequest = (SetStateRequest)requests[failedResponse.RequestIndex];
this.logger.LogError($"Failed to set state for process {failedRequest.EntityMoniker.Name} with the following error: {failedResponse.Fault.Message}.");
}
}
return requests;
}

private EntityCollection RetrieveProcesses(IEnumerable<string> names)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ private void MockExecuteMultipleResponse(ExecuteMultipleResponse response = null
if (response == null)
{
response = new ExecuteMultipleResponse();
response.Results["Responses"] = new ExecuteMultipleResponseItemCollection();
}

var returnResult = this.crmServiceAdapterMock
Expand Down

0 comments on commit e89ac6e

Please sign in to comment.