feat(api): Выдача заданий агенту.

This commit is contained in:
Mikhail Trubnikov
2023-10-17 16:59:53 +10:00
parent 26bd0a9a6b
commit a1f19c7ac8
12 changed files with 3126 additions and 2 deletions

View File

@@ -41,6 +41,11 @@
public const string getParam = "{id}";
}
public static class AgentTask
{
public const string GetByIp = Base + "/agent-tasks/ip";
}
//public static class EsppData
//{
// public const string UploadTemplates = Base + "/espp-data/templates";

View File

@@ -0,0 +1,15 @@
namespace PARR.API.Contracts.V1.Requests.Queries
{
public class AgentTaskGetByIpQuery
{
/// <summary>
/// По-умолчанию берётся IP-клиента
/// </summary>
public string? Ip { get; set; }
/// <summary>
/// По-умолчанию расписание на сегодня
/// </summary>
public DateTimeOffset? Date { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
namespace PARR.API.Contracts.V1.Responses
{
public class AgentTaskResponse
{
}
public class AgentTaskMinResponse
{
public List<AgentTaskMinScheduleResponse> Scheduled { get; set; } = new List<AgentTaskMinScheduleResponse>();
}
public class AgentTaskMinScheduleResponse
{
public DateTimeOffset StartAt { get; set; }
public required string Script { get; set; }
public required string Name { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace PARR.API.Contracts.V1.Responses
{
public class TemplateAgentResponse
{
public bool? IsAgent { get; set; }
public string? Name { get; set; }
public string? Script { get; set; }
public int? TimeOutSec { get; set; }
}
}

View File

@@ -16,6 +16,11 @@
public required string Solution { get; set; }
public required string TemplateDuration { get; set; }
public TemplateAgentResponse? Agent { get; set; }
public DateTimeOffset? LastRun { get; set; }
public DateTimeOffset NextRun { get; set; }
public HostResponse? Host { get; set; }

View File

@@ -0,0 +1,111 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests.Queries;
using PARR.API.Contracts.V1.Responses;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Controllers.V1.Base;
using PARR.API.Services.Interfaces;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.TransformServices;
namespace PARR.API.Controllers.V1
{
/// <summary>
/// Выдает задания Агенту сервера
/// </summary>
public class AgentTaskController : BaseApiController
{
private readonly IMapper mapper;
private readonly IClientService clientService;
private readonly ITemplateService templateService;
private readonly IEsppScheduleTransformService esppScheduleTransformService;
private readonly ILogger<AgentTaskController> logger;
public AgentTaskController(
IMapper mapper,
IClientService clientService,
ITemplateService templateService,
IEsppScheduleTransformService esppScheduleTransformService,
ILogger<AgentTaskController> logger
)
{
this.mapper = mapper;
this.clientService = clientService;
this.templateService = templateService;
this.esppScheduleTransformService = esppScheduleTransformService;
this.logger = logger;
}
/// <summary>
/// Список заданий агенту по ip-адресу клиента исполнителя
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpGet(ApiRoutes.AgentTask.GetByIp)]
public async Task<IActionResult> GetByClientIp([FromQuery] AgentTaskGetByIpQuery request)
{
//ПАРР-ДВС-ПТК__ВРТ-DVGD-SDMI-WEB-01-ДВС__ПРОЧЕЕ(РАБОТЫ)
//10.99.253.65
//2023-10-16
var ip = request.Ip ?? clientService.GetClientIp()?.ToString();
if (string.IsNullOrEmpty(ip))
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Client IP address is null." } }));
var date = request.Date ?? DateTimeOffset.UtcNow;
//Агент получает задания, если `IsAgent = true`, шаблон и расписания активны, и статус синхронизации шаблона и расписания `= Ok`, и `NextRun = сегодня`.
// С одним IP может быть несколько информационных систем, так что может быть несколько хостов
var templates = await templateService.Get()
.Include(t => t.RobotConfigurations)
.Include(t => t.ApplicationsInWork)
.Include(t => t.Host)
.Where(t => t.Host!.IP == ip
&& t.ApplicationsInWork!.IsAgent == true
&& t.IsActiveTemplate == true
&& t.IsActiveSchedule == true
&& t.ApplicationsInWork!.NextRun.DateTime.Date == date.Date.Date
&& t.RobotConfigurations.All(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok)
).ToListAsync();
if (!templates.Any())
return NoContent();
// запросить расписание на день для каждого шаблона и сформировать из него список
//TODO: идти в appInWorks и отуда формировать список заданий. Так же, как делать если время у заданий совпадает?
var response = new AgentTaskMinResponse
{
Scheduled = new List<AgentTaskMinScheduleResponse>()
};
foreach (var template in templates)
{
var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.LastRun ?? template.ApplicationsInWork!.NextRun);
if (!templateSchedule.Any())
{
logger.LogWarning($"Запросили рапсисание для агента по LastRun и вернулся пустой список! Такого не должно быть! " +
$"ApplicationInWorkId: {template.ApplicationInWorkId}, latRun: {template.ApplicationsInWork!.LastRun}, NextRun: {template.ApplicationsInWork!.NextRun}, ip: {ip}, date: {date}");
continue;
}
// TODO: проверку что в бд есть поля AgentName, AgentScript
templateSchedule.ForEach(item => response.Scheduled.Add(new AgentTaskMinScheduleResponse { Name = template.ApplicationsInWork!.AgentName, Script = template.ApplicationsInWork!.AgentScript, StartAt = item }));
}
// отсортировать потом по дате
// минимальный респонс
return Ok(response);
}
}
}

View File

@@ -138,7 +138,9 @@ namespace PARR.API.Controllers.V1
// передаем LastRun, если его нет, то NextRun
var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun);
appInWorks.LastRun = appInWorks.NextRun;
if (appInWorks.LastRun != null)
appInWorks.LastRun = appInWorks.NextRun;
appInWorks.NextRun = nextRun;
await robotConfigurationService.CommitAsync();

View File

@@ -44,11 +44,20 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.ClosingCode, o => o.MapFrom<TemplateClosingCodeResolver>())
.ForMember(d => d.Category, o => o.MapFrom<TemplateCategoryResolver>())
.ForMember(d => d.SyncStatus, o => o.MapFrom(s => s.RobotConfigurations))
.ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>());
.ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>())
.ForMember(d => d.Agent, o => o.MapFrom(s => s.ApplicationsInWork))
.ForMember(d => d.NextRun, o => o.MapFrom(s => s.ApplicationsInWork!.NextRun))
.ForMember(d => d.LastRun, o => o.MapFrom(s => s.ApplicationsInWork!.LastRun));
// === Template ===
CreateMap<Template, TemplateScheduleEsppIdResponse>();
CreateMap<ApplicationsInWork, TemplateAgentResponse>()
.ForMember(d => d.IsAgent, o => o.MapFrom(s => s.IsAgent))
.ForMember(d => d.Name, o => o.MapFrom(s => s.AgentName))
.ForMember(d => d.Script, o => o.MapFrom(s => s.AgentScript))
.ForMember(d => d.TimeOutSec, o => o.MapFrom(s => s.AgentTimeOutSec));
CreateMap<DAL.Models.TaskStatus, TaskStatusResponse>();