case 4654 - every direct notification message to a user is delivered

Direct messages are general notifications with no object, so the 12-hour
repeat check in CoreJobNotify (case 3917, keyed on subscription and object)
dropped every message to a user after the first. For general notifications
the check now applies only to the job's own delivery error messages
(DELIVERY_ERROR_NAME). Changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 20:27:34 -07:00
parent a53a4b6ef7
commit ed641c4985
3 changed files with 28 additions and 23 deletions

View File

@@ -19,6 +19,8 @@ namespace AyaNova.Biz
{
private static bool NotifyIsRunning = false;
private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobNotify");
//case 4654: name of this job's own delivery error messages to a user, the only general notifications limited to one per 12 hours
private const string DELIVERY_ERROR_NAME = "Error";
private static DateTime lastRun = DateTime.MinValue;
private static DateTime lastNotifyHealthCheckSentLocal = DateTime.MinValue;
private static TimeSpan TS_24_HOURS = new TimeSpan(24, 0, 0);//used to ensure daily ops happen no more than that
@@ -103,29 +105,31 @@ namespace AyaNova.Biz
//Don't check for ones that are regular object based
//which can and will properly send out the same notification regularly
//(e.g. workorder status change into out of and back into the same staus)
switch (notifyevent.EventType)
//case 4654: a general notification is either a message a user sent (never repetitive by itself, and with no
//object, so the check below took every message to a user after the first within 12 hours as a repeat) or
//this job's own delivery error message (which can repeat); only the latter is checked
var checkRepeat = notifyevent.EventType switch
{
case NotifyEventType.BackupStatus:
case NotifyEventType.GeneralNotification:
case NotifyEventType.ServerOperationsProblem:
case NotifyEventType.PMGenerationFailed:
{
//check if we've just delivered this same thing in the last 12 hours which is the hard limit (case 3917)
var twelvehoursago = DateTime.UtcNow - new TimeSpan(12, 0, 0);
NotifyEventType.GeneralNotification => notifyevent.Name == DELIVERY_ERROR_NAME,
NotifyEventType.BackupStatus or NotifyEventType.ServerOperationsProblem or NotifyEventType.PMGenerationFailed => true,
_ => false
};
if (checkRepeat)
{
//check if we've just delivered this same thing in the last 12 hours which is the hard limit (case 3917)
var twelvehoursago = DateTime.UtcNow - new TimeSpan(12, 0, 0);
//look for same delivery less than last12hours ago
if (await ct.NotifyDeliveryLog.AnyAsync(z => z.Processed > twelvehoursago && z.NotifySubscriptionId == notifyevent.NotifySubscriptionId && z.ObjectId == notifyevent.ObjectId))
{
log.LogDebug($"Notification event will not be delivered: repetitive (server system event type and delivered at least once in the last 12 hours to this subscriber: {notifyevent})");
ct.NotifyEvent.Remove(notifyevent);
await ct.SaveChangesAsync();
//look for same delivery less than last12hours ago
if (await ct.NotifyDeliveryLog.AnyAsync(z => z.Processed > twelvehoursago && z.NotifySubscriptionId == notifyevent.NotifySubscriptionId && z.ObjectId == notifyevent.ObjectId))
{
log.LogDebug($"Notification event will not be delivered: repetitive (server system event type and delivered at least once in the last 12 hours to this subscriber: {notifyevent})");
ct.NotifyEvent.Remove(notifyevent);
await ct.SaveChangesAsync();
#if (DEBUG)
log.LogInformation($"DeliverInApp event will not be delivered: repetitive (server system event type and delivered at least once in the last 12 hours to this subscriber: {notifyevent})");
log.LogInformation($"DeliverInApp event will not be delivered: repetitive (server system event type and delivered at least once in the last 12 hours to this subscriber: {notifyevent})");
#endif
continue;
}
}
break;
continue;
}
}
//Do the delivery, it's kosher
@@ -201,7 +205,7 @@ namespace AyaNova.Biz
log.LogDebug($"DeliverSMTP delivering notify event: {ne}");
if (string.IsNullOrWhiteSpace(deliveryAddress))
{
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"No email address is set in subscription to deliver email notification. This event will be removed from the delivery queue as undeliverable: {ne}", "Error", null, ne.UserId);
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"No email address is set in subscription to deliver email notification. This event will be removed from the delivery queue as undeliverable: {ne}", DELIVERY_ERROR_NAME, null, ne.UserId);
DeliveryLogItem.Fail = true;
DeliveryLogItem.Error = $"No email address provided for smtp delivery; event: {ne}";
}
@@ -301,7 +305,7 @@ namespace AyaNova.Biz
if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive)
{
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"Email notifications are set to OFF at server, unable to send email notification for this event:{ne}", "Error", null, ne.UserId);
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"Email notifications are set to OFF at server, unable to send email notification for this event:{ne}", DELIVERY_ERROR_NAME, null, ne.UserId);
log.LogInformation($"** WARNING: SMTP notification is currently set to Active=False; unable to deliver email notification, re-routed to in-app notification instead [UserId={ne.UserId}, Notify subscription={ne.NotifySubscriptionId}]. Change this setting or have users remove email delivery notifications if this is permanent **");
DeliveryLogItem.Fail = true;
DeliveryLogItem.Error = $"Email notifications are set to OFF at server, unable to send email notification for this event: {ne}";
@@ -314,7 +318,7 @@ namespace AyaNova.Biz
catch (Exception ex)
{
await NotifyEventHelper.AddOpsProblemEvent("SMTP Notification failed", ex);
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"An error prevented delivering the following notification via email. System operator users have been notified:{ne}", "Error", null, ne.UserId);
await NotifyEventHelper.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"An error prevented delivering the following notification via email. System operator users have been notified:{ne}", DELIVERY_ERROR_NAME, null, ne.UserId);
DeliveryLogItem.Fail = true;
DeliveryLogItem.Error = $"SMTP Notification failed to deliver for this event: {ne}, message: {ex.Message}";
log.LogDebug(ex, $"DeliverSMTP Failure delivering notify event: {ne}");