using Newtonsoft.Json; using LCU.Library.Internal.ApiResponse.Models; using LCU.Api.Internal.Dispatcher.Services.QueueServices; using LCU.Library.Internal.DispatcherModels.Models.Requests; using LCU.Library.Internal.DispatcherModels.Enums; using System.Collections.Generic; using RabbitMQ.Client; using LCU.Api.Internal.MaidBotLib.Models; namespace LCU.Api.Internal.Dispatcher.Services.DispatcherOperationServices; public class CompletionService : ICompletionService { private readonly IJobService _jobService; private readonly IWorkItemService _workItemService; private readonly IExecutionMessageService _executionMessageService; private readonly IQueueJobFailureService _queueJobFailureService; private readonly IQueueDetermineOperationService _queueDetermineOperationService; public CompletionService(IJobService jobService, IWorkItemService workItemService, IExecutionMessageService executionMessageService, IQueueJobFailureService queueJobFailureService, IQueueDetermineOperationService queueDetermineOperationService) { _jobService = jobService; _workItemService = workItemService; _executionMessageService = executionMessageService; _queueJobFailureService = queueJobFailureService; _queueDetermineOperationService = queueDetermineOperationService; } public async Task HandleCompletionRequest(Response response) { var dispatcherReturnResponse = JsonConvert.DeserializeObject(response.ResponsePayload); try { ArgumentNullException.ThrowIfNull(dispatcherReturnResponse); var job = await _jobService.GetByWorkItemIdExcludingWorkItemsAsync(dispatcherReturnResponse.WorkItemId); if (!response.Successful) { await _queueJobFailureService.QueueJobFailure(job.JobId, dispatcherReturnResponse.WorkItemId, response.ResponseStack == null || response.ResponseStack.Any() ? response.ResponseStack : new List()); return; } var workItem = await _workItemService.GetByIdAsync(dispatcherReturnResponse.WorkItemId); if (workItem.CurrentWorkItemExecution == null) { Log.Warning($"CurrentWorkitemExecution was null for WorkItemId:{dispatcherReturnResponse.WorkItemId}"); return; } await _executionMessageService.SaveExecutionMessages(workItem.CurrentWorkItemExecution.WorkItemExecutionId, response.ResponseStack); if (workItem.CanceledJobCounter > 0) { workItem = await _workItemService.ResetCanceledJobCounter(workItem); } job.JobStatus = JobStatus.DeterminingOperation; var updatedJob = await _jobService.UpdateAsync(job); await _queueDetermineOperationService.QueueDetermineOperation(updatedJob, workItem, SetDetermineOperationType(dispatcherReturnResponse.Skipped)); } catch (Exception exception) { var exceptionMessage = $"Failed to perform completion. Job may be stuck in an inoperable status. WorkItemId: {dispatcherReturnResponse.WorkItemId}"; Log.Error(exception, exceptionMessage); throw new ServiceException(exceptionMessage); } } public DetermineOperationType SetDetermineOperationType(bool isSkipped) { if(isSkipped) { return DetermineOperationType.Skipped; } return DetermineOperationType.Completed; } }