using LCU.Api.Internal.Dispatcher.Configurations; using LCU.Api.Internal.DispatcherLib.Repositories; using LCU.Api.Internal.DispatcherSharedLib.BuilderServices; using LCU.Library.Internal.ApiResponse.Models; using LCU.Library.Internal.LcuMassTransitModels; using Microsoft.Data.SqlClient; using Newtonsoft.Json; using System.Collections.Generic; namespace LCU.Api.Internal.Dispatcher.Services; public class WorkItemService : IWorkItemService { private readonly IUnitOfWork _unitOfWork; private readonly IWorkItemRepository _workItemRepository; private readonly IWorkItemExecutionService _workItemExecutionService; private readonly IActionBuilderService _actionBuilderService; private readonly ConnectionConfiguration _connectionConfiguration; private readonly ReceiveEndpointConfiguration _completionReceiveEndpoint; private readonly ApiConfiguration _apiConfiguration; public WorkItemService(IUnitOfWork unitOfWork, IWorkItemRepository workItemRepository, IWorkItemExecutionService workItemExecutionService, IActionBuilderService actionBuilderService, ConnectionConfiguration connectionConfiguration, ReceiveEndpointConfigurations queueReceiveEndpointsConfigurations, ApiConfiguration apiConfiguration) { _unitOfWork = unitOfWork; _workItemRepository = workItemRepository; _workItemExecutionService = workItemExecutionService; _actionBuilderService = actionBuilderService; _connectionConfiguration = connectionConfiguration; _completionReceiveEndpoint = queueReceiveEndpointsConfigurations.CompletionReceiveEndpoint; _apiConfiguration = apiConfiguration; } public async Task GetByIdAsync(int id) { WorkItem workItem = null; try { workItem = await _workItemRepository.FindByIdAsync(id); ArgumentNullException.ThrowIfNull(workItem); } catch (Exception exception) { Log.Error(exception, $"Failure retrieving dispatcher workitem with id {id}."); throw new ServiceException($"Failure retrieving dispatcher workitem with id {id}."); } return workItem; } public async Task> GetByJobIdAsync(int jobId) { IEnumerable workItems = null; try { workItems = await _workItemRepository.FindByJobIdAsync(jobId); ArgumentNullException.ThrowIfNull(workItems); } catch (Exception exception) { Log.Error(exception, $"Failure retrieving dispatcher workitems with JobId {jobId}."); throw new ServiceException($"Failure retrieving dispatcher workitems with JobId {jobId}."); } return workItems; } public async Task> GetByJobIdWithExecutionsAsync(int jobId) { IEnumerable workItems = null; try { workItems = await _workItemRepository.FindByJobIdWithExecutionsAsync(jobId, _apiConfiguration.NumberOfWorkItemExecutions, _apiConfiguration.NumberOfExecutionMessages); ArgumentNullException.ThrowIfNull(workItems); } catch (Exception exception) { Log.Error(exception, $"Failure retrieving dispatcher workitems and executions with JobId {jobId}."); throw new ServiceException($"Failure retrieving dispatcher workitems and executions with JobId {jobId}."); } return workItems; } public async Task GetFirstOrDefaultWorkItemByJobId(int jobId) { WorkItem workItem = null; try { workItem = await _workItemRepository.GetFirstOrDefaultWorkItemByJobId(jobId); } catch (Exception exception) { Log.Error(exception, $"Failure retrieving first or default workItem with JobId: {jobId}."); throw new ServiceException($"Failure retrieving first or default workItem with JobId: {jobId}."); } return workItem; } public async Task GetNextWorkItemByJobId(int jobId, int currentWorkItemOrder) { WorkItem workItem = null; try { workItem = await _workItemRepository.GetNextWorkItemByJobId(jobId, currentWorkItemOrder); } catch (Exception exception) { Log.Error(exception, $"Failure retrieving next workItem with JobId: {jobId}."); throw new ServiceException($"Failure retrieving next workItem with JobId: {jobId}."); } return workItem; } public async Task> PopulateActionFieldsAndUpdateList(ICollection workItems) { try { var updatedWorkItems = new List(); foreach (var workItem in workItems) { var newWorkItem = workItem; newWorkItem = PopulateActionFields(newWorkItem); newWorkItem = await UpdateAsync(newWorkItem); updatedWorkItems.Add(newWorkItem); } return updatedWorkItems; } catch (Exception exception) { Log.Error(exception, $"Failure populating action fields and updating dispatcher workitems."); } return null; } public async Task ResetCanceledJobCounter(WorkItem workItem) { var trackedWorkItem = await _workItemRepository.GetTrackedWorkItem(workItem.WorkItemId); trackedWorkItem.CanceledJobCounter = 0; await _unitOfWork.CompleteAsync(); return await _workItemRepository.FindByIdAsync(trackedWorkItem.WorkItemId); } public async Task IncreaseCanceledJobCounter(WorkItem workItem) { var trackedWorkItem = await _workItemRepository.GetTrackedWorkItem(workItem.WorkItemId); trackedWorkItem.CanceledJobCounter++; await _unitOfWork.CompleteAsync(); return await _workItemRepository.FindByIdAsync(trackedWorkItem.WorkItemId); } public async Task UpdateAsync(WorkItem workItem) { try { _workItemRepository.Update(workItem); await _unitOfWork.CompleteAsync(); return workItem; } catch (SqlException sqlException) { Log.Error(sqlException, $"SQL Failure updating dispatcher workitem with id {workItem.WorkItemId}"); throw new ServiceException($"SQL Failure updating dispatcher workitem with id {workItem.WorkItemId}"); } catch (Exception exception) { Log.Error(exception, $"Failure updating dispatcher workitem with id {workItem.WorkItemId}"); throw new ServiceException($"Failure updating dispatcher workitem with id {workItem.WorkItemId}"); } } public void SaveList(ICollection workItems) { try { _workItemRepository.AddList(workItems); _unitOfWork.Complete(); } catch (Exception exception) { Log.Error(exception, $"Failure saving list of workitems."); throw new ServiceException($"Failure saving list of workitems."); } } public async Task DeleteList(ICollection workItems) { try { foreach (var workItem in workItems) { var workItemExecutions = await _workItemExecutionService.GetAllByWorkItemId(workItem.WorkItemId); workItem.WorkItemExecutions = workItemExecutions.ToList(); } _workItemRepository.RemoveList(workItems); await _unitOfWork.CompleteAsync(); } catch (SqlException sqlException) { Log.Error(sqlException, $"SQL Failure removing dispatcher workitems"); throw new ServiceException($"SQL Failure removing dispatcher workitems"); } catch (Exception exception) { Log.Error(exception, $"Failure removing dispatcher workitems"); throw new ServiceException($"Failure removing dispatcher workitems"); } } public WorkItem PopulateActionFields(WorkItem workItem) { var actionBuilder = _actionBuilderService.BuildAction(workItem.ActionType); var responseItem = CreateResponseItem(workItem.WorkItemId); workItem = actionBuilder.AddUrlAndHttpMethod(workItem); workItem = actionBuilder.AddWorkItemReturnResponse(workItem, responseItem); return workItem; } private ResponseItem CreateResponseItem(int workItemId) { var dispatcherReturnResponse = new DispatcherReturnResponse { WorkItemId = workItemId }; var serializeDispatcherReturnResponse = JsonConvert.SerializeObject(dispatcherReturnResponse); var newReturnItem = new ResponseItem { ResponsePayload = serializeDispatcherReturnResponse, ReturnQueueConnectionConfig = new QueueConnectionConfig() { Url = _connectionConfiguration.HostUrl, Username = _connectionConfiguration.UserName, Password = _connectionConfiguration.Password }, ReturnQueueConsumerConfig = new QueueConsumerConfig() { ExchangeName = _completionReceiveEndpoint.ReceiveEndpoint } }; return newReturnItem; } }