From 99dfbfbb986f98e4e57595a75acf344a5a2938c7 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Tue, 25 Apr 2023 00:03:57 +0000 Subject: [PATCH] case 4491 --- dist/latest-version.json | 2 +- .../GlobalBizSettingsController.cs | 12 +- .../AyaNova/generator/CoreJobVersionCheck.cs | 107 ++++++++++++++++++ .../util/ServerGlobalOpsSettingsCache.cs | 12 ++ 4 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 server/AyaNova/generator/CoreJobVersionCheck.cs diff --git a/dist/latest-version.json b/dist/latest-version.json index 984edbdc..16175473 100644 --- a/dist/latest-version.json +++ b/dist/latest-version.json @@ -1,4 +1,4 @@ { - "version":"8.0.44", + "latestversion":"8.0.44", "changelogurl":"https://ayanova.com/docs/changelog/#ayanova-8042-2023-04-06" } \ No newline at end of file diff --git a/server/AyaNova/Controllers/GlobalBizSettingsController.cs b/server/AyaNova/Controllers/GlobalBizSettingsController.cs index ea251448..3b94835c 100644 --- a/server/AyaNova/Controllers/GlobalBizSettingsController.cs +++ b/server/AyaNova/Controllers/GlobalBizSettingsController.cs @@ -86,7 +86,7 @@ namespace AyaNova.Api.Controllers if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); - var o = await biz.PutAsync(updatedObject); + var o = await biz.PutAsync(updatedObject); if (o == null) return StatusCode(409, new ApiErrorResponse(biz.Errors)); return Ok(ApiOkResponse.Response(new { Concurrency = o.Concurrency })); @@ -109,7 +109,7 @@ namespace AyaNova.Api.Controllers return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); } - bool IsSubscriptionBuild = false; + bool IsSubscriptionBuild = false; #if (SUBSCRIPTION_BUILD) IsSubscriptionBuild=true; @@ -137,8 +137,12 @@ namespace AyaNova.Api.Controllers LicenseStatus = AyaNova.Core.License.ActiveKey.Status, MaintenanceExpired = AyaNova.Core.License.ActiveKey.MaintenanceExpired, ServerDbId = AyaNova.Core.License.ServerDbId, - Company = AyaNova.Core.License.ActiveKey.RegisteredTo, - SBuild = IsSubscriptionBuild + Company = AyaNova.Core.License.ActiveKey.RegisteredTo, + SBuild = IsSubscriptionBuild, + //used to drive UI in case of out of date release message to be shown to staff users non subscription only + ShowUpdateAvailable = (Util.AyaNovaVersion.VersionString != AyaNova.Util.ServerGlobalOpsSettingsCache.LATEST_VERSION && !IsSubscriptionBuild), + LatestVersion = AyaNova.Util.ServerGlobalOpsSettingsCache.LATEST_VERSION, + ChangeLogUrl = AyaNova.Util.ServerGlobalOpsSettingsCache.CHANGE_LOG_URL // , // TestTSDaysWMS=new TimeSpan(22,10,15,22,33), diff --git a/server/AyaNova/generator/CoreJobVersionCheck.cs b/server/AyaNova/generator/CoreJobVersionCheck.cs new file mode 100644 index 00000000..3c9b9d51 --- /dev/null +++ b/server/AyaNova/generator/CoreJobVersionCheck.cs @@ -0,0 +1,107 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using AyaNova.Models; +using AyaNova.Util; + +namespace AyaNova.Biz +{ + + + /// + /// called by Generator to check new releases automatically + /// + /// + internal static class CoreJobVersionCheck + { + private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobVersionCheck"); + private static DateTime _lastCheck = DateTime.MinValue; + +#if (DEBUG) + private static TimeSpan FAST_TRACK = new TimeSpan(0, 1, 0); + private static TimeSpan SLOW_TRACK = new TimeSpan(0, 5, 0); +#else +#if (SUBSCRIPTION_BUILD) + //subscription servers need to check more frequently because the month to month rentals could be dodgy when 24 hours + //also it's all in-network so there is no downside or performance hit for this + private static TimeSpan FAST_TRACK = new TimeSpan(0, 30, 0); + private static TimeSpan SLOW_TRACK = new TimeSpan(0, 30, 0); +#else + private static TimeSpan FAST_TRACK = new TimeSpan(0, 30, 0); + private static TimeSpan SLOW_TRACK = new TimeSpan(24, 0, 0); +#endif +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + // DoWork + // + public static async Task DoWorkAsync() + { + log.LogTrace("Job starting"); + var tsSinceLastCheck = DateTime.UtcNow - _lastCheck; + //which track are we on? + /* + FAST TRACK=30 minutes + SLOW TRACK= 24 hours + NONE = 0,//fast track (no license) + ActiveTrial = 1,//fast track (because they may be testing a migration and running out of time and don't want to cancel it) + ExpiredTrial = 2,//fast track + ActivePurchased = 3,//slow track + ExpiredPurchased = 4,//fast track + Revoked = 5//slow track + */ + TimeSpan tsCheckFrequency; + switch (AyaNova.Core.License.ActiveKey.Status) + { + case AyaNova.Core.License.AyaNovaLicenseKey.LicenseStatus.NONE: + case AyaNova.Core.License.AyaNovaLicenseKey.LicenseStatus.ActiveTrial: + case AyaNova.Core.License.AyaNovaLicenseKey.LicenseStatus.ExpiredTrial: + case AyaNova.Core.License.AyaNovaLicenseKey.LicenseStatus.ExpiredPurchased: + tsCheckFrequency = FAST_TRACK; + break; + default: + tsCheckFrequency = SLOW_TRACK; + break; + } + log.LogTrace($"Check frequency{tsCheckFrequency}"); + if (tsSinceLastCheck < tsCheckFrequency) + { + log.LogTrace($"Not yet"); + return; + } + + using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) + { + try//allow exception to bubble up but using try block to ensure the lastcheck is set properly regardless so this doesn't spin out of control + { + var ServerState = (AyaNova.Api.ControllerHelpers.ApiServerState)ServiceProviderProvider.Provider.GetService(typeof(AyaNova.Api.ControllerHelpers.ApiServerState)); + + var ret = await AyaNova.Core.License.FetchKeyAsync(ServerState, ct, log, true); + //When this was enabled never saw a failed fetch, trying again without it + //#if (DEBUG) + // log.LogInformation("TEMP TEST LOG: CoreJobVersionCheck - result is: " + ret); + //#endif + //most often the result will be "notfound" but in future might be other results + if (ret == "ok") + { + //Eventlog + await EventLogProcessor.LogEventToDatabaseAsync(new Event(1, 0, AyaType.License, AyaEvent.LicenseFetch, "FromCoreJob"), ct); + } + if (ret != "notfound") + { + //I'm thinking do not log internally failed except as debug event as this would fill up log file + //instead if they have a license issue they can do manual fetch and then that will log so they can see error + //(also it will return an error to the client) + log.LogDebug($"FetchLicense - failed: {ret}"); + } + } + finally + { + _lastCheck = DateTime.UtcNow; + } + } + } + ///////////////////////////////////////////////////////////////////// + }//eoc +}//eons + diff --git a/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs b/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs index b7aeb2fe..8edab273 100644 --- a/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs +++ b/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs @@ -22,11 +22,23 @@ namespace AyaNova.Util internal static GlobalOpsBackupSettings Backup { get; set; } internal static GlobalOpsNotificationSettings Notify { get; set; } internal static DateTime NextBackup { get; set; } + + + //VERSION CHECKING + //set by CoreJobVersionCheck once daily and kept here statically while server is up + internal static string LATEST_VERSION { get; set; } + internal static string CHANGE_LOG_URL { get; set; } + + /// /// Populate and / or create the settings /// internal static void Initialize(AyContext ct = null) { + //set to current servers boot version so as to not trigger messaging at client on login until job has had a chance to set + LATEST_VERSION = Util.AyaNovaVersion.VersionString; + CHANGE_LOG_URL = "https://ayanova.com/docs/changelog/";//just something to default to, should never come up as it's not a different version at this point + //fetch or create as not provided (meaning this was called from Startup.cs) Backup = ct.GlobalOpsBackupSettings.FirstOrDefault(z => z.Id == 1); if (Backup == null)