Adding
This commit is contained in:
+47
@@ -0,0 +1,47 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LCU.API.Collections.RepoApi.Configuration;
|
||||
using LCU.API.Collections.RepoApi.Services;
|
||||
using LCU.Shared.Realtime.QueueLib.Models;
|
||||
using LCU.Shared.Realtime.QueueLib.Queue;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Serilog;
|
||||
|
||||
namespace LCU.API.Collections.RepoApi.HostedServices
|
||||
{
|
||||
public class HostedAutoImsTaskConsumer : BackgroundService, IQueueItemProcessor
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IQueueConnectionConfig _configuration;
|
||||
private readonly IQueueConsumerConfig _consumerConfig;
|
||||
|
||||
public HostedAutoImsTaskConsumer(IQueueConnectionConfig configuration, RepoApiConfiguration repoApiConfiguration, IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_scopeFactory = scopeFactory;
|
||||
_consumerConfig = repoApiConfiguration.QueueConsumerConfigs["AutoImsTask"];
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Log.Information("[QueueLib] Hosted Queue Producer is starting.");
|
||||
|
||||
var proxyQueue = new QueueItemConsumer(_configuration, _consumerConfig, this);
|
||||
|
||||
await proxyQueue.ProcessItems(cancellationToken, true, 0);
|
||||
|
||||
Log.Information("[QueueLib] Hosted Queue Producer is stopping.");
|
||||
}
|
||||
|
||||
public void HandleItem(QueueItem item)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var processor = scope.ServiceProvider.GetService<AutoImsService>();
|
||||
var files = processor.Download();
|
||||
processor.ProcessDownloadedFiles(files);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LCU.API.Collections.RepoApi.Configuration;
|
||||
using LCU.Shared.Collections.RepoApiLib.Hosted;
|
||||
using LCU.Shared.Realtime.QueueLib.Models;
|
||||
using LCU.Shared.Realtime.QueueLib.Queue;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Serilog;
|
||||
|
||||
namespace LCU.API.Collections.RepoApi.HostedServices
|
||||
{
|
||||
public class HostedRepoTaskConsumer : BackgroundService, IQueueItemProcessor
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IQueueConnectionConfig _configuration;
|
||||
private readonly IQueueConsumerConfig _consumerConfig;
|
||||
|
||||
public HostedRepoTaskConsumer(IQueueConnectionConfig configuration, RepoApiConfiguration repoApiConfiguration, IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_scopeFactory = scopeFactory;
|
||||
_consumerConfig = repoApiConfiguration.QueueConsumerConfigs["RepoProcessorTask"];
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Log.Information("Hosted Queue Producer is starting.");
|
||||
|
||||
try
|
||||
{
|
||||
var proxyQueue = new QueueItemConsumer(_configuration, _consumerConfig, this);
|
||||
|
||||
await proxyQueue.ProcessItems(cancellationToken, true, 0);
|
||||
}
|
||||
catch (TaskCanceledException ex) when (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Log.Information(ex, "Repo Producer was shut down normally.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error in main thread for HostedRepoTaskConsumer");
|
||||
}
|
||||
|
||||
Log.Information("Hosted Repo Producer is stopping.");
|
||||
}
|
||||
|
||||
public void HandleItem(QueueItem item)
|
||||
{
|
||||
var settings = new TaskSettings();
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var queueProducerService = scope.ServiceProvider.GetRequiredService<IRepoQueueProducerService>();
|
||||
queueProducerService.ImportData(settings).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using System.Threading.Tasks;
|
||||
using LCU.Shared.Collections.RepoApiLib.Hosted;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models.Producer;
|
||||
|
||||
namespace LCU.API.Collections.RepoApi.HostedServices
|
||||
{
|
||||
public interface IRepoQueueProducerService
|
||||
{
|
||||
Task ImportData(TaskSettings settings);
|
||||
void SendRequestToQueue(ProcessingItem queueRequest);
|
||||
}
|
||||
}
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LCU.API.Collections.RepoApi.Configuration;
|
||||
using LCU.API.Collections.RepoApi.Exceptions;
|
||||
using LCU.API.Collections.RepoApi.Services;
|
||||
using LCU.API.Collections.RepoApi.Services.Producer;
|
||||
using LCU.Api.Internal.MaidBotLib.Models;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models.Consumer;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models.Producer;
|
||||
using LCU.Shared.Collections.RepoApiLib.Repositories;
|
||||
using LCU.Shared.Realtime.QueueLib.Models;
|
||||
using LCU.Shared.Realtime.QueueLib.Queue;
|
||||
using Microsoft.CodeAnalysis.Operations;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
namespace LCU.API.Collections.RepoApi.HostedServices
|
||||
{
|
||||
/**
|
||||
* Special Notes.
|
||||
* 1. Direct injection of services cannot be done, the main API context is on it's own
|
||||
* scope/thread. So instead, the scope factory is passed, so that this can create scopes.
|
||||
* 2. This is designed to use 5 threads, from within an IHostedService thread context, to
|
||||
* process queues. It's designed to do this in 'batches' to simulate a batch job, which
|
||||
* is where the creation of the RunInfo comes into scope.
|
||||
* 3. There is a main 'thread' here, which waits for a 'batch' of work to be complete.
|
||||
* 4. Under the main thread, there are 5 worker threads, communicating using two queues besides
|
||||
* the main Rabbit queue. The queues are used to set something up for processing (_inputQueue)
|
||||
* and to mark something as done processing (_outputQueue).
|
||||
*/
|
||||
public class RepoQueueConsumerService : BackgroundService, IQueueItemProcessor
|
||||
{
|
||||
private readonly IQueueConnectionConfig _connectionConfig;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private RepoRunInfo _runInfo;
|
||||
|
||||
private const int ThreadCount = 5;
|
||||
private BlockingCollection<QueueItem> _inputQueue;
|
||||
private BlockingCollection<QueueResult> _outputQueue;
|
||||
private readonly ConcurrentDictionary<string, ProcessingItem> _inProgress;
|
||||
private readonly Task[] _workers;
|
||||
private Task _consumer;
|
||||
private QueueItemConsumer _queue;
|
||||
private readonly IQueueConsumerConfig _consumerConfig;
|
||||
private CancellationTokenSource _individualRunToken;
|
||||
|
||||
public RepoQueueConsumerService(IQueueConnectionConfig connectionConfig, RepoApiConfiguration repoApiConfiguration, IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_connectionConfig = connectionConfig;
|
||||
_scopeFactory = scopeFactory;
|
||||
_inProgress = new ConcurrentDictionary<string, ProcessingItem>();
|
||||
_workers = new Task[ThreadCount];
|
||||
_consumerConfig = repoApiConfiguration.QueueConsumerConfigs["RepoAccountQueue"];
|
||||
}
|
||||
|
||||
bool TopLevelThreadController()
|
||||
{
|
||||
Log.Information($"[Startup] {_consumerConfig.GetQueueName()} Consumer is starting a run.");
|
||||
_runInfo = new RepoRunInfo();
|
||||
|
||||
foreach (var workItem in _outputQueue.GetConsumingEnumerable())
|
||||
{
|
||||
_queue.AckItem(workItem.DeliveryTag);
|
||||
if (workItem.Receipt != null)
|
||||
{
|
||||
_runInfo.Receipts.Add(workItem.Receipt);
|
||||
}
|
||||
|
||||
var remainingCount = _queue.CheckQueueCount();
|
||||
// First the input queue will finish, and we have to let running tasks finish.
|
||||
if (remainingCount == 0 && EnumerableExtensions.Any(_inputQueue) == false && !_inputQueue.IsCompleted)
|
||||
{
|
||||
_inputQueue.CompleteAdding();
|
||||
Task.WaitAll(_workers);
|
||||
}
|
||||
|
||||
// That will cause the output queue to have the last THREADCOUNT items added, but
|
||||
// we are IN the loop that processes them, so wen can't wait, just continue...
|
||||
if (remainingCount == 0 && _inputQueue.IsCompleted && !_outputQueue.IsAddingCompleted)
|
||||
{
|
||||
_outputQueue.CompleteAdding();
|
||||
}
|
||||
|
||||
// Ok, both queues are complete, which means all done.
|
||||
if (_inputQueue.IsCompleted && _outputQueue.IsCompleted)
|
||||
{
|
||||
_individualRunToken.Cancel();
|
||||
_inputQueue.Dispose();
|
||||
_outputQueue.Dispose();
|
||||
Log.Information($"{_consumerConfig.GetQueueName()} run completed... recording RunInfo: {@_runInfo}", _runInfo);
|
||||
_runInfo.CompleteDateTime = DateTime.Now;
|
||||
SaveRunInfo(_runInfo);
|
||||
SendErrorNotification(_runInfo);
|
||||
SendAlertNotification(_runInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Error($"[Startup] {_consumerConfig.GetQueueName()} Consumer is finished in an unexpected way. {@_runInfo}", _runInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SaveRunInfo(RepoRunInfo runInfo)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
try
|
||||
{
|
||||
var receiptService = scope.ServiceProvider.GetRequiredService<IProcessingReceiptService>();
|
||||
receiptService.SaveAllAsync(runInfo.Receipts).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Could not save repo processor results.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendErrorNotification(RepoRunInfo runInfo)
|
||||
{
|
||||
if (runInfo.Receipts.Count > 0)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var resp = scope.ServiceProvider.GetService<IEmailer>().SendProccessSummary(_runInfo);
|
||||
if (!resp.Result.IsSuccessStatusCode)
|
||||
{
|
||||
Log.Error(
|
||||
$"RepoQueueConsumerService failed to send error email. Emailer Response: {resp.Result.StatusCode} - {resp.Result.ReasonPhrase}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendAlertNotification(RepoRunInfo runInfo)
|
||||
{
|
||||
if (runInfo.Receipts.Count > 0)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var resp = scope.ServiceProvider.GetService<IEmailer>().SendAlertSummaryEmailWithEndTime(runInfo.CompleteDateTime?? DateTime.Now);
|
||||
if (!resp.Result.IsSuccessStatusCode)
|
||||
{
|
||||
Log.Error(
|
||||
$"RepoQueueConsumerService failed to send alerts email. Emailer Response: {resp.Result.StatusCode} - {resp.Result.ReasonPhrase}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SingleThreadMessageWorker(int workerId)
|
||||
{
|
||||
Log.Debug("[Startup] Worker {0} is starting.", workerId);
|
||||
foreach (var workItem in _inputQueue.GetConsumingEnumerable())
|
||||
{
|
||||
var message = Encoding.UTF8.GetString(workItem.Body.ToArray());
|
||||
Log.Information("Worker {0} Processing {1}", workerId, message);
|
||||
var result = HandleSingleItem(message).GetAwaiter().GetResult();
|
||||
result.DeliveryTag = workItem.DeliveryTag;
|
||||
_outputQueue.Add(result);
|
||||
}
|
||||
|
||||
Log.Debug("[Shutdown] Worker {0} is complete.", workerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is the main function run by the IHostedService interface, so
|
||||
* should be considered the 'main' here.
|
||||
*/
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (_queue == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_queue = new QueueItemConsumer(_connectionConfig, _consumerConfig, this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to create RepoQueueConsumerService, Will try again in 1 minute.");
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
Log.Debug($"{_consumerConfig.GetQueueName()} Processor started a run.");
|
||||
_inputQueue = new BlockingCollection<QueueItem>();
|
||||
_outputQueue = new BlockingCollection<QueueResult>();
|
||||
_consumer = Task<bool>.Factory.StartNew(TopLevelThreadController, stoppingToken);
|
||||
for (var threadIndex = 0; threadIndex < ThreadCount; ++threadIndex)
|
||||
{
|
||||
var workerId = threadIndex;
|
||||
var task = new Task(() => SingleThreadMessageWorker(workerId));
|
||||
_workers[threadIndex] = task;
|
||||
task.Start();
|
||||
}
|
||||
|
||||
_individualRunToken = new CancellationTokenSource();
|
||||
await _queue.ProcessItems(_individualRunToken.Token, false, ThreadCount);
|
||||
|
||||
while (!_consumer.IsCompleted)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||
Log.Debug($"{_consumerConfig.GetQueueName()} Finishing Heartbeat.");
|
||||
}
|
||||
|
||||
_consumer?.Dispose();
|
||||
_individualRunToken.Dispose();
|
||||
Log.Debug($"{_consumerConfig.GetQueueName()} Processor Completed a run.");
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||
}
|
||||
|
||||
// the thread is cancelled, so the loop will exit, be sure to propagate the cancellation to our token
|
||||
if (_individualRunToken != null && _individualRunToken.IsCancellationRequested == false)
|
||||
{
|
||||
_individualRunToken.Cancel();
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException ex) when (stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
Log.Information(ex, "Repo Processor was shut down normally.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
|
||||
.Fatal(ex,$"There is an unhandled exception when processing repos; The IIS App Pool may need to be restarted.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<QueueResult> HandleSingleItem(string itemAsString)
|
||||
{
|
||||
var result = new QueueResult();
|
||||
ProcessingItem item = null;
|
||||
try
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var repoAccountProcessor = scope.ServiceProvider.GetRequiredService<IRepoAccountProcessor>();
|
||||
|
||||
item = JsonConvert.DeserializeObject<ProcessingItem>(itemAsString);
|
||||
Log.Debug($"{_consumerConfig.GetQueueName()} Consumer received: {@item}", item);
|
||||
|
||||
var newKey = item.DetermineAuditItemKey();
|
||||
if (_inProgress.TryAdd(newKey, item) == false)
|
||||
{
|
||||
Log.Information("Conflicting item found for {0}, skipping.",
|
||||
item.DetermineAuditItemKey(),
|
||||
_inProgress[newKey].DetermineAuditItemKey());
|
||||
return result;
|
||||
}
|
||||
|
||||
var receipt = new ProcessingReceipt(item.AccountNo)
|
||||
{
|
||||
AccountId = item.AccountId ?? "",
|
||||
CaseId = item.CaseId ?? "",
|
||||
QueuedBy = item.QueuedBy
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information($"Processing {item.AccountNo}");
|
||||
receipt.Outcome = await repoAccountProcessor.HandleAccount(item);
|
||||
receipt.Message = "Success";
|
||||
}
|
||||
catch (IneligibleAccountException iaEx)
|
||||
{
|
||||
receipt.Message = $"The item {item.AccountNo} is ineligible {iaEx.Field} : {iaEx.Reason}";
|
||||
receipt.Outcome = RepoProcessingResult.Ineligible;
|
||||
}
|
||||
catch (MissingRequirementException mrEx)
|
||||
{
|
||||
receipt.Message = $"The item {item.AccountNo} is missing {mrEx.Field} : {mrEx.Advice}.";
|
||||
receipt.Outcome = RepoProcessingResult.MissingRequirement;
|
||||
}
|
||||
catch (Exception ex) /* Mostly ServerErrorException */
|
||||
{
|
||||
receipt.Message = $"The item {item.AccountNo} produced an error. Please investigate.";
|
||||
Log.Error(ex, receipt.Message);
|
||||
}
|
||||
|
||||
if (!_inProgress.TryRemove(newKey, out item))
|
||||
{
|
||||
Log.Error("Couldn't remove item from concurrent dictionary. (Success branch) {@item}", item);
|
||||
}
|
||||
|
||||
result.Receipt = receipt;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, $"[INVESTIGATE] Failed processing {itemAsString}.");
|
||||
if (item == null) return result;
|
||||
var newKey = item.DetermineAuditItemKey();
|
||||
if (!_inProgress.TryRemove(newKey, out item))
|
||||
{
|
||||
Log.Error("Couldn't remove item from concurrent dictionary. (Exception branch) {@item}", item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleItem(QueueItem item)
|
||||
{
|
||||
_inputQueue.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LCU.API.Collections.RepoApi.Configuration;
|
||||
using LCU.API.Collections.RepoApi.DataAccess;
|
||||
using LCU.API.Collections.RepoApi.Services;
|
||||
using LCU.Shared.Collections.RepoApiLib.Hosted;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models;
|
||||
using LCU.Shared.Collections.RepoApiLib.Models.Producer;
|
||||
using LCU.Shared.Collections.RepoApiLib.Repositories;
|
||||
using LCU.Shared.Realtime.QueueLib.Models;
|
||||
using LCU.Shared.Realtime.QueueLib.Queue;
|
||||
using Serilog;
|
||||
|
||||
namespace LCU.API.Collections.RepoApi.HostedServices
|
||||
{
|
||||
public class RepoQueueProducerService : IRepoQueueProducerService
|
||||
{
|
||||
private readonly RepoApiConfiguration _configuration;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ICollectionsDao _collectionsDao;
|
||||
private readonly QueueItemProducer<ProcessingItem> _queueService;
|
||||
private readonly IQueueConsumerConfig _consumerConfig;
|
||||
private readonly IRepoAccountService _repoAccountService;
|
||||
private readonly IProcessingReceiptService _processingReceiptService;
|
||||
|
||||
public RepoQueueProducerService(IQueueConnectionConfig connectionConfig,
|
||||
IRepoAccountService repoAcountService,
|
||||
RepoApiConfiguration configuration,
|
||||
ISettingsService settingsService,
|
||||
ICollectionsDao collectionsDao,
|
||||
IProcessingReceiptService processingReceiptService)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_settingsService = settingsService;
|
||||
_collectionsDao = collectionsDao;
|
||||
_processingReceiptService = processingReceiptService;
|
||||
_consumerConfig = configuration.QueueConsumerConfigs["RepoAccountQueue"];
|
||||
_queueService = new QueueItemProducer<ProcessingItem>(connectionConfig);
|
||||
_repoAccountService = repoAcountService;
|
||||
}
|
||||
|
||||
public async Task ImportData(TaskSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
var reprocessItems = await _processingReceiptService.GetRetryListAsync();
|
||||
var watchStatusItems = await RetrieveRepoAccountsOfInterest();
|
||||
var combinedList = CreateCombinedList(reprocessItems, watchStatusItems);
|
||||
|
||||
Log.Information($"Repo Producer Queueing {combinedList.Count} results.");
|
||||
if (combinedList.Any())
|
||||
{
|
||||
_queueService.EnqueueList(combinedList, _consumerConfig);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Error Deserializing. Repo Producer Failed to queue accounts.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fullConfig = await _collectionsDao.RetrieveTemenosConfigurationAsync();
|
||||
var users = fullConfig.Users.Select(x => new ExternalUser()
|
||||
{
|
||||
Code = x.Code,
|
||||
ReferenceId = x.Id,
|
||||
Name = x.Description
|
||||
}).ToList();
|
||||
await _settingsService.SyncExternalUsersAsync(users);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Error Updating external user list from Temenos.");
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<ProcessingItem> CreateCombinedList(IReadOnlyCollection<ProcessingReceipt> listPriority,
|
||||
IReadOnlyCollection<ProcessingItem> listSecondary)
|
||||
{
|
||||
var combinedList = new List<ProcessingItem>();
|
||||
|
||||
if (listPriority != null && listPriority.Any())
|
||||
{
|
||||
foreach (var processingItem in listPriority)
|
||||
{
|
||||
combinedList.Add(new ProcessingItem()
|
||||
{
|
||||
AccountNo = processingItem.AccountNo,
|
||||
AccountId = processingItem.AccountId,
|
||||
CaseId = processingItem.CaseId,
|
||||
QueuedBy = "RepoManager-Retry"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (listSecondary == null || !listSecondary.Any()) return combinedList;
|
||||
|
||||
foreach (var processingItem in listSecondary)
|
||||
{
|
||||
if (combinedList.Any(x => x.AccountNo == processingItem.AccountNo)) continue;
|
||||
|
||||
processingItem.QueuedBy = "RepoManager";
|
||||
combinedList.Add(processingItem);
|
||||
}
|
||||
|
||||
return combinedList;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<ProcessingItem>> RetrieveRepoAccountsOfInterest()
|
||||
{
|
||||
var repoAccountNos = new List<ProcessingItem>();
|
||||
try
|
||||
{
|
||||
repoAccountNos.AddRange(await _repoAccountService.GetItemsForProcessing());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to Retrieve Repo Accounts For Polling in RepoQueueProducerService");
|
||||
}
|
||||
|
||||
return repoAccountNos;
|
||||
}
|
||||
|
||||
public void SendRequestToQueue(ProcessingItem queueRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
_queueService.Enqueue(queueRequest, _consumerConfig);
|
||||
Log.Debug($"Queued The Following Account {queueRequest.AccountNo}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Failed to Add AccountNo To Queue {queueRequest.AccountNo}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user