diff --git a/AsbCloudApp/Data/NotificationDto.cs b/AsbCloudApp/Data/NotificationDto.cs
index 2b47ccc0..2f4b09dd 100644
--- a/AsbCloudApp/Data/NotificationDto.cs
+++ b/AsbCloudApp/Data/NotificationDto.cs
@@ -1,5 +1,4 @@
using System;
-using AsbCloudApp.Data.User;
namespace AsbCloudApp.Data;
@@ -79,9 +78,4 @@ public class NotificationDto : IId
/// DTO категории уведомления
///
public NotificationCategoryDto NotificationCategory { get; set; } = null!;
-
- ///
- /// DTO получателя уведомления
- ///
- public UserDto User { get; set; } = null!;
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/Notifications/NotificationService.cs b/AsbCloudApp/Services/Notifications/NotificationService.cs
index 5be9ab33..6d6fc6d7 100644
--- a/AsbCloudApp/Services/Notifications/NotificationService.cs
+++ b/AsbCloudApp/Services/Notifications/NotificationService.cs
@@ -16,7 +16,6 @@ namespace AsbCloudApp.Services.Notifications;
public class NotificationService
{
private readonly ICrudRepository notificationCategoryRepository;
- private readonly IUserRepository userRepository;
private readonly INotificationRepository notificationRepository;
private readonly IEnumerable notificationTransportServices;
@@ -28,11 +27,9 @@ public class NotificationService
///
///
public NotificationService(ICrudRepository notificationCategoryRepository,
- IUserRepository userRepository,
INotificationRepository notificationRepository,
IEnumerable notificationTransportServices)
{
- this.userRepository = userRepository;
this.notificationCategoryRepository = notificationCategoryRepository;
this.notificationRepository = notificationRepository;
this.notificationTransportServices = notificationTransportServices;
@@ -50,14 +47,11 @@ public class NotificationService
.GetOrDefaultAsync(request.IdNotificationCategory, cancellationToken)
?? throw new ArgumentInvalidException("Категория уведомления не найдена", nameof(request.IdNotificationCategory));
- var user = await userRepository.GetOrDefaultAsync(request.IdUser, cancellationToken)
- ?? throw new ArgumentInvalidException("Пользователь не найден" , nameof(request.IdUser));
-
var notification = new NotificationDto
{
IdUser = request.IdUser,
RegistrationDate = DateTime.UtcNow,
- IdNotificationCategory = request.IdNotificationCategory,
+ IdNotificationCategory = notificationCategory.Id,
Title = request.Title,
Message = request.Message,
IdTransportType = request.IdTransportType,
@@ -65,8 +59,7 @@ public class NotificationService
notification.Id = await notificationRepository.InsertAsync(notification, cancellationToken);
notification.NotificationCategory = notificationCategory;
- notification.User = user;
-
+
var notificationTransportService = GetNotificationTransportService(request.IdTransportType);
await notificationTransportService.SendAsync(notification, cancellationToken);
diff --git a/AsbCloudInfrastructure/Background/BackgroundWorker.cs b/AsbCloudInfrastructure/Background/BackgroundWorker.cs
index e50b21b8..7c88fade 100644
--- a/AsbCloudInfrastructure/Background/BackgroundWorker.cs
+++ b/AsbCloudInfrastructure/Background/BackgroundWorker.cs
@@ -7,7 +7,6 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background
{
-# nullable enable
///
/// Сервис для фонового выполнения работы
///
@@ -94,5 +93,4 @@ namespace AsbCloudInfrastructure.Background
}
}
}
-
}
diff --git a/AsbCloudInfrastructure/Background/NotificationBackgroundWorker.cs b/AsbCloudInfrastructure/Background/NotificationBackgroundWorker.cs
new file mode 100644
index 00000000..4b68df31
--- /dev/null
+++ b/AsbCloudInfrastructure/Background/NotificationBackgroundWorker.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace AsbCloudInfrastructure.Background;
+
+public class NotificationBackgroundWorker : BackgroundWorker
+{
+ public NotificationBackgroundWorker(IServiceProvider serviceProvider) : base(serviceProvider)
+ {
+ }
+}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 64a2fa49..c40afca9 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -111,6 +111,7 @@ namespace AsbCloudInfrastructure
services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider));
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration));
services.AddTransient();
diff --git a/AsbCloudInfrastructure/Repository/NotificationRepository.cs b/AsbCloudInfrastructure/Repository/NotificationRepository.cs
index 37e3e4bd..c3302c95 100644
--- a/AsbCloudInfrastructure/Repository/NotificationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/NotificationRepository.cs
@@ -8,21 +8,21 @@ using AsbCloudDb;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Caching.Memory;
namespace AsbCloudInfrastructure.Repository;
-public class NotificationRepository : CrudCacheRepositoryBase, INotificationRepository
+public class NotificationRepository : CrudRepositoryBase, INotificationRepository
{
private static IQueryable MakeQueryNotification(DbSet dbSet)
=> dbSet.Include(n => n.NotificationCategory)
.Include(n => n.User)
.AsNoTracking();
- public NotificationRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache)
- : base(dbContext, memoryCache, MakeQueryNotification)
+ public NotificationRepository(IAsbCloudDbContext context)
+ : base(context, MakeQueryNotification)
{
}
+
public async Task> GetNotificationsAsync(int idUser,
NotificationRequest request,
@@ -33,7 +33,7 @@ public class NotificationRepository : CrudCacheRepositoryBase()
+ var result = new PaginationContainer
{
Skip = skip,
Take = take,
@@ -61,13 +61,12 @@ public class NotificationRepository : CrudCacheRepositoryBase x.NotificationCategory)
.Where(n => n.IdUser == idUser);
- if (request.IsSent.HasValue)
+ if (request.IsSent.HasValue)
{
- if(request.IsSent.Value)
- query = query.Where(n => n.SentDate != null);
- else
- query = query.Where(n => n.SentDate == null);
- }
+ query = request.IsSent.Value ?
+ query.Where(n => n.SentDate != null)
+ : query.Where(n => n.SentDate == null);
+ }
if (request.IdTransportType.HasValue)
query = query.Where(n => n.IdTransportType == request.IdTransportType);
diff --git a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
index 2dd225f6..e0f4ba0e 100644
--- a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
+++ b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
@@ -50,7 +50,7 @@ namespace AsbCloudInfrastructure.Services.Email
return Task.CompletedTask;
}
- var workId = MakeWorkId(notification.User.Email, notification.Title, notification.Message);
+ var workId = MakeWorkId(notification.IdUser, notification.Title, notification.Message);
if (!backgroundWorker.Contains(workId))
{
var workAction = MakeEmailSendWorkAction(notification);
@@ -73,17 +73,23 @@ namespace AsbCloudInfrastructure.Services.Email
private Func MakeEmailSendWorkAction(NotificationDto notification)
{
- if(!MailAddress.TryCreate(notification.User.Email, out var mailAddress))
- Trace.TraceWarning($"Mail {notification.User.Email} is not correct.");
-
- if (mailAddress is null)
- throw new ArgumentInvalidException($"Mail {notification.User.Email} is not null.", nameof(notification.User.Email));
-
if (string.IsNullOrWhiteSpace(notification.Title))
throw new ArgumentInvalidException($"{nameof(notification.Title)} should be set", nameof(notification.Title));
return async (_, serviceProvider, token) =>
{
+ var notificationRepository = serviceProvider.GetRequiredService();
+ var userRepository = serviceProvider.GetRequiredService();
+
+ var user = await userRepository.GetOrDefaultAsync(notification.IdUser, token)
+ ?? throw new ArgumentInvalidException("Пользователь не найден" , nameof(notification.IdUser));
+
+ if(!MailAddress.TryCreate(user.Email, out var mailAddress))
+ Trace.TraceWarning($"Mail {user.Email} is not correct.");
+
+ if (mailAddress is null)
+ throw new ArgumentInvalidException($"Mail {user.Email} is not null.", nameof(user.Email));
+
var from = new MailAddress(sender);
var message = new MailMessage
{
@@ -105,17 +111,15 @@ namespace AsbCloudInfrastructure.Services.Email
notification.SentDate = DateTime.UtcNow;
- var notificationRepository = serviceProvider.GetRequiredService();
-
await notificationRepository.UpdateAsync(notification, token);
- Trace.TraceInformation($"Send email to {notification.User.Email} subj:{notification.Title} html body count {notification.Message.Length}");
+ Trace.TraceInformation($"Send email to {user.Email} subj:{notification.Title} html body count {notification.Message.Length}");
};
}
- private static string MakeWorkId(string address, string subject, string content)
+ private static string MakeWorkId(int idUser, string subject, string content)
{
- var hash = address.GetHashCode();
+ var hash = idUser.GetHashCode();
hash ^= subject.GetHashCode();
hash ^= content.GetHashCode();
return hash.ToString("x");
diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs
index 207270c2..55cd361c 100644
--- a/AsbCloudInfrastructure/Startup.cs
+++ b/AsbCloudInfrastructure/Startup.cs
@@ -40,8 +40,14 @@ namespace AsbCloudInfrastructure
backgroundWorker.Push(LimitingParameterCalcWorkFactory.MakeWork());
backgroundWorker.Push(MakeMemoryMonitoringWork());
+ var notificationBackgroundWorker = provider.GetRequiredService();
+
Task.Delay(1_000)
- .ContinueWith(async (_) => await backgroundWorker.StartAsync(CancellationToken.None));
+ .ContinueWith(async (_) =>
+ {
+ await backgroundWorker.StartAsync(CancellationToken.None);
+ await notificationBackgroundWorker.StartAsync(CancellationToken.None);
+ });
}
static WorkPeriodic MakeMemoryMonitoringWork()
diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
index e84ad6ae..fda6e0f9 100644
--- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
+++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
@@ -145,7 +145,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests
.Returns(1);
notificationService = new NotificationService(notificationCategoryRepositoryMock.Object,
- userRepositoryMock.Object,
new Mock().Object,
new [] { notificationTransportServiceMock.Object });
diff --git a/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs b/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
index 63fd8f8e..c29ea241 100644
--- a/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
+++ b/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
@@ -6,50 +6,47 @@ using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services.Notifications;
+using AsbCloudInfrastructure.Background;
using Microsoft.AspNetCore.SignalR;
+using Microsoft.Extensions.DependencyInjection;
namespace AsbCloudWebApi.SignalR.Services;
public class SignalRNotificationTransportService : INotificationTransportService
{
+ private readonly NotificationBackgroundWorker backgroundWorker;
private readonly ConnectionManagerService connectionManagerService;
private readonly IHubContext notificationHubContext;
- private readonly INotificationRepository notificationRepository;
- private readonly SemaphoreSlim semaphoreSlim = new (1, 1);
- public SignalRNotificationTransportService(ConnectionManagerService connectionManagerService,
- IHubContext notificationHubContext,
- INotificationRepository notificationRepository)
+ public SignalRNotificationTransportService(NotificationBackgroundWorker backgroundWorker,
+ ConnectionManagerService connectionManagerService,
+ IHubContext notificationHubContext)
{
+ this.backgroundWorker = backgroundWorker;
this.connectionManagerService = connectionManagerService;
this.notificationHubContext = notificationHubContext;
- this.notificationRepository = notificationRepository;
}
public int IdTransportType => 0;
- public async Task SendAsync(NotificationDto notification,
+ public Task SendAsync(NotificationDto notification,
CancellationToken cancellationToken)
{
- const string method = "receiveNotifications";
+ var workId = notification.Id.ToString();
- var connectionId = connectionManagerService.GetConnectionIdByUserId(notification.IdUser);
-
- if (!string.IsNullOrWhiteSpace(connectionId))
+ if (!backgroundWorker.Contains(workId))
{
- notification.SentDate = DateTime.UtcNow;
-
- await notificationHubContext.Clients.Client(connectionId)
- .SendAsync(method,
- notification,
- cancellationToken);
+ var connectionId = connectionManagerService.GetConnectionIdByUserId(notification.IdUser);
- await semaphoreSlim.WaitAsync(cancellationToken);
-
- await notificationRepository.UpdateAsync(notification, cancellationToken);
-
- semaphoreSlim.Release();
+ if (!string.IsNullOrWhiteSpace(connectionId))
+ {
+ var workAction = MakeSignalRSendWorkAction(notification, connectionId);
+ var work = new WorkBase(workId, workAction);
+ backgroundWorker.Push(work);
+ }
}
+
+ return Task.CompletedTask;
}
public Task SendRangeAsync(IEnumerable notifications,
@@ -60,4 +57,24 @@ public class SignalRNotificationTransportService : INotificationTransportService
return Task.WhenAll(tasks);
}
+
+ private Func MakeSignalRSendWorkAction(NotificationDto notification,
+ string connectionId)
+ {
+ const string method = "receiveNotifications";
+
+ return async (_, serviceProvider, cancellationToken) =>
+ {
+ notification.SentDate = DateTime.UtcNow;
+
+ await notificationHubContext.Clients.Client(connectionId)
+ .SendAsync(method,
+ notification,
+ cancellationToken);
+
+ var notificationRepository = serviceProvider.GetRequiredService();
+
+ await notificationRepository.UpdateAsync(notification, cancellationToken);
+ };
+ }
}
\ No newline at end of file