Merge branch 'worker-repairing' into dev

This commit is contained in:
Mikhail Kuznetsov
2023-09-21 15:55:57 +10:00
13 changed files with 250 additions and 102 deletions

View File

@@ -24,7 +24,7 @@ namespace PARR.DAL.Services.Implementations
public async Task<Template?> GetTemplateByNameAsync(string name) public async Task<Template?> GetTemplateByNameAsync(string name)
{ {
return await EntitySet.FirstOrDefaultAsync(t => t.Name == name); return await GetWithIncludes().FirstOrDefaultAsync(t => t.Name == name);
} }
public IQueryable<Template> GetWithIncludes() public IQueryable<Template> GetWithIncludes()

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.EsppTemplateSync.Domain
{
internal class EsppTemplate
{
public required string Name { get; set; }
public bool IsActive { get; set; }
public required string WorkGroup { get; set; }
public required string ShortDescription { get; set; }
public required string ResponseArea { get; set; }
public required string Duration { get; set; }
public required string EK { get; set; }
//public required string Initiator { get; set; }
public required string FullDescription { get; set; }
//public required string ClosingCode { get; set; }
public required string Solution { get; set; }
public required string Process { get; set; }
public required string SubProcess { get; set; }
public required string TNK { get; set; }
public required string Work { get; set; }
//public required string Worker { get; set; }
}
}

View File

@@ -18,6 +18,7 @@ namespace PARR.EsppTemplateSync
configuration.GetSection(nameof(GlobalSettings)).Bind(globalSettings); configuration.GetSection(nameof(GlobalSettings)).Bind(globalSettings);
services.AddSingleton(globalSettings); services.AddSingleton(globalSettings);
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
//services.AddTransient<ITemplateSyncer, TemplateFileSyncer>(); //services.AddTransient<ITemplateSyncer, TemplateFileSyncer>();
services.AddTransient<ITemplateSyncer, TemplateMQSyncer>(); services.AddTransient<ITemplateSyncer, TemplateMQSyncer>();
services.AddTransient<IParserService, ParserService>(); services.AddTransient<IParserService, ParserService>();

View File

@@ -0,0 +1,30 @@
using AutoMapper;
using PARR.DAL.Models;
using PARR.EsppTemplateSync.Domain;
namespace PARR.EsppTemplateSync.MappingProfiles
{
public class DomainToDomainProfile : Profile
{
public DomainToDomainProfile()
{
CreateMap<Template, EsppTemplate>()
.ForMember(d => d.Name, o => o.MapFrom(s => s.Name))
.ForMember(d => d.IsActive, o => o.MapFrom(s => s.IsActive))
.ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.Host!.WorkGroup))
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.ApplicationsInWork!.ShortDescription))
.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.ApplicationsInWork!.ShortDescription))
.ForMember(d => d.Duration, o => o.MapFrom(s => s.ApplicationsInWork!.TemplateDuration))
.ForMember(d => d.EK, o => o.MapFrom(s => s.Host!.Ek))
//.ForMember(d => d.Initiator, o => o.MapFrom(s => )) TODO откуда то нужно брать инициатора
.ForMember(d => d.FullDescription, o => o.MapFrom(s => s.ApplicationsInWork!.FullDescription))
//.ForMember(d => d.ClosingCode, o => o.MapFrom(s => s.)) TODO toоda же к инициатору
.ForMember(d => d.Solution, o => o.MapFrom(s => s.ApplicationsInWork!.Solution))
.ForMember(d => d.Process, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Process!.Name))
.ForMember(d => d.SubProcess, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Name))
.ForMember(d => d.TNK, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk!.Name))
.ForMember(d => d.Work, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Name));
}
}
}

View File

@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" /> <PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
</ItemGroup> </ItemGroup>

View File

@@ -1,9 +1,9 @@
using PARR.DAL.Models; using PARR.EsppTemplateSync.Domain;
namespace PARR.EsppTemplateSync.Services namespace PARR.EsppTemplateSync.Services
{ {
internal interface IParserService internal interface IParserService
{ {
Template? ParseString(string str); EsppTemplate? ParseString(string str);
} }
} }

View File

