using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Responses;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Controllers.V1.Base;
using PARR.DAL.Contracts;
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces;
namespace PARR.API.Controllers.V1
{
public class RobotTaskController : BaseApiController
{
private readonly IMapper mapper;
private readonly SettingsFromDb settingsFromDb;
private readonly IRobotConfigurationService robotConfigurationService;
public RobotTaskController(
IMapper mapper,
SettingsFromDb settingsFromDb,
IRobotConfigurationService robotConfigurationService
)
{
this.mapper = mapper;
this.settingsFromDb = settingsFromDb;
this.robotConfigurationService = robotConfigurationService;
}
///
/// Получить задание для робота по коду робота и по статусу задания
///
///
///
///
[HttpGet(ApiRoutes.RobotTask.GetByRobotAndStatusTask)]
public async Task GetByRobotAndStatusTask([FromRoute] RobotsEnum robotCode, [FromRoute] TaskStatusEnum taskStatusCode)
{
//Ищем все задания с превышенным кол-вом попыток и с просроченным временем и ставим им статус ошибки
await robotConfigurationService.FindUnfulfilledTaskAndSetRobotErrorStatusAsync(settingsFromDb.RobotAttemptsNumber, settingsFromDb.RobotWaitTime);
var query = robotConfigurationService.Get()
.Where(t => t.RobotCode == (int)robotCode && t.TaskStatusCode == (int)taskStatusCode);
//var query = robotConfigurationService.Get();
switch (robotCode)
{
case RobotsEnum.TemplateOrder:
// шаблоны
query = query.Include(t => t.Template)
.ThenInclude(t => t!.Host).ThenInclude(t => t!.ResponseArea)
.Include(t => t.Template)
.ThenInclude(a => a!.ApplicationsInWork)
.ThenInclude(w => w!.Work)
.ThenInclude(t => t!.Tnk)
.ThenInclude(s => s!.Subprocess)
.ThenInclude(p => p!.Process)
.AsSplitQuery();
break;
case RobotsEnum.ScheduleOrder:
//расписание
// тут не делаем AsSplitQuery, не может подтянуть все таблицы
query = query.Include(t => t.Template)
.ThenInclude(t => t!.Host).ThenInclude(t => t!.ResponseArea)
.Include(t => t.Template)
.ThenInclude(t => t!.ApplicationsInWork)
.ThenInclude(t => t!.EsppSchValues)
.ThenInclude(t => t!.EsppSchTypeConfig)
.ThenInclude(t => t!.EsppSchTypeSchedule);
//выбираем только записи с созданными шаблонами (у которых статус 30), а только потом у них ищем расписания
// сначала находим шаблоны со статусом 30
var createdTemplates = robotConfigurationService.Get()
.Where(t => t.RobotCode == (int)RobotsEnum.TemplateOrder && t.TaskStatusCode == (int)TaskStatusEnum.Ok)
.Select(t => t.TemplateId);
//находим задания с расписанием по списку шаблонов createdTemplates
query = query.Where(t => t.RobotCode == (int)RobotsEnum.ScheduleOrder && createdTemplates.Contains(t.TemplateId));
break;
default:
break;
}
RobotConfiguration? task = null;
//ищем задание в ожидании, если нашли, выбираем его
task = await query.FirstOrDefaultAsync(t => t.RobotStatusCode == (int)RobotStatusEnum.Wait);
if (task == null)
{
//ищем задания в работе, которые можно перезапустить
//Поиск по `RobotStatusCode` = 22.
//Далее проверяется `LastStatusUpdated`, что время последнего смены статуса не превышает допустимого(берется из настроек, поле `RobotWaitTime`)
//и что текущая попытка не больше разрешенной(берется из настроек, поле `RobotAttemptsNumber`) - если это так, берется эта запись.
var endDate = DateTimeOffset.UtcNow.Add(-settingsFromDb.RobotWaitTime);
task = await query
.FirstOrDefaultAsync(t =>
t.RobotStatusCode == (int)RobotStatusEnum.InProgress
&& t.AttemptsNumber < settingsFromDb.RobotAttemptsNumber
&& t.LastRobotStatusUpdated < endDate
);
}
if (task == null)
return NotFound();
switch (robotCode)
{
case RobotsEnum.TemplateOrder:
//RobotTaskTemplateResponse
return Ok(new Response(mapper.Map(task), true));
case RobotsEnum.ScheduleOrder:
//RobotTaskScheduleResponse
return Ok(new Response(mapper.Map(task), true));
default:
break;
}
return BadRequest();
}
}
}