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
)
);
}
}
}
}