This commit is contained in:
2023-04-26 17:57:50 +00:00
parent 4a502db722
commit 08e9a8a275
4 changed files with 127 additions and 110 deletions

2
.vscode/launch.json vendored
View File

@@ -63,7 +63,7 @@
"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;CommandTimeout=300;", "AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;CommandTimeout=300;",
"AYANOVA_DATA_PATH": "c:\\temp\\ravendata", "AYANOVA_DATA_PATH": "c:\\temp\\ravendata",
"AYANOVA_USE_URLS": "http://*:7575;", "AYANOVA_USE_URLS": "http://*:7575;",
"AYANOVA_PERMANENTLY_ERASE_DATABASE":"true", //"AYANOVA_PERMANENTLY_ERASE_DATABASE":"true",
//"AYANOVA_REMOVE_LICENSE_FROM_DB":"true", //"AYANOVA_REMOVE_LICENSE_FROM_DB":"true",
//"AYANOVA_REPORT_RENDERING_TIMEOUT":"1", //"AYANOVA_REPORT_RENDERING_TIMEOUT":"1",
//"AYANOVA_REPORT_RENDER_API_URL_OVERRIDE": "http://localhost:7575", //"AYANOVA_REPORT_RENDER_API_URL_OVERRIDE": "http://localhost:7575",

View File

@@ -1,4 +1,4 @@
{ {
"latestversion":"8.0.44", "latestversion":"8.0.42",
"changelogurl":"https://ayanova.com/docs/changelog/#ayanova-8042-2023-04-06" "changelogurl":"https://ayanova.com/docs/changelog/#ayanova-8042-2023-04-06"
} }

View File

@@ -295,6 +295,12 @@ namespace AyaNova.Biz
await CoreIntegrationLogSweeper.DoWorkAsync(); await CoreIntegrationLogSweeper.DoWorkAsync();
if (!KeepOnWorking()) return; if (!KeepOnWorking()) return;
#if !SUBSCRIPTION_BUILD
//CHECK IF NEW VERSION AVAILABLE
//this will alert users on login for perpetual server instances
await CoreJobVersionCheck.DoWorkAsync();
#endif
log.LogTrace("Processing exclusive dynamic jobs"); log.LogTrace("Processing exclusive dynamic jobs");
@@ -374,58 +380,61 @@ namespace AyaNova.Biz
/// <returns></returns> /// <returns></returns>
internal static async Task ProcessJobAsync(OpsJob job) internal static async Task ProcessJobAsync(OpsJob job)
{ {
var JobDescription = $"{job.Name} - {job.JobType.ToString()}"; var JobDescription = $"{job.Name} - {job.JobType.ToString()}";
if (job.SubType != JobSubType.NotSet) if (job.SubType != JobSubType.NotSet)
JobDescription += $":{job.SubType}"; JobDescription += $":{job.SubType}";
await LogJobAsync(job.GId, $"LT:ProcessingJob \"{JobDescription}\""); await LogJobAsync(job.GId, $"LT:ProcessingJob \"{JobDescription}\"");
log.LogDebug($"ProcessJobAsync -> Processing job {JobDescription}"); log.LogDebug($"ProcessJobAsync -> Processing job {JobDescription}");
IJobObject o = null; IJobObject o = null;
try{ try
using (AyContext ct = ServiceProviderProvider.DBContext)
{ {
switch (job.JobType) using (AyContext ct = ServiceProviderProvider.DBContext)
{ {
case JobType.Backup: switch (job.JobType)
//This is called when on demand only, normal backups are processed above with normal system jobs {
await CoreJobBackup.DoWorkAsync(true); case JobType.Backup:
await UpdateJobStatusAsync(job.GId, JobStatus.Completed); //This is called when on demand only, normal backups are processed above with normal system jobs
break; await CoreJobBackup.DoWorkAsync(true);
case JobType.TestJob: await UpdateJobStatusAsync(job.GId, JobStatus.Completed);
o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.ServerJob, ct, 1, AuthorizationRoles.BizAdmin); break;
break; case JobType.TestJob:
case JobType.SeedTestData: o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.ServerJob, ct, 1, AuthorizationRoles.BizAdmin);
o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.TrialSeeder, ct, 1, AuthorizationRoles.BizAdmin); break;
break; case JobType.SeedTestData:
case JobType.AttachmentMaintenance: o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.TrialSeeder, ct, 1, AuthorizationRoles.BizAdmin);
o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.FileAttachment, ct, 1, AuthorizationRoles.BizAdmin); break;
break; case JobType.AttachmentMaintenance:
case JobType.BatchCoreObjectOperation: o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.FileAttachment, ct, 1, AuthorizationRoles.BizAdmin);
//batch op, hand off to biz object to deal with break;
//note, convention is that there is an idList in job.jobinfo json if preselected else it's all objects of type case JobType.BatchCoreObjectOperation:
//batch op, hand off to biz object to deal with
//note, convention is that there is an idList in job.jobinfo json if preselected else it's all objects of type
//case 4357 //case 4357
var tempObject=BizObjectFactory.GetBizObject(job.AType, ct, 1, AuthorizationRoles.BizAdmin); var tempObject = BizObjectFactory.GetBizObject(job.AType, ct, 1, AuthorizationRoles.BizAdmin);
if(! (tempObject is IJobObject)){ if (!(tempObject is IJobObject))
throw new System.NotSupportedException($"ProcessJobAsync type {job.JobType.ToString()} is not supported for Batch operations"); {
} throw new System.NotSupportedException($"ProcessJobAsync type {job.JobType.ToString()} is not supported for Batch operations");
o = (IJobObject)tempObject; }
break; o = (IJobObject)tempObject;
case JobType.RenderReport: break;
o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.Report, ct, 1, AuthorizationRoles.BizAdmin); case JobType.RenderReport:
break; o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.Report, ct, 1, AuthorizationRoles.BizAdmin);
default: break;
throw new System.NotSupportedException($"ProcessJobAsync type {job.JobType.ToString()} is not supported"); default:
throw new System.NotSupportedException($"ProcessJobAsync type {job.JobType.ToString()} is not supported");
}
if (o != null)
await o.HandleJobAsync(job);
} }
log.LogDebug($"ProcessJobAsync -> Job completed {JobDescription}");
if (o != null)
await o.HandleJobAsync(job);
} }
log.LogDebug($"ProcessJobAsync -> Job completed {JobDescription}"); catch (Exception ex)
} {
catch(Exception ex){
await LogJobAsync(job.GId, $"LT:BatchJob \"{JobDescription}\" - LT:Failed "); await LogJobAsync(job.GId, $"LT:BatchJob \"{JobDescription}\" - LT:Failed ");
log.LogError(ex,$"ProcessJobAsync -> job failed {JobDescription}"); log.LogError(ex, $"ProcessJobAsync -> job failed {JobDescription}");
await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Failed); await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Failed);
} }
} }

