diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json index 1d9e827e..e0ebee46 100644 --- a/PARR.API/appsettings.json +++ b/PARR.API/appsettings.json @@ -6,7 +6,8 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "None" } }, "Serilog": { @@ -14,7 +15,8 @@ "Default": "Information", "Override": { "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "Fatal" } } }, diff --git a/PARR.Core/Repositories/Interfaces/TemplateRepositories/ITemplateRenamePendingRepository.cs b/PARR.Core/Repositories/Interfaces/TemplateRepositories/ITemplateRenamePendingRepository.cs new file mode 100644 index 00000000..9e892852 --- /dev/null +++ b/PARR.Core/Repositories/Interfaces/TemplateRepositories/ITemplateRenamePendingRepository.cs @@ -0,0 +1,10 @@ +using PARR.Domain.Entities.TemplateEntities; + +namespace PARR.Core.Repositories.Interfaces.TemplateRepositories +{ + public interface ITemplateRenamePendingRepository + { + Task CreateAsync(TemplateRenamePending obj); + IQueryable Get(); + } +} diff --git a/PARR.DAL/DependencyInjection.cs b/PARR.DAL/DependencyInjection.cs index 8a41b0f7..c2d342b9 100644 --- a/PARR.DAL/DependencyInjection.cs +++ b/PARR.DAL/DependencyInjection.cs @@ -8,6 +8,7 @@ using PARR.Core.Repositories.Interfaces.JobRepositories; using PARR.Core.Repositories.Interfaces.RobotRepositories; using PARR.Core.Repositories.Interfaces.Schedule; using PARR.Core.Repositories.Interfaces.TaskRepositories; +using PARR.Core.Repositories.Interfaces.TemplateRepositories; using PARR.Core.Repositories.Interfaces.Unit; using PARR.DAL.Configurations.DbSettings; using PARR.DAL.Context; @@ -18,6 +19,7 @@ using PARR.DAL.Repositories.JobRepositories; using PARR.DAL.Repositories.RobotRepositories; using PARR.DAL.Repositories.Schedule; using PARR.DAL.Repositories.TaskRepositories; +using PARR.DAL.Repositories.TemplateRepositories; using PARR.DAL.Repositories.Unit; using PARR.Domain.Settings; @@ -142,6 +144,12 @@ namespace PARR.DAL #endregion + #region Templates + + services.AddScoped(); + + #endregion + //services.AddTransient(); #region NextRun Services diff --git a/PARR.DAL/Repositories/Base/BaseRepository.cs b/PARR.DAL/Repositories/Base/BaseRepository.cs index 7eedce14..98e83bc1 100644 --- a/PARR.DAL/Repositories/Base/BaseRepository.cs +++ b/PARR.DAL/Repositories/Base/BaseRepository.cs @@ -15,16 +15,6 @@ namespace PARR.DAL.Repositories.Base { internal abstract class BaseRepository : IBaseRepository where T : class, IBaseEntity { - //private readonly ILogger> logger; - - //protected abstract DbSet EntitySet { get; } - //protected abstract DataContext EntitiContext { get; } - - //public BaseRepository(ILogger> logger) - //{ - // this.logger = logger; - //} - protected readonly ILogger logger; protected readonly DbSet EntitySet; protected readonly DataContext EntityContext; diff --git a/PARR.DAL/Repositories/TemplateRepositories/TemplateRenamePendingRepository.cs b/PARR.DAL/Repositories/TemplateRepositories/TemplateRenamePendingRepository.cs new file mode 100644 index 00000000..a1e0f023 --- /dev/null +++ b/PARR.DAL/Repositories/TemplateRepositories/TemplateRenamePendingRepository.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; +using PARR.Core.Repositories.Interfaces.TemplateRepositories; +using PARR.DAL.Context; +using PARR.Domain.Entities.TemplateEntities; + +namespace PARR.DAL.Repositories.TemplateRepositories +{ + internal class TemplateRenamePendingRepository : ITemplateRenamePendingRepository + { + private readonly DataContext _dataContext; + private readonly ILogger _logger; + + public TemplateRenamePendingRepository( + DataContext dataContext, + ILogger logger + ) + { + _dataContext = dataContext; + _logger = logger; + } + + + public IQueryable Get() + { + return _dataContext.TemplateRenamePendings; + } + + public async Task CreateAsync(TemplateRenamePending obj) + { + try + { + await _dataContext.TemplateRenamePendings.AddAsync(obj); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка при добавлении объекта типа TemplateRenamePending в БД"); + return false; + } + } + } +} diff --git a/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs b/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs index ca86b4e5..3ed6c86a 100644 --- a/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs +++ b/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs @@ -3,10 +3,13 @@ using Microsoft.Extensions.Logging; using PARR.Core.Extensions; using PARR.Core.Repositories.Interfaces; using PARR.Core.Repositories.Interfaces.JobRepositories; +using PARR.Core.Repositories.Interfaces.TemplateRepositories; using PARR.Core.Repositories.Interfaces.Unit; using PARR.Core.Services.NextRunServices; using PARR.Domain.Common.Rabbit.Messages.TemplateMatching; +using PARR.Domain.Entities; using PARR.Domain.Entities.JobEntities; +using PARR.Domain.Entities.TemplateEntities; using PARR.Domain.Enums; namespace PARR.TemplateUpdater.Services @@ -20,6 +23,7 @@ namespace PARR.TemplateUpdater.Services private readonly IRobotConfigurationRepository robotConfigurationService; private readonly INextRunService nextRunService; private readonly IUnitInValueRepository unitInValueService; + private readonly ITemplateRenamePendingRepository _templateRenamePendingRepository; public TemplateUpdaterService( ILogger logger, @@ -28,7 +32,8 @@ namespace PARR.TemplateUpdater.Services IUnitRepository unitService, IRobotConfigurationRepository robotConfigurationService, INextRunService nextRunService, - IUnitInValueRepository unitInValueService + IUnitInValueRepository unitInValueService, + ITemplateRenamePendingRepository templateRenamePendingRepository ) { this.logger = logger; @@ -38,6 +43,7 @@ namespace PARR.TemplateUpdater.Services this.robotConfigurationService = robotConfigurationService; this.nextRunService = nextRunService; this.unitInValueService = unitInValueService; + _templateRenamePendingRepository = templateRenamePendingRepository; } @@ -53,7 +59,8 @@ namespace PARR.TemplateUpdater.Services var template = await templateService.Get() .Include(t => t.RobotConfigurations) .Include(t => t.UnitsInTemplate) - .AsSplitQuery() + //.AsSplitQuery() + .AsSingleQuery() .FirstOrDefaultAsync(t => t.Id == query.TemplateId); if (template == null) { @@ -64,9 +71,14 @@ namespace PARR.TemplateUpdater.Services var templateIsChanged = false; var scheduleIsChanged = false; - if (template.Name != query.Name.Trim()) + var trimmedNewName = query.Name.Trim(); + if (template.Name != trimmedNewName) { - template.Name = query.Name.Trim(); + var prepareOldNameResult = await PrepareOldTemplateNameAsync(template.Name, trimmedNewName, template); + if (!prepareOldNameResult) + return; + + template.Name = trimmedNewName; templateIsChanged = true; scheduleIsChanged = true; } @@ -276,5 +288,57 @@ namespace PARR.TemplateUpdater.Services return true; } + + + /// + /// Добавление записи в таблицу ожидания переименования + /// + /// + /// + /// + /// + private async Task PrepareOldTemplateNameAsync(string oldName, string newName, Template template) + { + // Проверяем, не запущено ли уже переименование для этого шаблона + var alreadyPending = await _templateRenamePendingRepository.Get() + .AsNoTracking() + .FirstOrDefaultAsync(t => t.TemplateId == template.Id); + + if (alreadyPending != null) + { + logger.LogError("При попытке переименования шаблона {TemplateId}, из '{OldName}' в '{NewName}', " + + "произошла ошибка, этот шаблон уже находится в процессе переименования (старое имя {PendingName})", template.Id, oldName, newName, alreadyPending.OldName); + return false; + } + + // Уникально ли имя в таблице ожидания переименования + var existPendingOldName = await _templateRenamePendingRepository.Get() + .AsNoTracking() + .FirstOrDefaultAsync(t => t.OldName == oldName); + + if (existPendingOldName != null) + { + logger.LogError("При добавлении старого имени в таблицу ожидания для шаблона {TemplateId} обнаружен конфликт: " + + "имя '{ExistOldName}' уже зарезервировано другим процессом для шаблона {ExistTemplateId}", + template.Id, existPendingOldName.OldName, existPendingOldName.TemplateId); + + return false; + } + + // Все нормально, добавляем запись в таблицу + var pendingRename = new TemplateRenamePending + { + TemplateId = template.Id, + DateCreated = DateTimeOffset.UtcNow, + OldName = oldName, + Template = template + }; + + var addResult = await _templateRenamePendingRepository.CreateAsync(pendingRename); + if (!addResult) + return false; + + return true; + } } } \ No newline at end of file