@@ -1,8 +1,10 @@
using Microsoft.Extensions.DependencyInjection; using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PARR.DAL.Contracts; using PARR.DAL.Contracts;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.EsppTemplateSync.Domain;
using PARR.EsppTemplateSync.Settings; using PARR.EsppTemplateSync.Settings;
namespace PARR.EsppTemplateSync.Services namespace PARR.EsppTemplateSync.Services
@@ -13,18 +15,21 @@ namespace PARR.EsppTemplateSync.Services
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;
private readonly IParserService parserService; private readonly IParserService parserService;
private readonly GlobalSettings globalSettings; private readonly GlobalSettings globalSettings;
private readonly IMapper mapper;
public Manager( public Manager(
ILogger<Manager> logger, ILogger<Manager> logger,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IParserService parserService, IParserService parserService,
GlobalSettings globalSettings GlobalSettings globalSettings,
IMapper mapper
) )
{ {
this.logger = logger; this.logger = logger;
this.serviceProvider = serviceProvider; this.serviceProvider = serviceProvider;
this.parserService = parserService; this.parserService = parserService;
this.globalSettings = globalSettings; this.globalSettings = globalSettings;
this.mapper = mapper;
} }
public Task<bool> ManageFileAsync(string path) public Task<bool> ManageFileAsync(string path)
@@ -40,9 +45,9 @@ namespace PARR.EsppTemplateSync.Services
if (str == null || str.Trim().Length == 0) if (str == null || str.Trim().Length == 0)
return false; return false;
var template = parserService.ParseString(str); var esppTemplate = parserService.ParseString(str);
if (template == null) if (esppTemplate == null)
{ {
isSuccess = false; isSuccess = false;
logger.LogError($"Не удалось распознать строку({str}) в Template"); logger.LogError($"Не удалось распознать строку({str}) в Template");
@@ -50,24 +55,86 @@ namespace PARR.EsppTemplateSync.Services
else else
{ {
//если шаблон не аквтивен, пропускаем //если шаблон не аквтивен, пропускаем
if (!template.IsActive) //if (!esppTemplate.IsActive)
{ //{
return isSuccess; // return isSuccess;
} //}
//TODO: !!! тут метод называет чек, но он же и сохраняет. По идее надо чтобы чек че то вернул, а исходя из этого дургой метод сохранит или ченить изменит await SyncTemplateAsync(esppTemplate);
// и опять же, saccess всегда true получается??? или это норм. // var template = await GetTemplateAsync(esppTemplate);
await CheckChangesAsync(template); //var isChanged = false;
//if (template == null)
//{
// // создает запись-шаблон из ЕСПП в ПАРР. Возможно избыточно так как эталон в ПАРР
// ////esppTemplate.StatusCode = "Deactivating";
// ////---
// //esppTemplate.StatusCode = (int)StatusTemplateEnum.Ok;
// //esppTemplate.IsActive = false;
// //if (!await templateService.CreateAsync(esppTemplate) || !await templateService.CommitAsync())
// //{
// // logger.LogError($"Не удалось создать запись Template {esppTemplate.Name}({esppTemplate.ShortDescription})");
// //}
// //else
// // logger.LogInformation($"----- Создана запись Template {esppTemplate.Name}({esppTemplate.ShortDescription}) -----");
// //---
// logger.LogWarning($"----- Найден шаблон ЕСПП незарегистрированный в ПАРР {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
// return false;
//}
//else isChanged = await CheckChangesAsync(esppTemplate, template);
////if (isChanged)
////var isChanged = await UpdateIfNeedAsync(template);
// //if (isChanged)
// //{
// // logger.LogInformation($"----- Запись в ЕСПП отличается от Template {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
// // //template.Status = "Updating";
// // template.StatusCode = (int)StatusTemplateEnum.Updating;
// // if (!await templateService.CommitAsync())
// // logger.LogError($"Не удалось обновить запись Template {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription})");
// // else
// // logger.LogInformation($"----- Требуется обновление шаблона в ЕСПП роботом {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
// //}
// //else
// //{
// // //if (template.Status != "Ok")
// // if (template.StatusCode != (int)StatusTemplateEnum.Ok)
// // {
// // template.DateModified = DateTimeOffset.UtcNow;
// // template.StatusCode = (int)StatusTemplateEnum.Ok;
// // if (!await templateService.CommitAsync())
// // logger.LogInformation($"Шаблон в ЕСПП соответствует шаблону в ПАРР {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}). Установлен статус {StatusTemplateEnum.Ok}");
// // }
// //}
} }
//todo: only true????? //todo: only true?????
return isSuccess; return isSuccess;
} }
private async Task CheckChangesAsync(Template esppTemplate) //private async Task<Template?> GetTemplateAsync(Template esppTemplate)
{ //{
// --- test --- // using (var scope = serviceProvider.CreateScope())
// {
// var services = scope.ServiceProvider;
// var templateService = services.GetService<ITemplateService>();
// if (templateService == null)
// {
// throw new Exception($"Не найден сервис: {nameof(ITemplateService)}");
// // return;
// }
// return await templateService.GetTemplateByNameAsync(esppTemplate.Name);
// }
//}
private async Task SyncTemplateAsync(EsppTemplate esppTemplate)
{
using (var scope = serviceProvider.CreateScope()) using (var scope = serviceProvider.CreateScope())
{ {
var services = scope.ServiceProvider; var services = scope.ServiceProvider;
@@ -80,7 +147,7 @@ namespace PARR.EsppTemplateSync.Services
// return; // return;
} }
var template = await templateService.GetTemplateByNameAsync(esppTemplate.Name); Template? template = await templateService.GetTemplateByNameAsync(esppTemplate.Name);
//существует в ЕСПП но отсутствует в ПАРР. //существует в ЕСПП но отсутствует в ПАРР.
//TODO деактивируем и видимо ещё что-то нужно //TODO деактивируем и видимо ещё что-то нужно
if (template == null) if (template == null)
@@ -97,65 +164,57 @@ namespace PARR.EsppTemplateSync.Services
//else //else
// logger.LogInformation($"----- Создана запись Template {esppTemplate.Name}({esppTemplate.ShortDescription}) -----"); // logger.LogInformation($"----- Создана запись Template {esppTemplate.Name}({esppTemplate.ShortDescription}) -----");
//--- //---
logger.LogWarning($"----- Найден шаблон ЕСПП незарегистрированный в ПАРР {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----"); logger.LogWarning($"----- Найден шаблон ЕСПП незарегистрированный в ПАРР {esppTemplate.Name}({esppTemplate.ShortDescription}) -----");
return;
} }
else else
{ {
var isChanged = false; var mappedTemplate = mapper.Map<EsppTemplate>(template);
//var ignoreTemplateFieldsList = globalSettings.IgnoreTemplateFields?.Split(",").ToList().Select(t => t.Trim().ToLower()); if (mappedTemplate == null)
return;
foreach (var prop in template.GetType().GetProperties()) var isChanged = IsChanged(mappedTemplate, esppTemplate);
{
if (prop == null) continue;
if (globalSettings.IgnoreTemplateFields != null && globalSettings.IgnoreTemplateFields.Contains(prop.Name)) continue;
//if (prop.Name == "Id" ||
// prop.Name == "Status" ||
// prop.Name == "DateCreated" ||
// prop.Name == "DateModified" ||
// prop.Name == "StatusCode"
// ) continue;
var parrValue = template.GetType().GetProperty(prop.Name)?.GetValue(template, null);
var esppValue = esppTemplate.GetType().GetProperty(prop.Name)?.GetValue(esppTemplate, null);
if (parrValue == null || esppValue == null) continue;
if (parrValue!.ToString()!.ToLower() != esppValue!.ToString()!.ToLower())
{
isChanged = true;
break;
}
}
if (isChanged) if (isChanged)
{ {
logger.LogInformation($"----- Запись в ЕСПП отличается от Template {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----"); SetUpdateStatus(template);
//template.Status = "Updating";
template.StatusCode = (int)StatusTemplateEnum.Updating;
if (!await templateService.CommitAsync()) if (!await templateService.CommitAsync())
logger.LogError($"Не удалось обновить запись Template {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription})");
else
logger.LogInformation($"----- Требуется обновление шаблона в ЕСПП роботом {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
}
else
{
//if (template.Status != "Ok")
if (template.StatusCode != (int)StatusTemplateEnum.Ok)
{ {
template.DateModified = DateTimeOffset.UtcNow; logger.LogError($"Не удалось изменить запись Template {template.Name}");
template.StatusCode = (int)StatusTemplateEnum.Ok;
if (!await templateService.CommitAsync())
logger.LogInformation($"Шаблон в ЕСПП соответствует шаблону в ПАРР {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}). Установлен статус {StatusTemplateEnum.Ok}");
} }
else
logger.LogInformation($"----- Установлен принудительный статус обновления Template {template.Name} -----");
} }
} }
} }
return;
}
private void SetUpdateStatus(Template template)
{
template.StatusCode = (int)StatusTemplateEnum.Updating;
}
private bool IsChanged(EsppTemplate template, EsppTemplate esppTemplate)
{
foreach (var prop in template.GetType().GetProperties())
{
if (prop == null) continue;
if (globalSettings.IgnoreTemplateFields != null && globalSettings.IgnoreTemplateFields.Contains(prop.Name)) continue;
var parrValue = template.GetType().GetProperty(prop.Name)?.GetValue(template, null);
var esppValue = esppTemplate.GetType().GetProperty(prop.Name)?.GetValue(esppTemplate, null);
if (parrValue == null || esppValue == null)
continue;
if (parrValue!.ToString()!.ToLower() != esppValue!.ToString()!.ToLower())
return true;
}
return false;
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PARR.DAL.Contracts; using PARR.EsppTemplateSync.Domain;
using PARR.DAL.Models; using PARR.EsppTemplateSync.Settings;
using PARR.DAL.Services.Interfaces;
using System.Globalization; using System.Globalization;
namespace PARR.EsppTemplateSync.Services namespace PARR.EsppTemplateSync.Services
@@ -9,10 +8,15 @@ namespace PARR.EsppTemplateSync.Services
internal class ParserService : IParserService internal class ParserService : IParserService
{ {
private readonly ILogger<ParserService> logger; private readonly ILogger<ParserService> logger;
private readonly GlobalSettings globalSettings;
public ParserService(ILogger<ParserService> logger) public ParserService(
ILogger<ParserService> logger,
GlobalSettings globalSettings
)
{ {
this.logger = logger; this.logger = logger;
this.globalSettings = globalSettings;
} }
public async Task<bool> ParseFileAsync(string path) public async Task<bool> ParseFileAsync(string path)
{ {
@@ -24,12 +28,11 @@ namespace PARR.EsppTemplateSync.Services
return isSuccess; return isSuccess;
} }
public Template? ParseString(string str) public EsppTemplate? ParseString(string str)
{ {
//TODO: а если формат нет тот? Все будет ок? //TODO: а если формат нет тот? Все будет ок?
//TODO: var splittedContent = str.Split(globalSettings.ParsingSeparator);
var splittedContent = str.Split("<|>");
if (splittedContent.Length != 17) if (splittedContent.Length != 17)
{ {
return null; return null;
@@ -55,35 +58,28 @@ namespace PARR.EsppTemplateSync.Services
var work = splittedContent[15].Trim(); var work = splittedContent[15].Trim();
var worker = splittedContent[16].Trim(); var worker = splittedContent[16].Trim();
//logger.LogInformation($"Получено сообщение: {ek}"); var template = new EsppTemplate
var template = new Template
{ {
Id = Guid.NewGuid(),
DateCreated = DateTime.UtcNow,
Name = name, Name = name,
IsActive = bool.Parse(isActive), IsActive = bool.Parse(isActive),
//WorkGroup = workGroup, WorkGroup = workGroup,
//ShortDescription = shortDescription, ShortDescription = shortDescription,
//Category = category, //Category = category,
//ResponseArea = responseArea, ResponseArea = responseArea,
//Duration = duration, Duration = duration,
//EK = ek, EK = ek,
//Initiator = initiator, //Initiator = initiator,
//FullDescription = fullDescription, FullDescription = fullDescription,
//ClosingCode = closingCode, //ClosingCode = closingCode,
//Solution = solution, Solution = solution,
//Process = process, Process = process,
//SubProcess = subProcess, SubProcess = subProcess,
//TNK = tnk, TNK = tnk,
//Work = work, Work = work,
//Worker = worker, //Worker = worker
//Status = "Checking"
StatusCode = (int)StatusTemplateEnum.Ok
}; };
//bool isSuccess = true;
return template; return template;
} }

View File

@@ -6,6 +6,7 @@
public StorageSettings? StorageSettings { get; set; } public StorageSettings? StorageSettings { get; set; }
public List<string>? IgnoreTemplateFields { get; set; } public List<string>? IgnoreTemplateFields { get; set; }
public string ParsingSeparator { get; set; } = "<|>";
} }
internal class MqSettings internal class MqSettings

View File

@@ -1,19 +1,50 @@
{ {
"ConnectionStrings": {
"DefaultConnection": "Server=10.99.253.184;Database=parr;User Id=app_parr; Password=PosdfkhT&)%sdfligL&%5546;"
},
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Debug"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "log/log-.txt",
"rollingInterval": "Day"
}
}
]
},
"StorageSettings": { "StorageSettings": {
"StoragePath": "W:\\" "StoragePath": "Data",
"EsppTemplates": {
"AllowedExtensions": [ ".csv" ],
"MaxFileSizeMb": 100
}
}, },
"GlobalSettings": { "GlobalSettings": {
"MqSettings": { "MqSettings": {
"HostName": "10.99.253.216",
"QueueName": "parr-espp-templates",
"UserName": "espp_templates_reader",
"Password": "P@ssReaderPtk202!"
}, },
"StorageSettings": { "StorageSettings": {
"CheckIntervalSeconds": 5 "CheckIntervalSeconds": 30
} },
"IgnoreTemplateFields": [ "Id", "Status", "Name", "DateCreated", "DateModified", "StatusCode" ],
"ParsingSeparator": "<|>"
} }
} }

