Skip to content

Commit 5a70147

Browse files
authored
MMI-3346 Notification Service (#2491)
1 parent 8eeabb4 commit 5a70147

File tree

6 files changed

+71
-19
lines changed

6 files changed

+71
-19
lines changed

libs/net/ches/ChesService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.IdentityModel.Tokens.Jwt;
22
using System.Security.Claims;
33
using System.Text;
4+
using System.Text.Json;
45
using System.Text.RegularExpressions;
56
using System.Web;
67
using Microsoft.Extensions.Logging;
@@ -182,6 +183,11 @@ private async Task<string> SendAsync(string endpoint, HttpMethod method)
182183
_logger.LogError(ex, "Failed to send/receive request: {code} {url}. Error: {error}", ex.StatusCode, url, ex.GetAllMessages());
183184
throw new ChesException("Failed to send message to CHES", ex);
184185
}
186+
catch (Exception ex)
187+
{
188+
_logger.LogError(ex, "Failed to send/receive request: {url}. Error: {error}", url, ex.GetAllMessages());
189+
throw new ChesException("Failed to send message to CHES", ex);
190+
}
185191
}
186192

187193
/// <summary>

libs/net/core/Exceptions/HttpClientRequestException.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public HttpClientRequestException(string message, Exception innerException, Http
4949
public HttpClientRequestException(HttpResponseMessage response) : base($"HTTP Request failed [{response?.RequestMessage?.Method}]:[{response?.StatusCode}]:{response?.RequestMessage?.RequestUri}", null, response?.StatusCode)
5050
{
5151
this.Response = response ?? throw new ArgumentNullException(nameof(response));
52-
this.Data["Body"] = response.Content.ReadAsStringAsync().Result;
5352
}
5453

5554
/// <summary>
@@ -60,7 +59,6 @@ public HttpClientRequestException(HttpResponseMessage response) : base($"HTTP Re
6059
public HttpClientRequestException(HttpResponseMessage response, string message) : base(message, null, response?.StatusCode)
6160
{
6261
this.Response = response ?? throw new ArgumentNullException(nameof(response));
63-
this.Data["Body"] = response.Content.ReadAsStringAsync().Result;
6462
}
6563

6664
/// <summary>
@@ -71,7 +69,6 @@ public HttpClientRequestException(HttpResponseMessage response, string message)
7169
public HttpClientRequestException(HttpResponseMessage response, Exception innerException) : base($"HTTP Request failed [{response?.RequestMessage?.Method}]:[{response?.StatusCode}]:{response?.RequestMessage?.RequestUri}", innerException, response?.StatusCode)
7270
{
7371
this.Response = response ?? throw new ArgumentNullException(nameof(response));
74-
this.Data["Body"] = response.Content.ReadAsStringAsync().Result;
7572
}
7673
#endregion
7774
}

libs/net/services/Helpers/ApiService.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ protected async Task<T> RetryRequestAsync<T>(Func<Task<T>> callbackDelegate)
105105
this.FailureCount = 0;
106106
return response;
107107
}
108+
catch (HttpClientRequestException ex)
109+
{
110+
if (this.Options.RetryLimit <= ++this.FailureCount)
111+
{
112+
this.FailureCount = 0;
113+
throw;
114+
}
115+
116+
// Wait before retrying.
117+
var response = ex.Response?.Content.ReadAsStringAsync().Result;
118+
this.Logger.LogError(ex, "Retry attempt {count}.{newline}Error:{body}", this.FailureCount, Environment.NewLine, response);
119+
await Task.Delay(this.Options.RetryDelayMS);
120+
return await RetryRequestAsync<T>(callbackDelegate);
121+
}
108122
catch (Exception ex)
109123
{
110124
if (this.Options.RetryLimit <= ++this.FailureCount)
@@ -114,7 +128,7 @@ protected async Task<T> RetryRequestAsync<T>(Func<Task<T>> callbackDelegate)
114128
}
115129

