using System; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using AyaNova.Models; namespace AyaNova.Biz { /// /// Notification processor /// /// internal static class CoreJobNotify { private static bool NotifyIsRunning = false; private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobNotify"); private static DateTime lastRun = DateTime.MinValue; private static TimeSpan DELETE_AFTER_AGE = new TimeSpan(90, 0, 0, 0); private static TimeSpan RUN_EVERY_INTERVAL = new TimeSpan(0, 2, 0);//once every 2 minutes minimum 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 //////////////////////////////////////////////////////////////////////////////////////////////// // DoSweep // public static async Task DoWorkAsync() { log.LogTrace("Checking if Notify should run"); if (NotifyIsRunning) { log.LogTrace("Notify is running already exiting this cycle"); return; } //This will get triggered roughly every minute, but we don't want to deliver that frequently if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL) { log.LogTrace($"Notify ran less than {RUN_EVERY_INTERVAL}, exiting this cycle"); return; } try { NotifyIsRunning = true; log.LogTrace("Notify set to RUNNING state and starting now"); //NotifyHealthCheck processing //Note this deliberately uses LOCAL time in effort to deliver the health check first thing in the morning for workers //However if server is on UTC already then that's what is used, there is no adjustment DateTime dtNowLocal = DateTime.Now; if (dtNowLocal - lastNotifyHealthCheckSentLocal > TS_24_HOURS) { //are we in the 7th to 9th hour? if (dtNowLocal.Hour > 6 && dtNowLocal.Hour < 10) { log.LogTrace("Notify health check submitted to subscribers"); await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.NotifyHealthCheck, "OK"); lastNotifyHealthCheckSentLocal = dtNowLocal; } } using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) { //select all jobs with no deliver date or deliver date no longer in future //IMPLEMENTATION NOTES: This code // finds the events in NotifyEvent // check subscription to determine if the age related ones are deliverable now // check subscriptions for each delivery type, i.e. there might be both smtp and inapp separately for the same event so it needs to know that and deliver accordingly // remove the notify event after it's processed //Older notes: //### 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 //NEW NOTIFICATION SUBSCRIPTION EVENT TYPE: //OPERATIONS_PROBLEMS - backup, notifications, out of memory, what have you, anyone can subscribe to it regardless of rights //this is just to let people know there is a problem //todo: create message here if not already set? //todo: generate and attach report here? } } catch (Exception ex) { } finally { log.LogTrace("Notify is done setting to not running state and tagging lastRun timestamp"); lastRun = DateTime.UtcNow; NotifyIsRunning = false; } } ///////////////////////////////////////////////////////////////////// }//eoc }//eons