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); 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) ; //todo: include 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 //TODO: сделать маппинг!!! return Ok(new Response(mapper.Map(task), true)); default: break; } return BadRequest(); } } }