Files
2026-03-24 15:26:03 -05:00

173 lines
5.9 KiB
C#

using LCU.Api.Internal.Dispatcher.Configurations;
using LCU.Api.Internal.DispatcherLib.Repositories;
using LCU.Api.Internal.MaidBotLib.Models;
using LCU.Library.Internal.DispatcherModels.Models.Results;
using Newtonsoft.Json;
using System.Threading;
namespace LCU.Api.Internal.Dispatcher.Services.DispatcherOperationServices;
public class CleanUpJobsService : ICleanUpJobsService
{
private readonly IJobService _jobService;
private readonly ICleanUpJobSettingService _cleanUpJobSettingService;
private readonly IUnitOfWork _unitOfWork;
private readonly ApiConfiguration _apiConfiguration;
public CleanUpJobsService(IJobService jobService,
ICleanUpJobSettingService cleanUpJobSettingService,
IUnitOfWork unitOfWork,
ApiConfiguration apiConfiguration)
{
_jobService = jobService;
_cleanUpJobSettingService = cleanUpJobSettingService;
_unitOfWork = unitOfWork;
_apiConfiguration = apiConfiguration;
}
public async Task PerformCleanUpJobs(CancellationToken cancellationToken)
{
try
{
var result = new CleanUpJobBatchResult();
result = await PerformSoftCleanUpJobTask(result);
result = await PerformHardDeleteCleanUpJobTask(result);
await _unitOfWork.CompleteAsync();
if (result.IsFailure)
{
Log.ForContext(nameof(PropertyEnum.Group),
nameof(GroupEnum.ITDevelopment))
.Error("CleanUpJob Batch Result: {@CleanUpJobBatchResult}", result);
}
}
catch (Exception ex)
{
Log.ForContext(nameof(PropertyEnum.Group),
nameof(GroupEnum.ITDevelopment))
.Error(ex, $"Failed to perform Clean Up Jobs.");
}
}
public async Task<CleanUpJobBatchResult> PerformSoftCleanUpJobTask(CleanUpJobBatchResult result)
{
var jobs = await _jobService.GetInactiveExcludeSoftDeletedTrackedAsync();
var cleanUpJobSettings = await _cleanUpJobSettingService.GetAsync();
foreach (var setting in cleanUpJobSettings)
{
if (setting.CleanUpJobTags == null || !setting.CleanUpJobTags.Any())
{
continue;
}
foreach (var job in jobs)
{
result = PerformCleanUpTaskForJob(result, job, setting);
}
}
return result;
}
public bool ValidateShouldSoftDelete(CleanUpJobSetting setting, Job job, CleanUpJobBatchResult result)
{
var shouldSoftDelete = ShouldSoftDeleteByTag(setting, job);
if (!shouldSoftDelete)
{
return false;
}
return ShouldSoftDeleteByDate(setting, job, result);
}
public bool ShouldSoftDeleteByDate(CleanUpJobSetting setting, Job job, CleanUpJobBatchResult result)
{
try
{
if (!job.WorkItems.Any() || !job.WorkItems.FirstOrDefault().WorkItemExecutions.Any())
{
result.AddToFailureCount($"Job would be cleaned but cannot determine if it is old enough to be cleaned due to not having any workItemExecutions. Job: {job.JobId} - {job.Name}");
return false;
}
var currentDate = DateTime.Now;
var cutoffDate = currentDate.AddDays(setting.CompletionDaysPast);
var jobLastCompletedTime = job.WorkItems.FirstOrDefault()
.WorkItemExecutions.OrderByDescending(wie => wie.CompletedTimestamp).FirstOrDefault().CompletedTimestamp.Value;
return DateTime.Compare(cutoffDate, jobLastCompletedTime) > 0;
}
catch (Exception ex)
{
var message = $"Error while attempting to compare CompletedTimestamp for SoftDeletion. Job: {job.JobId} - {job.Name}. ExeptionMessage: {ex.Message}";
Log.Error(message);
throw new Exception(message);
}
}
public bool ShouldSoftDeleteByTag(CleanUpJobSetting setting, Job job)
{
if (job.JobTags.Count != setting.CleanUpJobTags.Count)
{
return false;
}
var orderedJobTagIds = job.JobTags.Select(t => t.TagId).OrderBy(t => t).ToList();
var orderedCleanUpJobTagIds = setting.CleanUpJobTags.Select(t => t.TagId).OrderBy(t => t).ToList();
return orderedJobTagIds.SequenceEqual(orderedCleanUpJobTagIds);
}
public async Task<CleanUpJobBatchResult> PerformHardDeleteCleanUpJobTask(CleanUpJobBatchResult result)
{
var softDeletedJobs = await _jobService.GetSoftDeletedTrackedAsync(DateTime.Now.AddDays(_apiConfiguration.CleanUpJobsDaysToDelete));
foreach (var job in softDeletedJobs)
{
try
{
await _jobService.DeleteFromCleanupAsync(job);
}
catch (Exception ex)
{
Log.Error(ex.Message, "Failure to hard delete dispatcher job through Clean Up Job Task. Job: {@Job}", job);
result.AddToFailureCount(ex.Message);
continue;
}
}
return result;
}
private CleanUpJobBatchResult PerformCleanUpTaskForJob(CleanUpJobBatchResult result, Job job, CleanUpJobSetting setting)
{
try
{
var shouldSoftDelete = ValidateShouldSoftDelete(setting, job, result);
if (!shouldSoftDelete)
{
return result;
}
job.SoftDeleteDate = DateTime.Now;
var updatedJob = _jobService.UpdateExcludingWorkItemsAsyncWithoutSave(job);
if (updatedJob == null || updatedJob.Result.JobId != job.JobId)
{
throw new Exception($"Failure to setup soft delete update for job. Job:{JsonConvert.SerializeObject(job)}");
}
}
catch (Exception ex)
{
result.AddToFailureCount(ex.Message);
}
return result;
}
}