diff --git a/devdocs/todo.txt b/devdocs/todo.txt index a101bab7..45975974 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -1090,6 +1090,9 @@ https://www.ayanova.com/download/next/ayanova-linux-x64-server.zip https://www.ayanova.com/download/next/ayanova-windows-x64-lan-setup.exe Current v8 docs home: https://www.ayanova.com/docs/next -BUILD 8.0.0 CHANGES OF NOTE +BUILD 8.0.0 rc2 CHANGES OF NOTE + +Added integration back end feature for integration of external applications with AyaNova 8 +Added front end administrative UI for viewing and controlling integrated applications and their logs diff --git a/server/AyaNova/biz/JobsBiz.cs b/server/AyaNova/biz/JobsBiz.cs index 9836a739..0073e9a3 100644 --- a/server/AyaNova/biz/JobsBiz.cs +++ b/server/AyaNova/biz/JobsBiz.cs @@ -211,7 +211,7 @@ namespace AyaNova.Biz //NOTIFICATIONS await CoreJobNotify.DoWorkAsync(); if (!KeepOnWorking()) return; - + await CoreNotificationSweeper.DoWorkAsync(); if (!KeepOnWorking()) return; @@ -239,6 +239,11 @@ namespace AyaNova.Biz //CUSTOMER NOTIFICATIONS TaskUtil.Forget(Task.Run(() => CoreJobCustomerNotify.DoWorkAsync()));//must fire and forget as it will call a report render job. In fact probably all of these can be fire and forget + //INTEGRATION LOG SWEEP + await CoreIntegrationLogSweeper.DoWorkAsync(); + if (!KeepOnWorking()) return; + + log.LogTrace("Processing exclusive dynamic jobs"); //BIZOBJECT DYNAMIC JOBS diff --git a/server/AyaNova/generator/CoreIntegrationLogSweeper.cs b/server/AyaNova/generator/CoreIntegrationLogSweeper.cs new file mode 100644 index 00000000..cf51044d --- /dev/null +++ b/server/AyaNova/generator/CoreIntegrationLogSweeper.cs @@ -0,0 +1,48 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using AyaNova.Models; + +namespace AyaNova.Biz +{ + + /// + /// Clear out old integration log data + /// + internal static class CoreIntegrationLogSweeper + { + private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreIntegrationLogSweeper"); + private static DateTime lastSweep = DateTime.MinValue; + private static TimeSpan DELETE_AFTER_AGE = new TimeSpan(90, 0, 0, 0);//The same typical 90 days as everything uses + private static TimeSpan SWEEP_EVERY_INTERVAL = new TimeSpan(8, 0, 0);//once every 8 hours, three times a day + + //////////////////////////////////////////////////////////////////////////////////////////////// + // DoSweep + // + public static async Task DoWorkAsync() + { + //This will get triggered roughly every minute, but we don't want to sweep that frequently + if (DateTime.UtcNow - lastSweep < SWEEP_EVERY_INTERVAL) + return; + DateTime dtDeleteCutoff = DateTime.UtcNow - DELETE_AFTER_AGE; + DateTime dtPastEventCutoff = DateTime.UtcNow - SWEEP_EVERY_INTERVAL; + + log.LogDebug("Sweep starting"); + using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) + { + await ct.Database.ExecuteSqlInterpolatedAsync($"delete from aintegrationlog where created < {dtDeleteCutoff}"); + + } + lastSweep = DateTime.UtcNow; + } + + + + ///////////////////////////////////////////////////////////////////// + + }//eoc + + +}//eons + diff --git a/server/AyaNova/models/IntegrationLog.cs b/server/AyaNova/models/IntegrationLog.cs index e8ef67c2..ff0baf51 100644 --- a/server/AyaNova/models/IntegrationLog.cs +++ b/server/AyaNova/models/IntegrationLog.cs @@ -26,3 +26,9 @@ namespace AyaNova.Models } } + +// CREATE TABLE [dbo].[AINTEGRATIONLOG]( +// [ACREATED] [datetime] NOT NULL, +// [ACREATOR] [uniqueidentifier] NOT NULL, +// [AINTEGRATIONID] [uniqueidentifier] NOT NULL, +// [AMESSAGE] [nvarchar](500) NOT NULL \ No newline at end of file diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index f33c8481..a1e43699 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -1326,7 +1326,9 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); await SetSchemaLevelAsync(++currentSchema); } - + //////////////////////////////////////////////// + // rc 2 integration objects for QBI etc + // if (currentSchema < 4) { LogUpdateMessage(log); @@ -1340,7 +1342,12 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); + "atype INTEGER NOT NULL, objectid BIGINT NOT NULL, integrationitemid TEXT NOT NULL, lastsync TIMESTAMPTZ, integrationitemdata TEXT " + ")"); + //INTEGRATIONLOG + await ExecQueryAsync("CREATE TABLE aintegrationlog (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, integrationappid uuid NOT NULL, created TIMESTAMPTZ NOT NULL, statustext TEXT NOT NULL)"); + //Trans keys must come in a subsequent schema update when get to front end UI code + + //UPDATED NAME FETCHER FOR INTEGRATION await ExecQueryAsync(@" CREATE OR REPLACE FUNCTION PUBLIC.AYGETNAME(IN AYOBJECTID BIGINT, IN AYATYPE INTEGER,TRANSLATIONID integer) RETURNS TEXT AS $BODY$ DECLARE