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)
{
return await EntitySet.FirstOrDefaultAsync(t => t.Name == name);
return await GetWithIncludes().FirstOrDefaultAsync(t => t.Name == name);
}
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);
services.AddSingleton(globalSettings);
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
//services.AddTransient<ITemplateSyncer, TemplateFileSyncer>();
services.AddTransient<ITemplateSyncer, TemplateMQSyncer>();
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>
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
</ItemGroup>

View File

@@ -1,9 +1,9 @@
using PARR.DAL.Models;
using PARR.EsppTemplateSync.Domain;
namespace PARR.EsppTemplateSync.Services
{
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 PARR.DAL.Contracts;
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces;
using PARR.EsppTemplateSync.Domain;
using PARR.EsppTemplateSync.Settings;
namespace PARR.EsppTemplateSync.Services
@@ -13,18 +15,21 @@ namespace PARR.EsppTemplateSync.Services
private readonly IServiceProvider serviceProvider;
private readonly IParserService parserService;
private readonly GlobalSettings globalSettings;
private readonly IMapper mapper;
public Manager(
ILogger<Manager> logger,
IServiceProvider serviceProvider,
IParserService parserService,
GlobalSettings globalSettings
GlobalSettings globalSettings,
IMapper mapper
)
{
this.logger = logger;
this.serviceProvider = serviceProvider;
this.parserService = parserService;
this.globalSettings = globalSettings;
this.mapper = mapper;
}
public Task<bool> ManageFileAsync(string path)
@@ -40,9 +45,9 @@ namespace PARR.EsppTemplateSync.Services
if (str == null || str.Trim().Length == 0)
return false;
var template = parserService.ParseString(str);
var esppTemplate = parserService.ParseString(str);
if (template == null)
if (esppTemplate == null)
{
isSuccess = false;
logger.LogError($"Не удалось распознать строку({str}) в Template");
@@ -50,24 +55,86 @@ namespace PARR.EsppTemplateSync.Services
else
{
//если шаблон не аквтивен, пропускаем
if (!template.IsActive)
{
return isSuccess;
}
//if (!esppTemplate.IsActive)
//{
// return isSuccess;
//}
//TODO: !!! тут метод называет чек, но он же и сохраняет. По идее надо чтобы чек че то вернул, а исходя из этого дургой метод сохранит или ченить изменит
// и опять же, saccess всегда true получается??? или это норм.
await CheckChangesAsync(template);
await SyncTemplateAsync(esppTemplate);
// var template = await GetTemplateAsync(esppTemplate);
//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?????
return isSuccess;
}
private async Task CheckChangesAsync(Template esppTemplate)
{
// --- test ---
//private async Task<Template?> GetTemplateAsync(Template esppTemplate)
//{
// 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())
{
var services = scope.ServiceProvider;
@@ -80,7 +147,7 @@ namespace PARR.EsppTemplateSync.Services
// return;
}
var template = await templateService.GetTemplateByNameAsync(esppTemplate.Name);
Template? template = await templateService.GetTemplateByNameAsync(esppTemplate.Name);
//существует в ЕСПП но отсутствует в ПАРР.
//TODO деактивируем и видимо ещё что-то нужно
if (template == null)
@@ -97,65 +164,57 @@ namespace PARR.EsppTemplateSync.Services
//else
// logger.LogInformation($"----- Создана запись Template {esppTemplate.Name}({esppTemplate.ShortDescription}) -----");
//---
logger.LogWarning($"----- Найден шаблон ЕСПП незарегистрированный в ПАРР {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
logger.LogWarning($"----- Найден шаблон ЕСПП незарегистрированный в ПАРР {esppTemplate.Name}({esppTemplate.ShortDescription}) -----");
return;
}
else
{
var isChanged = false;
//var ignoreTemplateFieldsList = globalSettings.IgnoreTemplateFields?.Split(",").ToList().Select(t => t.Trim().ToLower());
foreach (var prop in template.GetType().GetProperties())
{
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;
}
}
var mappedTemplate = mapper.Map<EsppTemplate>(template);
if (mappedTemplate == null)
return;
var isChanged = IsChanged(mappedTemplate, esppTemplate);
if (isChanged)
{
logger.LogInformation($"----- Запись в ЕСПП отличается от Template {esppTemplate.Name}({esppTemplate.ApplicationsInWork?.ShortDescription}) -----");
//template.Status = "Updating";
template.StatusCode = (int)StatusTemplateEnum.Updating;
SetUpdateStatus(template);
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}");
logger.LogError($"Не удалось изменить запись Template {template.Name}");
}
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 PARR.DAL.Contracts;
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces;
using PARR.EsppTemplateSync.Domain;
using PARR.EsppTemplateSync.Settings;
using System.Globalization;
namespace PARR.EsppTemplateSync.Services
@@ -9,10 +8,15 @@ namespace PARR.EsppTemplateSync.Services
internal class ParserService : IParserService
{
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.globalSettings = globalSettings;
}
public async Task<bool> ParseFileAsync(string path)
{
@@ -24,12 +28,11 @@ namespace PARR.EsppTemplateSync.Services
return isSuccess;
}
public Template? ParseString(string str)
public EsppTemplate? ParseString(string str)
{
//TODO: а если формат нет тот? Все будет ок?
//TODO:
var splittedContent = str.Split("<|>");
var splittedContent = str.Split(globalSettings.ParsingSeparator);
if (splittedContent.Length != 17)
{
return null;
@@ -55,35 +58,28 @@ namespace PARR.EsppTemplateSync.Services
var work = splittedContent[15].Trim();
var worker = splittedContent[16].Trim();
//logger.LogInformation($"Получено сообщение: {ek}");
var template = new Template
var template = new EsppTemplate
{
Id = Guid.NewGuid(),
DateCreated = DateTime.UtcNow,
Name = name,
IsActive = bool.Parse(isActive),
//WorkGroup = workGroup,
//ShortDescription = shortDescription,
WorkGroup = workGroup,
ShortDescription = shortDescription,
//Category = category,
//ResponseArea = responseArea,
//Duration = duration,
//EK = ek,
ResponseArea = responseArea,
Duration = duration,
EK = ek,
//Initiator = initiator,
//FullDescription = fullDescription,
FullDescription = fullDescription,
//ClosingCode = closingCode,
//Solution = solution,
//Process = process,
//SubProcess = subProcess,
//TNK = tnk,
//Work = work,
//Worker = worker,
//Status = "Checking"
StatusCode = (int)StatusTemplateEnum.Ok
Solution = solution,
Process = process,
SubProcess = subProcess,
TNK = tnk,
Work = work,
//Worker = worker
};
//bool isSuccess = true;
return template;
}

View File

@@ -6,6 +6,7 @@
public StorageSettings? StorageSettings { get; set; }
public List<string>? IgnoreTemplateFields { get; set; }
public string ParsingSeparator { get; set; } = "<|>";
}
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": {
"LogLevel": {
"Default": "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": {
"StoragePath": "W:\\"
"StoragePath": "Data",
"EsppTemplates": {
"AllowedExtensions": [ ".csv" ],
"MaxFileSizeMb": 100
}
},
"GlobalSettings": {
"MqSettings": {
"HostName": "10.99.253.216",
"QueueName": "parr-espp-templates",
"UserName": "espp_templates_reader",
"Password": "P@ssReaderPtk202!"
},
"StorageSettings": {
"CheckIntervalSeconds": 5
}
"CheckIntervalSeconds": 30
},
"IgnoreTemplateFields": [ "Id", "Status", "Name", "DateCreated", "DateModified", "StatusCode" ],
"ParsingSeparator": "<|>"
}
}

View File

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