View File

@@ -4,10 +4,14 @@ using Microsoft.Extensions.Logging;
using AyaNova.Models; using AyaNova.Models;
using AyaNova.Util; using AyaNova.Util;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace AyaNova.Biz namespace AyaNova.Biz
{ {
/// <summary> /// <summary>
/// called by Generator to check new releases automatically /// called by Generator to check new releases automatically
/// ///
@@ -18,18 +22,11 @@ namespace AyaNova.Biz
private static DateTime _lastCheck = DateTime.MinValue; private static DateTime _lastCheck = DateTime.MinValue;
#if (DEBUG) #if (DEBUG)
private static TimeSpan FAST_TRACK = new TimeSpan(0, 1, 0);
private static TimeSpan SLOW_TRACK = new TimeSpan(0, 5, 0); private static TimeSpan CHECK_INTERVAL = new TimeSpan(0, 0, 30);//30 seconds
#else #else
#if (SUBSCRIPTION_BUILD)
//subscription servers need to check more frequently because the month to month rentals could be dodgy when 24 hours private static TimeSpan CHECK_INTERVAL = new TimeSpan(24, 0, 0);//every day
//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 #endif
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -37,69 +34,80 @@ namespace AyaNova.Biz
// //
public static async Task DoWorkAsync() public static async Task DoWorkAsync()
{ {
log.LogTrace("Job starting"); if (DateTime.UtcNow - _lastCheck < CHECK_INTERVAL)
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; return;
}
using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) log.LogDebug("Check starting");
// ServerGlobalOpsSettingsCache.LATEST_VERSION = "8.0.44";
// ServerGlobalOpsSettingsCache.CHANGE_LOG_URL = "https://ayanova.com/docs/changelog/";
try
{ {
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); var client = ServiceProviderProvider.HttpClientFactory.CreateClient();
//When this was enabled never saw a failed fetch, trying again without it var res = await client.GetAsync("https://ayanova.com/download/latest-version.json");
//#if (DEBUG) string responseText = string.Empty;
// 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 (res.IsSuccessStatusCode)
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; responseText = await res.Content.ReadAsStringAsync();
var responseJson = JObject.Parse(responseText);
//validate contains version string and that it appears to be valid
if (responseJson.ContainsKey("latestversion"))
{
var v = responseJson["latestversion"].Value<string>();
if (v.Contains("."))
{
ServerGlobalOpsSettingsCache.LATEST_VERSION = v;
}
else
{
log.LogDebug($"version json response latestversion missing or malformed, response was: {responseText}");
}
}
else
{
log.LogDebug($"version json response latestversion missing or malformed, response was: {responseText}");
}
if (responseJson.ContainsKey("changelogurl"))
{
var u = responseJson["changelogurl"].Value<string>();
if (u.Contains("http"))
{
ServerGlobalOpsSettingsCache.CHANGE_LOG_URL = u;
}
else
{
log.LogDebug($"version json response changelogurl missing or malformed, response was: {responseText}");
}
}
else
{
log.LogDebug($"version json response changelogurl missing or malformed, response was: {responseText}");
}
}
else
{
log.LogWarning($"Error checking AyaNova website for updated release version: {res.ReasonPhrase},{responseText}");
} }
} }
catch (Exception ex)
{
log.LogError(ex, "Error checking AyaNova website for updated version");
}
finally
{
_lastCheck = DateTime.UtcNow;
}
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
}//eoc }//eoc