using System;
using System.Linq;
using AyaNova.Models;
namespace AyaNova.Util
{
///
/// Contains static mirror copy in memory of Operations related settings stored in db
/// that are accessed frequently by server
///
internal static class ServerGlobalOpsSettingsCache
{
//BOOT flag, set during boot and
//is used to control generator from starting
internal static bool BOOTING { get; set; }
//False if db server is detected to be down
//is used to control generator from processing
internal static bool DBAVAILABLE { get; set; }
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)
{
Backup = new GlobalOpsBackupSettings();
ct.GlobalOpsBackupSettings.Add(Backup);
ct.SaveChanges();
}
NextBackup = FileUtil.MostRecentAutomatedBackupFileDate();
SetNextBackup();
Notify = ct.GlobalOpsNotificationSettings.FirstOrDefault(z => z.Id == 1);
if (Notify == null)
{
Notify = new GlobalOpsNotificationSettings();
ct.GlobalOpsNotificationSettings.Add(Notify);
ct.SaveChanges();
}
}
internal static void SetNextBackup()
{
DateTime utcNow = DateTime.UtcNow;
//case 4682: the backup time is a time on the server's clock; days are the server's local days
DateTime localToday = TimeZoneInfo.ConvertTimeFromUtc(utcNow, TimeZoneInfo.Local).Date;
//case 4755: the next backup is the next time the backup time comes round on the server's clock: today's if it is
//still ahead, otherwise tomorrow's. It no longer counts from the last backup, which skipped a night after a restart
//between midnight and the backup time, or after a manual backup
NextBackup = BackupTimeOnLocalDay(localToday);
if (NextBackup <= utcNow)
NextBackup = BackupTimeOnLocalDay(localToday.AddDays(1));
}
//case 4682: the backup time is stored as the UTC moment it meant on the day it was set, and was run at that UTC hour
//every day, so it moved an hour on the server's clock with each daylight saving change. The server's clock time is
//recovered with that day's offset and the backup is run at that clock time on the given local day (UTC returned)
private static DateTime BackupTimeOnLocalDay(DateTime localDay)
{
var chosen = TimeZoneInfo.ConvertTimeFromUtc(DateTime.SpecifyKind(Backup.BackupTime, DateTimeKind.Utc), TimeZoneInfo.Local);
var local = DateTime.SpecifyKind(localDay.Date + new TimeSpan(chosen.Hour, chosen.Minute, 0), DateTimeKind.Unspecified);
//a time skipped when the clocks go forward (e.g. 2:30 AM that night) runs an hour later
if (TimeZoneInfo.Local.IsInvalidTime(local))
local = local.AddHours(1);
//case 4755: a time that happens twice when the clocks go back (e.g. 1:30 AM that night) runs at the first one only
if (TimeZoneInfo.Local.IsAmbiguousTime(local))
return new DateTimeOffset(local, TimeZoneInfo.Local.GetAmbiguousTimeOffsets(local).Max()).UtcDateTime;
return TimeZoneInfo.ConvertTimeToUtc(local, TimeZoneInfo.Local);
}
//case 4684: the backup schedule as written to the server log, on the server's clock as the backup time is set
internal static string BackupStatusText()
{
if (!Backup.Active)
return "Automatic backup - inactive";
var utc = DateTime.SpecifyKind(NextBackup, DateTimeKind.Utc);
var local = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);
//from the UTC moment, so the night the clocks go back shows the offset of the hour actually meant
var offset = TimeZoneInfo.Local.GetUtcOffset(utc);
return $"Automatic backup - next at {local:yyyy-MM-dd HH:mm} (UTC{(offset < TimeSpan.Zero ? "-" : "+")}{offset:hh\\:mm})";
}
}//eoc
}//eons