116130
// Wait before retrying.
117-
this.Logger.LogError(ex, "Retry attempt {count}.{newline}Error:{body}", this.FailureCount, Environment.NewLine, ex.Data["Body"]);
131+
this.Logger.LogError(ex, "Retry attempt {count}", this.FailureCount);
118132
await Task.Delay(this.Options.RetryDelayMS);
119133
return await RetryRequestAsync<T>(callbackDelegate);
120134
}
@@ -138,11 +152,11 @@ public async Task<T> HandleConcurrencyAsync<T>(Func<Task<T>> callbackDelegate)
138152
catch (HttpClientRequestException ex)
139153
{
140154
// If it's a concurrency error, keep trying. Otherwise throw the error.
155+
var response = ex.Response?.Content.ReadAsStringAsync().Result;
141156
this.Logger.LogError(ex, "Failed to complete request. Determining if this is a concurrency error.");
142-
var data = ex.Data["Body"] as string;
143-
if (!String.IsNullOrWhiteSpace(data))
157+
if (!String.IsNullOrWhiteSpace(response))
144158
{
145-
var json = JsonSerializer.Deserialize<API.Models.ErrorResponseModel>(data, _serializerOptions);
159+
var json = JsonSerializer.Deserialize<API.Models.ErrorResponseModel>(response, _serializerOptions);
146160
if (json != null && json.Type == nameof(Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException))
147161
{
148162
// A concurrency error can be resolved by loading the latest and reapplying the values.

libs/net/services/Managers/IngestManager`.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using TNO.API.Areas.Services.Models.Ingest;
55
using TNO.Ches;
66
using TNO.Ches.Configuration;
7+
using TNO.Core.Exceptions;
78
using TNO.Services.Config;
89

910
namespace TNO.Services.Managers;
@@ -124,7 +125,7 @@ public override async Task RunAsync()
124125

125126
if (!theLatest.IsEnabled ||
126127
!theLatest.IngestSchedules.Any(d => d.Schedule?.IsEnabled == true) ||
127-
!theLatest.DataLocations.Any(d => d.Name.ToLower() == Options.DataLocation.ToLower()))
128+
!theLatest.DataLocations.Any(d => d.Name.Equals(Options.DataLocation, StringComparison.CurrentCultureIgnoreCase)))
128129
{
129130
await manager.StopAsync();
130131
continue;
@@ -172,9 +173,10 @@ public override async Task RunAsync()
172173
// Successful run clears any errors.
173174
this.State.ResetFailures();
174175
}
175-
catch (HttpRequestException ex)
176+
catch (HttpClientRequestException ex)
176177
{
177-
this.Logger.LogError(ex, "Ingest [{name}] failed to run. This is failure [{failures}] out of [{maxFailures}] maximum retries. Response: {Data}", ingest.Name, manager.Ingest.FailedAttempts + 1, manager.Ingest.RetryLimit, ex.Data["Body"]);
178+
var response = ex.Response?.Content.ReadAsStringAsync().Result;
179+
this.Logger.LogError(ex, "Ingest [{name}] failed to run. This is failure [{failures}] out of [{maxFailures}] maximum retries. Response: {Data}", ingest.Name, manager.Ingest.FailedAttempts + 1, manager.Ingest.RetryLimit, response);
178180

179181
// Update ingest with failure.
180182
await manager.RecordFailureAsync(ex);

services/net/extract-quotes/CoreNLP/CoreNLPService.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
using TNO.Core.Http;
1+
using Microsoft.Extensions.Logging;
22
using Microsoft.Extensions.Options;
3+
using TNO.API.Areas.Services.Models.Content;
4+
using TNO.Core.Exceptions;
5+
using TNO.Core.Http;
36
using TNO.Services.ExtractQuotes.Config;
47
using TNO.Services.ExtractQuotes.CoreNLP.models;
5-
using Microsoft.Extensions.Logging;
6-
using TNO.API.Areas.Services.Models.Content;
78

89
namespace TNO.Services.NLP.ExtractQuotes;
910

10-
public interface ICoreNLPService {
11+
public interface ICoreNLPService
12+
{
1113
Task<AnnotationResponse?> PerformAnnotation(string text);
1214
Task<AnnotationResponse?> PerformAnnotationWithExistingQuotes(string text, IEnumerable<QuoteModel> existingQuotes);
1315
}
1416

1517
/// <summary>
1618
/// CoreNLPService class, provides a wrapper service for the Core NLP API.
1719
/// </summary>
18-
public class CoreNLPService: ICoreNLPService
20+
public class CoreNLPService : ICoreNLPService
1921
{
2022
#region Properties
2123
/// <summary>
@@ -97,6 +99,20 @@ protected async Task<T> RetryRequestAsync<T>(Func<Task<T>> callbackDelegate)
9799
this.FailureCount = 0;
98100
return response;
99101
}
102+
catch (HttpClientRequestException ex)
103+
{
104+
if (this.Options.RetryLimit <= ++this.FailureCount)
105+
{
106+
this.FailureCount = 0;
107+
throw;
108+
}
109+
110+
var response = ex.Response?.Content.ReadAsStringAsync().Result;
111+
// Wait before retrying.
112+
this.Logger.LogError(ex, "Retry attempt {count}.{newline}Error:{body}", this.FailureCount, Environment.NewLine, response);
113+
await Task.Delay(this.Options.RetryDelayMS);
114+
return await RetryRequestAsync<T>(callbackDelegate);
115+
}
100116
catch (Exception ex)
101117
{
102118
if (this.Options.RetryLimit <= ++this.FailureCount)
@@ -106,7 +122,7 @@ protected async Task<T> RetryRequestAsync<T>(Func<Task<T>> callbackDelegate)
106122
}
107123

108124
// Wait before retrying.
109-
this.Logger.LogError(ex, "Retry attempt {count}.{newline}Error:{body}", this.FailureCount, Environment.NewLine, ex.Data["Body"]);
125+
this.Logger.LogError(ex, "Retry attempt {count}.", this.FailureCount);
110126
await Task.Delay(this.Options.RetryDelayMS);
111127
return await RetryRequestAsync<T>(callbackDelegate);
112128
}
@@ -141,4 +157,4 @@ protected async Task<T> RetryRequestAsync<T>(Func<Task<T>> callbackDelegate)
141157
return await PerformAnnotation(text);
142158
}
143159
#endregion
144-
}
160+
}

services/net/extract-quotes/LLM/Clients/LLMClient.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Text.Json;
44
using Microsoft.Extensions.Logging;
55
using Microsoft.Extensions.Options;
6+
using TNO.Core.Exceptions;
67
using TNO.Core.Http;
78
using TNO.Services.ExtractQuotes.Config;
89
using TNO.Services.ExtractQuotes.LLM.Models;
@@ -61,7 +62,7 @@ public LLMClient(
6162
{
6263
return await callbackDelegate();
6364
}
64-
catch (Exception ex)
65+
catch (HttpClientRequestException ex)
6566
{
6667
// Use Interlocked.Increment for thread-safe increment and wrap-around
6768
int currentFailureCount = Interlocked.Increment(ref _failureCount);
@@ -71,9 +72,25 @@ public LLMClient(
7172
throw;
7273
}
7374

75+
var response = ex.Response?.Content.ReadAsStringAsync().Result;
7476
// Wait before retrying
7577
_logger.LogError(ex, "LLM API retry attempt {count}.{newline}Error:{body}",
76-
currentFailureCount, Environment.NewLine, ex.Data["Body"]);
78+
currentFailureCount, Environment.NewLine, response);
79+
await Task.Delay(_options.RetryDelayMS);
80+
return await RetryRequestAsync<T>(callbackDelegate);
81+
}
82+
catch (Exception ex)
83+
{
84+
// Use Interlocked.Increment for thread-safe increment and wrap-around
85+
int currentFailureCount = Interlocked.Increment(ref _failureCount);
86+
if (_options.RetryLimit <= currentFailureCount)
87+
{
88+
Interlocked.Exchange(ref _failureCount, 0); // Reset the counter
89+
throw;
90+
}
91+
92+
// Wait before retrying
93+
_logger.LogError(ex, "LLM API retry attempt {count}.", currentFailureCount);
7794
await Task.Delay(_options.RetryDelayMS);
7895
return await RetryRequestAsync<T>(callbackDelegate);
7996
}

0 commit comments

Comments
 (0)