using System; using System.Linq; using System.Threading.Tasks; using Abp.BackgroundJobs; using Abp.Collections.Extensions; using Abp.Dependency; using Abp.Domain.Entities; using Abp.Domain.Uow; using Abp.Extensions; using Abp.Json; using Abp.Runtime.Session; namespace Abp.Notifications { /// /// Implements . /// public class NotificationPublisher : AbpServiceBase, INotificationPublisher, ITransientDependency { public const int MaxUserCountToDirectlyDistributeANotification = 5; /// /// Indicates all tenants. /// public static int[] AllTenants { get { return new[] { NotificationInfo.AllTenantIds.To() }; } } /// /// Reference to ABP session. /// public IAbpSession AbpSession { get; set; } private readonly INotificationStore _store; private readonly IBackgroundJobManager _backgroundJobManager; private readonly INotificationConfiguration _notificationConfiguration; private readonly IGuidGenerator _guidGenerator; private readonly IIocResolver _iocResolver; /// /// Initializes a new instance of the class. /// public NotificationPublisher( INotificationStore store, IBackgroundJobManager backgroundJobManager, INotificationConfiguration notificationConfiguration, IGuidGenerator guidGenerator, IIocResolver iocResolver) { _store = store; _backgroundJobManager = backgroundJobManager; _notificationConfiguration = notificationConfiguration; _guidGenerator = guidGenerator; _iocResolver = iocResolver; AbpSession = NullAbpSession.Instance; } //Create EntityIdentifier includes entityType and entityId. [UnitOfWork] public virtual async Task PublishAsync( string notificationName, NotificationData data = null, EntityIdentifier entityIdentifier = null, NotificationSeverity severity = NotificationSeverity.Info, UserIdentifier[] userIds = null, UserIdentifier[] excludedUserIds = null, int?[] tenantIds = null) { if (notificationName.IsNullOrEmpty()) { throw new ArgumentException("NotificationName can not be null or whitespace!", "notificationName"); } if (!tenantIds.IsNullOrEmpty() && !userIds.IsNullOrEmpty()) { throw new ArgumentException("tenantIds can be set only if userIds is not set!", "tenantIds"); } if (tenantIds.IsNullOrEmpty() && userIds.IsNullOrEmpty()) { tenantIds = new[] { AbpSession.TenantId }; } var notificationInfo = new NotificationInfo(_guidGenerator.Create()) { NotificationName = notificationName, EntityTypeName = entityIdentifier == null ? null : entityIdentifier.Type.FullName, EntityTypeAssemblyQualifiedName = entityIdentifier == null ? null : entityIdentifier.Type.AssemblyQualifiedName, EntityId = entityIdentifier == null ? null : entityIdentifier.Id.ToJsonString(), Severity = severity, UserIds = userIds.IsNullOrEmpty() ? null : userIds.Select(uid => uid.ToUserIdentifierString()).JoinAsString(","), ExcludedUserIds = excludedUserIds.IsNullOrEmpty() ? null : excludedUserIds.Select(uid => uid.ToUserIdentifierString()).JoinAsString(","), TenantIds = tenantIds.IsNullOrEmpty() ? null : tenantIds.JoinAsString(","), Data = data == null ? null : data.ToJsonString(), DataTypeName = data == null ? null : data.GetType().AssemblyQualifiedName }; await _store.InsertNotificationAsync(notificationInfo); await CurrentUnitOfWork.SaveChangesAsync(); //To get Id of the notification if (userIds != null && userIds.Length <= MaxUserCountToDirectlyDistributeANotification) { //We can directly distribute the notification since there are not much receivers foreach (var notificationDistributorType in _notificationConfiguration.Distributers) { using (var notificationDistributer = _iocResolver.ResolveAsDisposable(notificationDistributorType)) { await notificationDistributer.Object.DistributeAsync(notificationInfo.Id); } } } else { //We enqueue a background job since distributing may get a long time await _backgroundJobManager.EnqueueAsync( new NotificationDistributionJobArgs( notificationInfo.Id ) ); } } } }