173 lines
5.9 KiB
C#
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;
|
|
}
|
|
}
|