This commit is contained in:
@@ -190,11 +190,15 @@ namespace AyaNova.Biz
|
|||||||
log.LogCritical(msg);
|
log.LogCritical(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO: NOTIFICATIONS
|
|
||||||
//await CoreJobNotify.DoWorkAsync();
|
|
||||||
|
|
||||||
//BACKUP
|
//BACKUP
|
||||||
await CoreJobBackup.DoWorkAsync();
|
await CoreJobBackup.DoWorkAsync();
|
||||||
|
|
||||||
|
//NOTIFICATIONS
|
||||||
|
await CoreJobNotify.DoWorkAsync();
|
||||||
|
await CoreNotificationSweeper.DoWorkAsync();
|
||||||
|
|
||||||
//JOB SWEEPER
|
//JOB SWEEPER
|
||||||
await CoreJobSweeper.DoWorkAsync();
|
await CoreJobSweeper.DoWorkAsync();
|
||||||
|
|
||||||
|
|||||||
82
server/AyaNova/generator/CoreJobNotify.cs
Normal file
82
server/AyaNova/generator/CoreJobNotify.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using AyaNova.Models;
|
||||||
|
|
||||||
|
namespace AyaNova.Biz
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notification processor
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
|
||||||
|
using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
|
||||||
|
{
|
||||||
|
//select all jobs with no deliver date or deliver date no longer in future
|
||||||
|
//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
|
||||||
|
//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
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -8,7 +7,6 @@ using AyaNova.Models;
|
|||||||
namespace AyaNova.Biz
|
namespace AyaNova.Biz
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clean up notification system, keep items down to 90 days
|
/// Clean up notification system, keep items down to 90 days
|
||||||
///
|
///
|
||||||
@@ -52,82 +50,6 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static async Task sweepAsync(AyContext ct, DateTime dtDeleteCutoff, JobStatus jobStatus)
|
|
||||||
{
|
|
||||||
//Get the deleteable succeeded jobs list
|
|
||||||
var jobs = await ct.OpsJob
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(z => z.Created < dtDeleteCutoff && z.JobStatus == jobStatus)
|
|
||||||
.OrderBy(z => z.Created)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
log.LogTrace($"SweepAsync processing: cutoff={dtDeleteCutoff.ToString()}, for {jobs.Count.ToString()} jobs of status {jobStatus.ToString()}");
|
|
||||||
|
|
||||||
foreach (OpsJob j in jobs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
await JobsBiz.RemoveJobAndLogsAsync(j.GId);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
log.LogError(ex, "sweepAsync exception calling JobsBiz.RemoveJobAndLogsAsync");
|
|
||||||
//for now just throw it but this needs to be removed when logging added and better handling
|
|
||||||
throw (ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Kill jobs that have been stuck in "running" state for too long
|
|
||||||
/// </summary>
|
|
||||||
private static async Task killStuckJobsAsync(AyContext ct, DateTime dtRunningDeadline)
|
|
||||||
{
|
|
||||||
//Get the deleteable succeeded jobs list
|
|
||||||
var jobs = await ct.OpsJob
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(z => z.Created < dtRunningDeadline && z.JobStatus == JobStatus.Running)
|
|
||||||
.OrderBy(z => z.Created)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
log.LogTrace($"killStuckJobsAsync processing: cutoff={dtRunningDeadline.ToString()}, for {jobs.Count.ToString()} jobs of status {JobStatus.Running.ToString()}");
|
|
||||||
|
|
||||||
foreach (OpsJob j in jobs)
|
|
||||||
{
|
|
||||||
//OPSMETRIC
|
|
||||||
await JobsBiz.LogJobAsync(j.GId, "Job took too long to run - setting to failed");
|
|
||||||
log.LogError($"Job found job stuck in running status and set to failed: deadline={dtRunningDeadline.ToString()}, jobId={j.GId.ToString()}, jobname={j.Name}, jobtype={j.JobType.ToString()}, jobObjectType={j.ObjectType.ToString()}, jobObjectId={j.ObjectId.ToString()}");
|
|
||||||
await JobsBiz.UpdateJobStatusAsync(j.GId, JobStatus.Failed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static async Task SweepInternalJobsLogsAsync(AyContext ct, DateTime dtDeleteCutoff)
|
|
||||||
{
|
|
||||||
//Get the deleteable list (this is for reporting, could easily just do it in one go)
|
|
||||||
var logs = await ct.OpsJobLog
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(z => z.Created < dtDeleteCutoff)
|
|
||||||
.OrderBy(z => z.Created)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
log.LogTrace($"SweepInternalJobsLogsAsync processing: cutoff={dtDeleteCutoff.ToString()}, for {logs.Count.ToString()} log entries");
|
|
||||||
|
|
||||||
foreach (OpsJobLog l in logs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from aopsjoblog where gid = {l.GId}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
log.LogError(ex, "SweepInternalJobsLogsAsync exception removed old log entries");
|
|
||||||
throw (ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ namespace AyaNova.Models
|
|||||||
public long SubscriptionId { get; set; }
|
public long SubscriptionId { get; set; }
|
||||||
public long? IdValue { get; set; }
|
public long? IdValue { get; set; }
|
||||||
public decimal? DecValue { get; set; }
|
public decimal? DecValue { get; set; }
|
||||||
public DateTime? EventDate { get; set; }
|
public DateTime? EventDate { get; set; }//date of the event actually occuring, e.g. WarrantyExpiry date. Duped with delivery date as source of truth in case edit to advance setting in subscription changes delivery date
|
||||||
|
public DateTime? DeliverDate { get; set; }//date user wants the event notification delivered, usually same as event date but could be set earlier if Advance setting in effect. This is the date consulted for delivery only.
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -688,7 +688,7 @@ $BODY$;
|
|||||||
"idvalue bigint, decvalue decimal(19,4), agevalue interval, deliverymethod integer not null, deliveryaddress text, attachreportid bigint, intags varchar(255) ARRAY, outtags varchar(255) ARRAY)");
|
"idvalue bigint, decvalue decimal(19,4), agevalue interval, deliverymethod integer not null, deliveryaddress text, attachreportid bigint, intags varchar(255) ARRAY, outtags varchar(255) ARRAY)");
|
||||||
|
|
||||||
await ExecQueryAsync("CREATE TABLE anotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created timestamp not null, " +
|
await ExecQueryAsync("CREATE TABLE anotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created timestamp not null, " +
|
||||||
"ayatype integer, objectid bigint, eventtype integer not null, subscriptionid bigint not null, idvalue bigint, decvalue decimal(19,4), eventdate timestamp, message text)");
|
"ayatype integer, objectid bigint, eventtype integer not null, subscriptionid bigint not null, idvalue bigint, decvalue decimal(19,4), eventdate timestamp, deliverdate timestamp, message text)");
|
||||||
|
|
||||||
await ExecQueryAsync("CREATE TABLE anotification (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, userid bigint not null, created timestamp not null, ayatype integer, objectid bigint, eventtype integer not null, " +
|
await ExecQueryAsync("CREATE TABLE anotification (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, userid bigint not null, created timestamp not null, ayatype integer, objectid bigint, eventtype integer not null, " +
|
||||||
"subscriptionid bigint not null, message text, fetched bool not null)");
|
"subscriptionid bigint not null, message text, fetched bool not null)");
|
||||||
|
|||||||
Reference in New Issue
Block a user