View File

@@ -44,6 +44,7 @@
"StorageSettings": { "StorageSettings": {
"CheckIntervalSeconds": 30 "CheckIntervalSeconds": 30
}, },
"IgnoreTemplateFields": [ "Id","Status","DateCreated","DateModified","StatusCode" ] "IgnoreTemplateFields": [ "Id", "Status", "Name", "DateCreated", "DateModified", "StatusCode" ],
"ParsingSeparator": "<|>"
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -71,15 +71,15 @@ namespace PARR.MockData.Services
logger.LogInformation($"----- Создан subprocess: {subprocess.Name} -----"); logger.LogInformation($"----- Создан subprocess: {subprocess.Name} -----");
} }
var tnk = await tnkService.Get().FirstOrDefaultAsync(p => p.EsppId == 292454); var tnk = await tnkService.Get().FirstOrDefaultAsync(p => p.EsppId == 292917);
if (tnk == null) if (tnk == null)
{ {
tnk = new Tnk tnk = new Tnk
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
DateCreated = DateTimeOffset.UtcNow, DateCreated = DateTimeOffset.UtcNow,
Name = ПО Анализ прикладных журналов серверов приложений (О3.2.2.4)", Name = рочее(работы)",
EsppId = 292454, EsppId = 292917,
SubprocessId = subprocess.Id SubprocessId = subprocess.Id
}; };
if (!await tnkService.CreateAsync(tnk) || !await tnkService.CommitAsync()) if (!await tnkService.CreateAsync(tnk) || !await tnkService.CommitAsync())
@@ -91,15 +91,15 @@ namespace PARR.MockData.Services
logger.LogInformation($"----- Создан tnk: {tnk.Name} -----"); logger.LogInformation($"----- Создан tnk: {tnk.Name} -----");
} }
var work = await workService.Get().FirstOrDefaultAsync(p => p.EsppId == 292454); var work = await workService.Get().FirstOrDefaultAsync(p => p.EsppId == 292917);
if (work == null) if (work == null)
{ {
work = new Work work = new Work
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
DateCreated = DateTimeOffset.UtcNow, DateCreated = DateTimeOffset.UtcNow,
Name = ПО Анализ прикладных журналов серверов приложений (О3.2.2.4)", Name = рочее(работы)",
EsppId = 292454, EsppId = 292917,
TnkId = tnk.Id TnkId = tnk.Id
}; };
if (!await workService.CreateAsync(work) || !await workService.CommitAsync()) if (!await workService.CreateAsync(work) || !await workService.CommitAsync())