Skip to content

Commit a6ae35e

Browse files
fix: adding automatic retries to durable function (#1706)
* fix: adding automatic retries to durrable function * fix: fixing unit tests * fix: fixing sonar cube issue * fix: changing MaxRetryCount to a private varible * fix: adding MaxRetryCount to config and cod clean up
1 parent 1c0aea5 commit a6ae35e

File tree

11 files changed

+70
-83
lines changed

11 files changed

+70
-83
lines changed

application/CohortManager/compose.core.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ services:
337337
- ExceptionFunctionURL=http://create-exception:7070/api/CreateException
338338
- AzureWebJobsStorage=${AZURITE_CONNECTION_STRING}
339339
- AcceptableLatencyThresholdMs=500
340+
- MaxRetryCount=3
340341

341342
# Service Now Integration Service
342343
servicenow-message-handler:
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
namespace NHS.Screening.DemographicDurableFunction;
1+
namespace NHS.CohortManager.DemographicServices;
22

33
using System.ComponentModel.DataAnnotations;
44

55
public class DemographicDurableFunctionConfig
66
{
77
[Required]
8-
public string DemographicDataServiceURL {get; set;}
8+
public string DemographicDataServiceURL { get; set; }
9+
10+
[Required]
11+
public int MaxRetryCount { get; set; }
912
}

application/CohortManager/src/Functions/DemographicServices/DemographicDurableFunction/DurableDemographicFunction.cs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
namespace NHS.CohortManager.DemographicServices;
22

33
using System.Net;
4+
45
using System.Text;
56
using System.Text.Json;
67
using Common;
78
using DataServices.Client;
8-
using Microsoft.AspNetCore.Components;
99
using Microsoft.Azure.Functions.Worker;
1010
using Microsoft.Azure.Functions.Worker.Http;
1111
using Microsoft.DurableTask;
1212
using Microsoft.DurableTask.Client;
1313
using Microsoft.Extensions.Logging;
14+
using Microsoft.Extensions.Options;
1415
using Model;
1516

1617
public class DurableDemographicFunction
@@ -19,12 +20,15 @@ public class DurableDemographicFunction
1920
private readonly ILogger<DurableDemographicFunction> _logger;
2021
private readonly ICreateResponse _createResponse;
2122

23+
private readonly DemographicDurableFunctionConfig _config;
24+
2225

23-
public DurableDemographicFunction(IDataServiceClient<ParticipantDemographic> dataServiceClient, ILogger<DurableDemographicFunction> logger, ICreateResponse createResponse)
26+
public DurableDemographicFunction(IDataServiceClient<ParticipantDemographic> dataServiceClient, ILogger<DurableDemographicFunction> logger, ICreateResponse createResponse, IOptions<DemographicDurableFunctionConfig> demographicDurableFunctionConfig)
2427
{
2528
_participantDemographic = dataServiceClient;
2629
_logger = logger;
2730
_createResponse = createResponse;
31+
_config = demographicDurableFunctionConfig.Value;
2832
}
2933

3034
/// <summary>
@@ -34,11 +38,9 @@ public DurableDemographicFunction(IDataServiceClient<ParticipantDemographic> dat
3438
/// <returns></returns>
3539
/// <exception cref="TimeoutException"></exception>
3640
[Function(nameof(DurableDemographicFunction))]
37-
public async Task<bool> RunOrchestrator(
41+
public async Task RunOrchestrator(
3842
[OrchestrationTrigger] TaskOrchestrationContext context)
3943
{
40-
41-
4244
try
4345
{
4446
var demographicJsonData = context.GetInput<string>();
@@ -48,24 +50,17 @@ public async Task<bool> RunOrchestrator(
4850
throw new InvalidDataException("demographicJsonData was null or empty in Orchestration function");
4951
}
5052

51-
var retryOptions = TaskOptions.FromRetryPolicy(new RetryPolicy(
52-
maxNumberOfAttempts: 1, // this means the function will not retry and therefore add duplicates
53-
firstRetryInterval: TimeSpan.FromSeconds(100))
54-
);
53+
TaskOptions retryOptions = TaskOptions.FromRetryHandler(retryContext =>
54+
{
55+
_logger.LogWarning("Retrying batch after failure. Current Retry count: {RetryCount} ", retryContext.LastAttemptNumber);
56+
return retryContext.LastAttemptNumber < _config.MaxRetryCount;
57+
});
5558

56-
// Add timeout-aware logic
57-
var recordsInserted = await context.CallActivityAsync<bool>(
59+
await context.CallActivityAsync<bool>(
5860
nameof(InsertDemographicData),
5961
demographicJsonData,
6062
options: retryOptions
6163
);
62-
63-
if (!recordsInserted)
64-
{
65-
throw new InvalidOperationException("Demographic records were not added to the database in the orchestration function");
66-
}
67-
return true;
68-
6964
}
7065
catch (Exception ex)
7166
{
@@ -81,18 +76,16 @@ public async Task<bool> RunOrchestrator(
8176
/// <param name="executionContext"></param>
8277
/// <returns></returns>
8378
[Function(nameof(InsertDemographicData))]
84-
public async Task<bool> InsertDemographicData([ActivityTrigger] string demographicJsonData, FunctionContext executionContext)
79+
public async Task InsertDemographicData([ActivityTrigger] string demographicJsonData, FunctionContext executionContext)
8580
{
86-
try
87-
{
88-
var participantData = JsonSerializer.Deserialize<List<ParticipantDemographic>>(demographicJsonData);
89-
return await _participantDemographic.AddRange(participantData);
90-
}
91-
catch (Exception ex)
81+
var participantData = JsonSerializer.Deserialize<List<ParticipantDemographic>>(demographicJsonData);
82+
var recordsInserted = await _participantDemographic.AddRange(participantData!);
83+
84+
if (!recordsInserted)
9285
{
93-
_logger.LogError(ex, "Inserting demographic data failed");
94-
return false;
86+
throw new InvalidOperationException("Demographic records were not added to the database in the orchestration function");
9587
}
88+
_logger.LogInformation("InsertDemographicData function has successfully completed");
9689
}
9790

9891

application/CohortManager/src/Functions/DemographicServices/DemographicDurableFunction/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
using Data.Database;
55
using Model;
66
using DataServices.Client;
7-
using NHS.Screening.DemographicDurableFunction;
87
using HealthChecks.Extensions;
8+
using NHS.CohortManager.DemographicServices;
99

1010
var host = new HostBuilder()
1111
.AddConfiguration<DemographicDurableFunctionConfig>(out DemographicDurableFunctionConfig config)

infrastructure/tf-core/environments/development.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ function_apps = {
865865
]
866866
env_vars_static = {
867867
AcceptableLatencyThresholdMs = "500"
868+
MaxRetryCount=3
868869
}
869870
}
870871

infrastructure/tf-core/environments/integration.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@ function_apps = {
866866
]
867867
env_vars_static = {
868868
AcceptableLatencyThresholdMs = "500"
869+
MaxRetryCount=3
869870
}
870871
}
871872

infrastructure/tf-core/environments/nft.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ function_apps = {
865865
]
866866
env_vars_static = {
867867
AcceptableLatencyThresholdMs = "500"
868+
MaxRetryCount=3
868869
}
869870
}
870871

infrastructure/tf-core/environments/preprod.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ function_apps = {
850850
]
851851
env_vars_static = {
852852
AcceptableLatencyThresholdMs = "500"
853+
MaxRetryCount=3
853854
}
854855
}
855856

infrastructure/tf-core/environments/production.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ function_apps = {
884884
]
885885
env_vars_static = {
886886
AcceptableLatencyThresholdMs = "500"
887+
MaxRetryCount=3
887888
}
888889
}
889890

infrastructure/tf-core/environments/sandbox.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ function_apps = {
917917
]
918918
env_vars_static = {
919919
AcceptableLatencyThresholdMs = "500"
920+
MaxRetryCount=3
920921
}
921922
}
922923

0 commit comments

Comments
 (0)