From dc4d4ff1d36030a4192133a3b62707e9c59c828c Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Fri, 30 Aug 2024 22:28:31 -0500 Subject: [PATCH] feat: begin working on adding search result back into Onspring --- .../Interfaces/IOnspringService.cs | 1 + .../Models/SearchRequest.cs | 1 + .../Models/SearchResult.cs | 6 ++ src/SanctionsSearch.Worker/Program.cs | 21 ++--- .../Services/OnspringService.cs | 78 +++++++++++++++---- 5 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/SanctionsSearch.Worker/Models/SearchResult.cs diff --git a/src/SanctionsSearch.Worker/Interfaces/IOnspringService.cs b/src/SanctionsSearch.Worker/Interfaces/IOnspringService.cs index d5cd0ee..7b16ebb 100644 --- a/src/SanctionsSearch.Worker/Interfaces/IOnspringService.cs +++ b/src/SanctionsSearch.Worker/Interfaces/IOnspringService.cs @@ -3,4 +3,5 @@ namespace SanctionsSearch.Worker.Interfaces; interface IOnspringService { Task> GetSearchRequestsAsync(); + Task AddSearchResultAsync(SearchResult result); } \ No newline at end of file diff --git a/src/SanctionsSearch.Worker/Models/SearchRequest.cs b/src/SanctionsSearch.Worker/Models/SearchRequest.cs index ced813c..f4bb54f 100644 --- a/src/SanctionsSearch.Worker/Models/SearchRequest.cs +++ b/src/SanctionsSearch.Worker/Models/SearchRequest.cs @@ -2,6 +2,7 @@ namespace SanctionsSearch.Worker.Models; class SearchRequest { + public int Id { get; init; } public string Name { get; set; } = string.Empty; public string Address { get; set; } = string.Empty; public string City { get; set; } = string.Empty; diff --git a/src/SanctionsSearch.Worker/Models/SearchResult.cs b/src/SanctionsSearch.Worker/Models/SearchResult.cs new file mode 100644 index 0000000..4ea39d5 --- /dev/null +++ b/src/SanctionsSearch.Worker/Models/SearchResult.cs @@ -0,0 +1,6 @@ +namespace SanctionsSearch.Worker.Models; + +class SearchResult +{ + // TODO: Add properties to represent the search result +} \ No newline at end of file diff --git a/src/SanctionsSearch.Worker/Program.cs b/src/SanctionsSearch.Worker/Program.cs index 2a05916..2c1d0d3 100644 --- a/src/SanctionsSearch.Worker/Program.cs +++ b/src/SanctionsSearch.Worker/Program.cs @@ -69,17 +69,18 @@ class Program builder.Services.AddSingleton(TimeProvider.System); - builder.Services - .AddHttpClient() - .AddStandardResilienceHandler(); + builder.Services.AddHttpClient(); + builder.Services.ConfigureHttpClientDefaults(builder => builder.AddStandardResilienceHandler()); + builder.Services.AddScoped(sp => + { + var options = sp.GetRequiredService(); + var httpClient = sp.GetRequiredService(); + httpClient.BaseAddress = new Uri(options.BaseUrl); + return new OnspringClient(options.ApiKey, httpClient); + }); - builder.Services - .AddHttpClient((sp, client) => - { - var options = sp.GetRequiredService(); - client.BaseAddress = new Uri(options.BaseUrl); - }) - .AddStandardResilienceHandler(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/src/SanctionsSearch.Worker/Services/OnspringService.cs b/src/SanctionsSearch.Worker/Services/OnspringService.cs index 7ebb4ae..5a8a015 100644 --- a/src/SanctionsSearch.Worker/Services/OnspringService.cs +++ b/src/SanctionsSearch.Worker/Services/OnspringService.cs @@ -1,26 +1,39 @@ + namespace SanctionsSearch.Worker.Services; class OnspringService( - HttpClient httpClient, + IOnspringClient client, OnspringOptions options, ILogger logger ) : IOnspringService { - private readonly IOnspringClient _client = new OnspringClient(options.ApiKey, httpClient); + private readonly OnspringOptions _options = options; private readonly ILogger _logger = logger; + private readonly IOnspringClient _client = client; + + public Task AddSearchResultAsync(SearchResult result) + { + // TODO: Implement this method + // - we should add a new record for each hit + // - each new hit record should reference the request + // - we should update the request status to processed + // - we should return a Result indicating success or failure + throw new NotImplementedException(); + } public async Task> GetSearchRequestsAsync() { var queryRequest = new QueryRecordsRequest() { - AppId = options.SearchRequestOptions.AppId, + AppId = _options.SearchRequestOptions.AppId, + Filter = $"{_options.SearchRequestOptions.StatusFieldId} contains '{_options.SearchRequestOptions.AwaitingProcessingStatusId}'", FieldIds = [ - options.SearchRequestOptions.NameFieldId, - options.SearchRequestOptions.AddressFieldId, - options.SearchRequestOptions.CityFieldId, - options.SearchRequestOptions.StateFieldId, - options.SearchRequestOptions.ZipFieldId, - options.SearchRequestOptions.CountryFieldId + _options.SearchRequestOptions.NameFieldId, + _options.SearchRequestOptions.AddressFieldId, + _options.SearchRequestOptions.CityFieldId, + _options.SearchRequestOptions.StateFieldId, + _options.SearchRequestOptions.ZipFieldId, + _options.SearchRequestOptions.CountryFieldId ], }; @@ -42,7 +55,35 @@ class OnspringService( if (initialResponse.Value.HasMorePages()) { - // TODO: Fan out and collect remaining pages + var remainingPageNumbers = Enumerable.Range(initialResponse.Value.PageNumber + 1, initialResponse.Value.TotalPages - 1); + var pagingRequests = remainingPageNumbers.Select(num => new PagingRequest { PageNumber = num }); + var remainingRequests = pagingRequests.Select(async pageRequest => + { + try + { + var res = await _client.QueryRecordsAsync(queryRequest, pageRequest); + + if (res.IsSuccessful is false) + { + _logger.LogError( + "Failed to retrieve search requests for page {PageNumber}: {StatusCode} - {Error}", + pageRequest.PageNumber, + res.StatusCode, + res.Message + ); + + return; + } + + res.Value.Items.ForEach(records.Add); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to retrieve search requests for page {PageNumber}", pageRequest.PageNumber); + } + }); + + await Task.WhenAll(remainingRequests); } return records.Select(MapRecordToSearchRequest).ToList(); @@ -50,31 +91,34 @@ class OnspringService( private SearchRequest MapRecordToSearchRequest(ResultRecord record) { - var searchRequest = new SearchRequest(); + var searchRequest = new SearchRequest + { + Id = record.RecordId + }; foreach (var field in record.FieldData) { - if (field.FieldId == options.SearchRequestOptions.NameFieldId) + if (field.FieldId == _options.SearchRequestOptions.NameFieldId) { searchRequest.Name = field.GetStringValue(); } - else if (field.FieldId == options.SearchRequestOptions.AddressFieldId) + else if (field.FieldId == _options.SearchRequestOptions.AddressFieldId) { searchRequest.Address = field.GetStringValue(); } - else if (field.FieldId == options.SearchRequestOptions.CityFieldId) + else if (field.FieldId == _options.SearchRequestOptions.CityFieldId) { searchRequest.City = field.GetStringValue(); } - else if (field.FieldId == options.SearchRequestOptions.StateFieldId) + else if (field.FieldId == _options.SearchRequestOptions.StateFieldId) { searchRequest.State = field.GetStringValue(); } - else if (field.FieldId == options.SearchRequestOptions.ZipFieldId) + else if (field.FieldId == _options.SearchRequestOptions.ZipFieldId) { searchRequest.Zip = field.GetStringValue(); } - else if (field.FieldId == options.SearchRequestOptions.CountryFieldId) + else if (field.FieldId == _options.SearchRequestOptions.CountryFieldId) { searchRequest.Country = field.GetStringValue(); }