Files
parr_api/PARR.DAL/Repositories/RobotConfigurationRepository.cs

168 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces;
using PARR.DAL.Context;
using PARR.DAL.Repositories.Base;
using PARR.Domain.Entities;
using PARR.Domain.Enums;
namespace PARR.DAL.Repositories
{
internal class RobotConfigurationRepository : BaseRepository<RobotConfiguration>, IRobotConfigurationRepository
{
public RobotConfigurationRepository(DataContext dataContext, ILogger<RobotConfigurationRepository> logger) : base(logger, dataContext) { }
public void ChangeTaskStatus(TaskStatusEnum taskStatus, RobotConfiguration configuration)
{
configuration.TaskStatusCode = (int)taskStatus;
switch (taskStatus)
{
case TaskStatusEnum.Creating:
ChangeRobotStatus(RobotStatusEnum.Wait, configuration);
break;
case TaskStatusEnum.Updating:
ChangeRobotStatus(RobotStatusEnum.Wait, configuration);
break;
case TaskStatusEnum.Ok:
ChangeRobotStatus(RobotStatusEnum.Complete, configuration);
break;
default:
break;
}
}
public bool SetUpdateTaskStatusIfAllow(RobotConfiguration configuration)
{
var updatingStatus = TaskStatusEnum.Updating;
// ставить статус Updating можно только если текущий статус == Ok
if (configuration.TaskStatusCode != (int)TaskStatusEnum.Ok)
{
int taskStatusValue = configuration.TaskStatusCode;
string taskStatusName = Enum.IsDefined(typeof(TaskStatusEnum), taskStatusValue)
? ((TaskStatusEnum)taskStatusValue).ToString()
: $"Unknown ({taskStatusValue})";
logger.LogInformation("Нельзя установить статус {newStatus} для конфигурации {configurationId}, templateId: {templateId}, так как текущий статус {currentStatus}",
updatingStatus, configuration.Id, configuration.TemplateId, taskStatusName);
return false;
}
// Если хотим поставить Updating у шаблона, можно ставить только в том случае, если у шаблона уже есть ScheduleEsppId
if (configuration.RobotCode == (int)RobotsEnum.TemplateOrder)
{
// есть ли связь у config с templetes, может инклуда нет, мало ли
if (configuration.Template == null)
{
logger.LogWarning("При изменении статуса задания на обновление шаблона, не смог проверить наличае ScheduleEsppId, так как нет Include с Templates. Пропустил эту проверку. configurationId: {configurationId}", configuration.Id);
}
else
{
if (configuration.Template.ScheduleEsppId == null)
{
logger.LogInformation("Нельзя установить статус {newStatus} для конфигурации {configurationId}, templateId: {templateId}, так как у шаблона отсутсвтует ScheduleEsppId=null",
updatingStatus, configuration.Id, configuration.TemplateId);
return false;
}
}
}
// Статус ОК, можно ставить Updating
ChangeTaskStatus(updatingStatus, configuration);
logger.LogInformation("Установлен статус {newStatus} для конфигурации {configurationId}, templateId: {templateId}", updatingStatus, configuration.Id, configuration.TemplateId);
return true;
}
public void ChangeRobotStatus(RobotStatusEnum robotStatus, RobotConfiguration configuration)
{
configuration.RobotStatusCode = (int)robotStatus;
switch (robotStatus)
{
case RobotStatusEnum.InProgress:
configuration.AttemptsNumber++;
configuration.LastRobotStatusUpdated = DateTimeOffset.UtcNow;
break;
//case RobotStatusEnum.Error:
// break;
case RobotStatusEnum.Complete:
configuration.LastRobotStatusUpdated = DateTimeOffset.UtcNow;
break;
case RobotStatusEnum.Wait:
configuration.LastRobotStatusUpdated = null;
configuration.AttemptsNumber = 0;
break;
default:
break;
}
}
public async Task<bool> SetInProgressStatusAsync(Guid id)
{
// Если задание все еще в статусе Wait (RobotStatusEnum.Wait), установить ему статус "InProgress"
// Выполняем атомарный UPDATE напрямую в базе данных
var affectedRows = await EntitySet.Where(t => t.Id == id && t.RobotStatusCode == (int)RobotStatusEnum.Wait)
.ExecuteUpdateAsync(s => s
.SetProperty(t => t.RobotStatusCode, (int)RobotStatusEnum.InProgress)
.SetProperty(t => t.LastRobotStatusUpdated, DateTimeOffset.UtcNow)
);
return affectedRows > 0;
}
public RobotConfiguration GetFromTemplateByRobotCode(RobotsEnum robotsEnum, Template template)
{
var config = template.RobotConfigurations.FirstOrDefault(t => t.RobotCode == (int)robotsEnum);
if (config == null)
{
logger.LogError($"У шаблона нет конфигурации роботов. TemplateId: {template.Id}");
throw new Exception($"У шаблона нет конфигурации роботов. TemplateId: {template.Id}");
}
return config;
}
// Поиск невыполненных заданий и установка им статуса ошибки робота
public async Task MarkExpiredTasksAsFailedAsync(int robotAttemptsNumber, TimeSpan robotWaitTime)
{
//Ищем `RobotStatusCode` = 22 и `LastStatusUpdated` истекло и `AttemptsNumber` >= допустимого значения из настроек,
//ставим всем этим записям `RobotStatusCode`= 33
var endDate = DateTimeOffset.UtcNow.Add(-robotWaitTime);
var configObjs = await EntitySet.Where(t =>
t.RobotStatusCode == (int)RobotStatusEnum.InProgress
&& t.AttemptsNumber >= robotAttemptsNumber
&& t.LastRobotStatusUpdated <= endDate
).ToListAsync();
if (!configObjs.Any())
return;
configObjs.ForEach(item =>
{
ChangeRobotStatus(RobotStatusEnum.Error, item);
logger.LogInformation($"Устанавливаю RobotStatus: {RobotStatusEnum.Error} для RobotConfigurationId {item.Id}");
});
var result = await CommitAsync();
if (!result)
logger.LogError($"Ошибка при сохранении изменений RobotStatus для RobotConfigurationId: item.Id, RobotStatus: {RobotStatusEnum.Error}");
}
}
}