This commit is contained in:
2020-07-22 23:02:30 +00:00
parent 9dda0623ba
commit 1223fd2f28
7 changed files with 83 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
@@ -37,6 +38,7 @@ namespace AyaNova.Biz
//temporary list to hold translations as required during delivery
private static Dictionary<long, List<NameIdItem>> _transCache = new Dictionary<long, List<NameIdItem>>();
private static Dictionary<long, long> _UserTranslationIdCache = new Dictionary<long, long>();
////////////////////////////////////////////////////////////////////////////////////////////////
// DoSweep
@@ -100,10 +102,22 @@ namespace AyaNova.Biz
//todo: create message here if not already set?
//todo: generate and attach report here?
//All items have an event date, for non time delayed events it's just the moment it was created
//which will predate this moment now if it's pre-existing
var events = await ct.NotifyEvent.Include(z => z.NotifySubscription).ToListAsync();
log.LogTrace($"Found {events.Count} NotifyEvents to examine for potential delivery");
//cache translations
//Get all subscription unique userId's that aren't inapp deliveries
var usersNeedingTranslations = events.Where(z => z.NotifySubscription.DeliveryMethod != NotifyDeliveryMethod.App).Select(z => z.NotifySubscription.UserId).ToList().Distinct();
foreach (long userid in usersNeedingTranslations)
{
long transId = (await ct.UserOptions.SingleAsync(z => z.UserId == userid)).TranslationId;
_UserTranslationIdCache.Add(userid, transId);
await CacheNotifyEventTypeTranslations(transId);
}
//iterate and deliver
foreach (var notifyevent in events)
{
@@ -149,18 +163,29 @@ namespace AyaNova.Biz
finally
{
log.LogTrace("Notify is done setting to not running state and tagging lastRun timestamp");
_UserTranslationIdCache.Clear();
_transCache.Clear();
lastRun = DateTime.UtcNow;
NotifyIsRunning = false;
}
}
//cache any translations required for email notification
private static async Task CacheNotifyEventTypeTranslations(long translationId){
if(_transCache.ContainsKey(translationId)){
//cache any translations required for email notification
private static async Task CacheNotifyEventTypeTranslations(long translationId)
{
if (_transCache.ContainsKey(translationId))
{
return;
}
_transCache.Add(translationId,AyaNova.Api.Controllers.EnumListController.GetEnumList("NotifyEventType",translationId));
_transCache.Add(translationId, await AyaNova.Api.Controllers.EnumListController.GetEnumList("NotifyEventType", translationId));
}
//Used for subject of email and message deliveries
private static string GetTranslatedNotifyEventName(NotifyEventType net, long translationId)
{
return _transCache[translationId][(int)net].Name;
}
private static async Task DeliverInApp(NotifyEvent ne, AyContext ct)
@@ -171,29 +196,44 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync();
}
private static async Task DeliverSMTP(NotifyEvent ne, string toAddress, AyContext ct)
private static async Task DeliverSMTP(NotifyEvent ne, AyContext ct)
{
log.LogTrace($"DeliverSMTP deliving notify event: {ne}");
if (string.IsNullOrWhiteSpace(ne.NotifySubscription.DeliveryAddress))
{
await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: no email address is set in subscription to deliver email notification for this event:{ne}", null, ne.UserId);
var subject = $"Notification: {ne.EventType.ToString()}";
}
var transid = _UserTranslationIdCache[ne.NotifySubscription.UserId];
var subject = $"AY:{GetTranslatedNotifyEventName(ne.EventType, transid)}:{ne.Name}";
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(toAddress, subject, "This is a test to confirm notification system is working", ServerGlobalOpsSettingsCache.Notify);
return "ok";
var body = "";
if (ne.ObjectId != 0)
{
body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId) + "\n";
}
body += ne.Message;
await m.SendEmailAsync(ne.NotifySubscription.DeliveryAddress, subject, body, ServerGlobalOpsSettingsCache.Notify);
}
catch (Exception ex)
{
return ExceptionUtil.ExtractAllExceptionMessages(ex);
await NotifyEventProcessor.AddOpsProblemEvent("SMTP Notification failed", ex);
await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: an error prevented delivering the following notification via email. System operator users have been notified:{ne}", null, ne.UserId);
}
finally
{
//remove event no matter what
ct.NotifyEvent.Remove(ne);
await ct.SaveChangesAsync();
}
//todo: //Open question: what to do with failed deliveries?
//we dont' want them piling up but we don't want to just dump them do we?
//it should be only mail ones that fail, not app ones, there's no way for an app delivery to fail as it's just put in a table
//### PLAN if it's an smtp delivery that fails and it's to someone who can be delivered in app then it should send an inapp notification of
//delivery failure and still delete the smtp delivery
//If it's not possible to notify the person via in app of the failed smtp then perhaps it notifies OPS personnel and biz admin personnel
}
//Called from ops notification settings to test smtp setup by delivering to address of choosing
@@ -218,6 +258,20 @@ namespace AyaNova.Biz
}
//Open object url
//### NOTE: If this is required anywhere else, move it to a central BizUtils class in Biz folder callable from here and there
private static string OpenObjectUrlBuilder(AyaType otype, long id)
{
var ServerUrl = ServerGlobalOpsSettingsCache.Notify.AyaNovaServerURL;
if (string.IsNullOrWhiteSpace(ServerUrl))
{
NotifyEventProcessor.AddOpsProblemEvent("Notification system: The OPS Notification setting is empty for AyaNova Server URL. This prevents Notification system from linking events to openable objects.").Wait();
return "OPS ERROR NO SERVER URL CONFIGURED";
}
ServerUrl = ServerUrl.Trim().TrimEnd('/');
return $"{ServerUrl}?type={otype}&id={id}";
}
/////////////////////////////////////////////////////////////////////
}//eoc