Add enhanced schedule management for background tasks (#267)

This commit is contained in:
Michael Green
2024-01-27 23:30:35 +11:00
committed by GitHub
parent ec115b33de
commit 163aa7a446
20 changed files with 1012 additions and 216 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using System.ComponentModel;
using System.IO.Compression;
using System.Reflection;
using System.Security.Cryptography;
@@ -120,6 +121,28 @@ namespace gaseous_server.Classes
.Single(x => x.GetValue(null).Equals(value)),
typeof(DescriptionAttribute)))?.Description ?? value.ToString();
}
// compression
public static byte[] Compress(byte[] data)
{
MemoryStream output = new MemoryStream();
using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Optimal))
{
dstream.Write(data, 0, data.Length);
}
return output.ToArray();
}
public static byte[] Decompress(byte[] data)
{
MemoryStream input = new MemoryStream(data);
MemoryStream output = new MemoryStream();
using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
{
dstream.CopyTo(output);
}
return output.ToArray();
}
}
/// <summary>

View File

@@ -3,6 +3,7 @@ using System.Data;
using Newtonsoft.Json;
using IGDB.Models;
using gaseous_server.Classes.Metadata;
using NuGet.Common;
namespace gaseous_server.Classes
{
@@ -161,7 +162,7 @@ namespace gaseous_server.Classes
File.WriteAllText(ConfigurationFilePath, configRaw);
}
private static Dictionary<string, string> AppSettings = new Dictionary<string, string>();
private static Dictionary<string, object> AppSettings = new Dictionary<string, object>();
public static void InitSettings()
{
@@ -173,43 +174,67 @@ namespace gaseous_server.Classes
{
if (AppSettings.ContainsKey((string)dataRow["Setting"]))
{
AppSettings[(string)dataRow["Setting"]] = (string)dataRow["Value"];
if ((int)dataRow["ValueType"] == 0)
{
AppSettings[(string)dataRow["Setting"]] = (string)dataRow["Value"];
}
else
{
AppSettings[(string)dataRow["Setting"]] = (DateTime)dataRow["ValueDate"];
}
}
else
{
AppSettings.Add((string)dataRow["Setting"], (string)dataRow["Value"]);
if ((int)dataRow["ValueType"] == 0)
{
AppSettings.Add((string)dataRow["Setting"], (string)dataRow["Value"]);
}
else
{
AppSettings.Add((string)dataRow["Setting"], (DateTime)dataRow["ValueDate"]);
}
}
}
}
public static string ReadSetting(string SettingName, string DefaultValue)
public static T ReadSetting<T>(string SettingName, T DefaultValue)
{
if (AppSettings.ContainsKey(SettingName))
{
return AppSettings[SettingName];
return (T)AppSettings[SettingName];
}
else
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT Value FROM Settings WHERE Setting = @SettingName";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("SettingName", SettingName);
dbDict.Add("Value", DefaultValue);
string sql = "SELECT Value, ValueDate FROM Settings WHERE Setting = @SettingName";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "SettingName", SettingName }
};
try
{
Logging.Log(Logging.LogType.Debug, "Database", "Reading setting '" + SettingName + "'");
DataTable dbResponse = db.ExecuteCMD(sql, dbDict);
Type type = typeof(T);
if (dbResponse.Rows.Count == 0)
{
// no value with that name stored - respond with the default value
SetSetting(SettingName, DefaultValue);
SetSetting<T>(SettingName, DefaultValue);
return DefaultValue;
}
else
{
AppSettings.Add(SettingName, (string)dbResponse.Rows[0][0]);
return (string)dbResponse.Rows[0][0];
if (type.ToString() == "System.DateTime")
{
AppSettings.Add(SettingName, dbResponse.Rows[0]["ValueDate"]);
return (T)dbResponse.Rows[0]["ValueDate"];
}
else
{
AppSettings.Add(SettingName, dbResponse.Rows[0]["Value"]);
return (T)dbResponse.Rows[0]["Value"];
}
}
}
catch (Exception ex)
@@ -220,13 +245,32 @@ namespace gaseous_server.Classes
}
}
public static void SetSetting(string SettingName, string Value)
public static void SetSetting<T>(string SettingName, T Value)
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "REPLACE INTO Settings (Setting, Value) VALUES (@SettingName, @Value)";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("SettingName", SettingName);
dbDict.Add("Value", Value);
string sql = "REPLACE INTO Settings (Setting, ValueType, Value, ValueDate) VALUES (@SettingName, @ValueType, @Value, @ValueDate)";
Dictionary<string, object> dbDict;
Type type = typeof(T);
if (type.ToString() == "System.DateTime")
{
dbDict = new Dictionary<string, object>
{
{ "SettingName", SettingName },
{ "ValueType", 1 },
{ "Value", null },
{ "ValueDate", Value }
};
}
else
{
dbDict = new Dictionary<string, object>
{
{ "SettingName", SettingName },
{ "ValueType", 0 },
{ "Value", Value },
{ "ValueDate", null }
};
}
Logging.Log(Logging.LogType.Debug, "Database", "Storing setting '" + SettingName + "' to value: '" + Value + "'");
try
@@ -341,11 +385,11 @@ namespace gaseous_server.Classes
{
get
{
return ReadSetting("LibraryRootDirectory", Path.Combine(Config.ConfigurationPath, "Data"));
return ReadSetting<string>("LibraryRootDirectory", Path.Combine(Config.ConfigurationPath, "Data"));
}
set
{
SetSetting("LibraryRootDirectory", value);
SetSetting<string>("LibraryRootDirectory", value);
}
}

View File

@@ -452,13 +452,15 @@ namespace gaseous_server.Classes
if (romDT.Rows.Count > 0)
{
foreach (DataRow dr in romDT.Rows)
for (int i = 0; i < romDT.Rows.Count; i++)
{
Logging.Log(Logging.LogType.Information, "Organise Library", "Processing ROM " + dr["name"]);
long RomId = (long)dr["id"];
SetStatus(i, romDT.Rows.Count, "Processing file " + romDT.Rows[i]["name"]);
Logging.Log(Logging.LogType.Information, "Organise Library", "(" + i + "/" + romDT.Rows.Count + ") Processing ROM " + romDT.Rows[i]["name"]);
long RomId = (long)romDT.Rows[i]["id"];
MoveGameFile(RomId);
}
}
ClearStatus();
// clean up empty directories
DeleteOrphanedDirectories(GameLibrary.GetDefaultLibrary.Path);

View File

@@ -9,7 +9,7 @@ namespace gaseous_server.Classes
{
const int MaxFileAge = 30;
public void RunMaintenance()
public void RunDailyMaintenance()
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "";
@@ -33,8 +33,8 @@ namespace gaseous_server.Classes
}
// delete old logs
sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate;";
dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRetentionDate;";
dbDict.Add("EventRetentionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
db.ExecuteCMD(sql, dbDict);
// delete files and directories older than 7 days in PathsToClean
@@ -69,6 +69,13 @@ namespace gaseous_server.Classes
}
}
}
}
public void RunWeeklyMaintenance()
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
Logging.Log(Logging.LogType.Information, "Maintenance", "Optimising database tables");
sql = "SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE';";

View File

@@ -12,6 +12,7 @@ using gaseous_server.Classes.Metadata;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Razor.Hosting;
using RestEase;
namespace gaseous_server.Controllers
{
@@ -96,7 +97,7 @@ namespace gaseous_server.Controllers
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
"var FirstRunStatus = " + Config.ReadSetting("FirstRunStatus", "0") + ";" + Environment.NewLine +
"var FirstRunStatus = " + Config.ReadSetting<string>("FirstRunStatus", "0") + ";" + Environment.NewLine +
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions{
WriteIndented = true
}) + ";" + Environment.NewLine +
@@ -113,19 +114,23 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
[Route("Settings/BackgroundTasks/Intervals")]
[Route("Settings/BackgroundTasks/Configuration")]
[Authorize(Roles = "Admin")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetBackgroundTasks()
{
Dictionary<string, BackgroundTaskItem> Intervals = new Dictionary<string, BackgroundTaskItem>();
Intervals.Add(ProcessQueue.QueueItemType.SignatureIngestor.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.SignatureIngestor));
Intervals.Add(ProcessQueue.QueueItemType.TitleIngestor.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.TitleIngestor));
Intervals.Add(ProcessQueue.QueueItemType.MetadataRefresh.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.MetadataRefresh));
Intervals.Add(ProcessQueue.QueueItemType.OrganiseLibrary.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.OrganiseLibrary));
Intervals.Add(ProcessQueue.QueueItemType.LibraryScan.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.LibraryScan));
Intervals.Add(ProcessQueue.QueueItemType.Rematcher.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.Rematcher));
Intervals.Add(ProcessQueue.QueueItemType.Maintainer.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.Maintainer));
foreach (ProcessQueue.QueueItemType itemType in Enum.GetValues(typeof(ProcessQueue.QueueItemType)))
{
BackgroundTaskItem taskItem = new BackgroundTaskItem(itemType);
if (taskItem.UserManageable == true)
{
if (!Intervals.ContainsKey(itemType.ToString()))
{
Intervals.Add(itemType.ToString(), taskItem);
}
}
}
return Ok(Intervals);
}
@@ -133,45 +138,102 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpPost]
[Route("Settings/BackgroundTasks/Intervals")]
[Route("Settings/BackgroundTasks/Configuration")]
[Authorize(Roles = "Admin")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult SetBackgroundTasks(Dictionary<string, int> Intervals)
public ActionResult SetBackgroundTasks([FromBody] List<BackgroundTaskSettingsItem> model)
{
foreach (KeyValuePair<string, int> Interval in Intervals)
foreach (BackgroundTaskSettingsItem TaskConfiguration in model)
{
if (Enum.IsDefined(typeof(ProcessQueue.QueueItemType), Interval.Key))
if (Enum.IsDefined(typeof(ProcessQueue.QueueItemType), TaskConfiguration.Task))
{
try
{
BackgroundTaskItem taskItem = new BackgroundTaskItem(
(ProcessQueue.QueueItemType)Enum.Parse(typeof(ProcessQueue.QueueItemType), Interval.Key)
(ProcessQueue.QueueItemType)Enum.Parse(typeof(ProcessQueue.QueueItemType), TaskConfiguration.Task)
);
if (Interval.Value >= taskItem.MinimumAllowedValue)
if (taskItem.UserManageable == true)
{
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + Interval.Key + " with new interval " + Interval.Value);
// update task enabled
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with enabled value " + TaskConfiguration.Enabled.ToString());
Config.SetSetting("Interval_" + Interval.Key, Interval.Value.ToString());
Config.SetSetting<string>("Enabled_" + TaskConfiguration.Task, TaskConfiguration.Enabled.ToString());
// update existing process
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
{
if (item.ItemType.ToString().ToLower() == Interval.Key.ToLower())
if (item.ItemType.ToString().ToLower() == TaskConfiguration.Task.ToLower())
{
item.Interval = Interval.Value;
item.Enabled(Boolean.Parse(TaskConfiguration.Enabled.ToString()));
}
}
// update task interval
if (TaskConfiguration.Interval >= taskItem.MinimumAllowedInterval)
{
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new interval " + TaskConfiguration.Interval);
Config.SetSetting<string>("Interval_" + TaskConfiguration.Task, TaskConfiguration.Interval.ToString());
// update existing process
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
{
if (item.ItemType.ToString().ToLower() == TaskConfiguration.Task.ToLower())
{
item.Interval = TaskConfiguration.Interval;
}
}
}
else
{
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Interval " + TaskConfiguration.Interval.ToString() + " for task " + TaskConfiguration.Task + " is below the minimum allowed value of " + taskItem.MinimumAllowedInterval + ". Skipping.");
}
// update task weekdays
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new weekdays " + String.Join(", ", TaskConfiguration.AllowedDays));
Config.SetSetting<string>("AllowedDays_" + TaskConfiguration.Task, Newtonsoft.Json.JsonConvert.SerializeObject(TaskConfiguration.AllowedDays));
// update existing process
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
{
if (item.ItemType.ToString().ToLower() == TaskConfiguration.Task.ToLower())
{
item.AllowedDays = TaskConfiguration.AllowedDays;
}
}
// update task hours
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new hours " + TaskConfiguration.AllowedStartHours + ":" + TaskConfiguration.AllowedStartMinutes.ToString("00") + " to " + TaskConfiguration.AllowedEndHours + ":" + TaskConfiguration.AllowedEndMinutes.ToString("00"));
Config.SetSetting<string>("AllowedStartHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartHours.ToString());
Config.SetSetting<string>("AllowedStartMinutes_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartMinutes.ToString());
Config.SetSetting<string>("AllowedEndHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedEndHours.ToString());
Config.SetSetting<string>("AllowedEndMinutes_" + TaskConfiguration.Task, TaskConfiguration.AllowedEndMinutes.ToString());
// update existing process
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
{
if (item.ItemType.ToString().ToLower() == TaskConfiguration.Task.ToLower())
{
item.AllowedStartHours = TaskConfiguration.AllowedStartHours;
item.AllowedStartMinutes = TaskConfiguration.AllowedStartMinutes;
item.AllowedEndHours = TaskConfiguration.AllowedEndHours;
item.AllowedEndMinutes = TaskConfiguration.AllowedEndMinutes;
}
}
}
else
{
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Interval " + Interval.Value + " for task " + Interval.Key + " is below the minimum allowed value of " + taskItem.MinimumAllowedValue + ". Skipping.");
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Unable to update non-user manageable task " + TaskConfiguration.Task + ". Skipping.");
}
}
catch
{
// task name not defined
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Task " + Interval.Key + " is not user definable. Skipping.");
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Task " + TaskConfiguration.Task + " is not user definable. Skipping.");
}
}
}
@@ -256,61 +318,387 @@ namespace gaseous_server.Controllers
public class BackgroundTaskItem
{
public BackgroundTaskItem()
{
}
public BackgroundTaskItem(ProcessQueue.QueueItemType TaskName)
{
this.Task = TaskName.ToString();
this.TaskEnum = TaskName;
switch (TaskName)
{
case ProcessQueue.QueueItemType.SignatureIngestor:
this._UserManageable = true;
this.DefaultInterval = 60;
this.MinimumAllowedValue = 20;
this.MinimumAllowedInterval = 20;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
break;
case ProcessQueue.QueueItemType.TitleIngestor:
this._UserManageable = true;
this.DefaultInterval = 1;
this.MinimumAllowedValue = 1;
this.MinimumAllowedInterval = 1;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.LibraryScan,
ProcessQueue.QueueItemType.LibraryScanWorker
};
break;
case ProcessQueue.QueueItemType.MetadataRefresh:
this._UserManageable = true;
this.DefaultInterval = 360;
this.MinimumAllowedValue = 360;
this.MinimumAllowedInterval = 360;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
break;
case ProcessQueue.QueueItemType.OrganiseLibrary:
this._UserManageable = true;
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 120;
this.MinimumAllowedInterval = 120;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.LibraryScan,
ProcessQueue.QueueItemType.LibraryScanWorker,
ProcessQueue.QueueItemType.TitleIngestor,
ProcessQueue.QueueItemType.Rematcher
};
break;
case ProcessQueue.QueueItemType.LibraryScan:
this._UserManageable = true;
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 120;
this.MinimumAllowedInterval = 120;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.Rematcher
};
break;
case ProcessQueue.QueueItemType.Rematcher:
this._UserManageable = true;
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 360;
this.MinimumAllowedInterval = 360;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.LibraryScan,
ProcessQueue.QueueItemType.LibraryScanWorker
};
break;
case ProcessQueue.QueueItemType.Maintainer:
case ProcessQueue.QueueItemType.DailyMaintainer:
this._UserManageable = true;
this.DefaultInterval = 1440;
this.MinimumAllowedInterval = 1440;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 1;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 5;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.All
};
break;
case ProcessQueue.QueueItemType.WeeklyMaintainer:
this._UserManageable = true;
this.DefaultInterval = 10080;
this.MinimumAllowedValue = 10080;
this.MinimumAllowedInterval = 10080;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Monday
};
this.DefaultAllowedStartHours = 1;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 5;
this.DefaultAllowedEndMinutes = 59;
this._Blocks = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.All
};
break;
case ProcessQueue.QueueItemType.BackgroundDatabaseUpgrade:
this._UserManageable = false;
this.DefaultInterval = 1;
this.MinimumAllowedInterval = 1;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
this._Blocks.Add(ProcessQueue.QueueItemType.All);
break;
case ProcessQueue.QueueItemType.TempCleanup:
this._UserManageable = true;
this.DefaultInterval = 1;
this.MinimumAllowedInterval = 1;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
break;
default:
throw new Exception("Invalid task");
this._UserManageable = false;
this.DefaultAllowedDays = new List<DayOfWeek>{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
this.DefaultAllowedStartHours = 0;
this.DefaultAllowedStartMinutes = 0;
this.DefaultAllowedEndHours = 23;
this.DefaultAllowedEndMinutes = 59;
break;
}
}
public string Task { get; set; }
public ProcessQueue.QueueItemType TaskEnum { get; set; }
public bool Enabled
{
get
{
if (_UserManageable == true)
{
return bool.Parse(Config.ReadSetting<string>("Enabled_" + Task, true.ToString()));
}
else
{
return true;
}
}
set
{
if (_UserManageable == true)
{
Config.SetSetting<string>("Enabled_" + Task, value.ToString());
}
}
}
private bool _UserManageable;
public bool UserManageable => _UserManageable;
public int Interval {
get
{
return int.Parse(Config.ReadSetting("Interval_" + Task, DefaultInterval.ToString()));
return int.Parse(Config.ReadSetting<string>("Interval_" + Task, DefaultInterval.ToString()));
}
}
public int DefaultInterval { get; set; }
public int MinimumAllowedValue { get; set; }
public int MinimumAllowedInterval { get; set; }
public List<DayOfWeek> AllowedDays
{
get
{
string jsonDefaultAllowedDays = Newtonsoft.Json.JsonConvert.SerializeObject(DefaultAllowedDays);
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<DayOfWeek>>(Config.ReadSetting<string>("AllowedDays_" + Task, jsonDefaultAllowedDays));
}
}
public int AllowedStartHours
{
get
{
return int.Parse(Config.ReadSetting<string>("AllowedStartHours_" + Task, DefaultAllowedStartHours.ToString()));
}
}
public int AllowedStartMinutes
{
get
{
return int.Parse(Config.ReadSetting<string>("AllowedStartMinutes_" + Task, DefaultAllowedStartMinutes.ToString()));
}
}
public int AllowedEndHours
{
get
{
return int.Parse(Config.ReadSetting<string>("AllowedEndHours_" + Task, DefaultAllowedEndHours.ToString()));
}
}
public int AllowedEndMinutes
{
get
{
return int.Parse(Config.ReadSetting<string>("AllowedEndMinutes_" + Task, DefaultAllowedEndMinutes.ToString()));
}
}
public List<DayOfWeek> DefaultAllowedDays { get; set; }
public int DefaultAllowedStartHours { get; set; }
public int DefaultAllowedStartMinutes { get; set; }
public int DefaultAllowedEndHours { get; set; }
public int DefaultAllowedEndMinutes { get; set; }
private List<ProcessQueue.QueueItemType> _Blocks = new List<ProcessQueue.QueueItemType>();
public List<ProcessQueue.QueueItemType> Blocks
{
get
{
if (_Blocks.Contains(ProcessQueue.QueueItemType.All))
{
List<ProcessQueue.QueueItemType> blockList = new List<ProcessQueue.QueueItemType>();
List<ProcessQueue.QueueItemType> skipBlockItems = new List<ProcessQueue.QueueItemType>{
ProcessQueue.QueueItemType.All,
ProcessQueue.QueueItemType.NotConfigured,
this.TaskEnum
};
foreach (ProcessQueue.QueueItemType blockType in Enum.GetValues(typeof(ProcessQueue.QueueItemType)))
{
if (!skipBlockItems.Contains(blockType))
{
blockList.Add(blockType);
}
}
return blockList;
}
else
{
return _Blocks;
}
}
}
public List<ProcessQueue.QueueItemType> BlockedBy
{
get
{
List<ProcessQueue.QueueItemType> blockedBy = new List<ProcessQueue.QueueItemType>();
List<BackgroundTaskItem> backgroundTaskItems = new List<BackgroundTaskItem>();
foreach (ProcessQueue.QueueItemType blockType in Enum.GetValues(typeof(ProcessQueue.QueueItemType)))
{
if (blockType != this.TaskEnum)
{
BackgroundTaskItem taskItem = new BackgroundTaskItem(blockType);
if (taskItem.Blocks.Contains(this.TaskEnum))
{
if (!blockedBy.Contains(blockType))
{
blockedBy.Add(blockType);
}
}
}
}
return blockedBy;
}
}
}
public class BackgroundTaskSettingsItem
{
public string Task { get; set; }
public bool Enabled { get; set; }
public int Interval { get; set; }
public List<DayOfWeek> AllowedDays { get; set; }
public int AllowedStartHours { get; set; }
public int AllowedStartMinutes { get; set; }
public int AllowedEndHours { get; set; }
public int AllowedEndMinutes { get; set; }
}
public class SystemSettingsModel

View File

@@ -40,7 +40,7 @@ namespace gaseous_server.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> CreateAdminAccount(Authentication.RegisterViewModel model)
{
if (Config.ReadSetting("FirstRunStatus", "0") == "0")
if (Config.ReadSetting<string>("FirstRunStatus", "0") == "0")
{
if (ModelState.IsValid)
{
@@ -68,7 +68,7 @@ namespace gaseous_server.Controllers
await _signInManager.SignInAsync(user, isPersistent: true);
Logging.Log(Logging.LogType.Information, "First Run", "Setting first run state to 1");
Config.SetSetting("FirstRunStatus", "1");
Config.SetSetting<string>("FirstRunStatus", "1");
return Ok(result);
}

View File

@@ -36,9 +36,11 @@ namespace gaseous_server.Controllers.v1_1
public async Task<ActionResult> SaveStateAsync(long RomId, UploadStateModel uploadState, bool IsMediaGroup = false)
{
var user = await _userManager.GetUserAsync(User);
byte[] CompressedState = Common.Compress(uploadState.StateByteArray);
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state); SELECT LAST_INSERT_ID();";
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State, Zipped) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state, @zipped); SELECT LAST_INSERT_ID();";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "userid", user.Id },
@@ -47,10 +49,20 @@ namespace gaseous_server.Controllers.v1_1
{ "statedatetime", DateTime.UtcNow },
{ "name", "" },
{ "screenshot", uploadState.ScreenshotByteArray },
{ "state", uploadState.StateByteArray }
{ "state", CompressedState },
{ "zipped", true }
};
DataTable data = db.ExecuteCMD(sql, dbDict);
if (IsMediaGroup == false)
{
Logging.Log(Logging.LogType.Information, "Save State", "Saved state for rom id " + RomId + ". State size: " + uploadState.StateByteArrayBase64.Length + " Compressed size: " + CompressedState.Length);
}
else
{
Logging.Log(Logging.LogType.Information, "Save State", "Saved state for media group id " + RomId + ". State size: " + uploadState.StateByteArrayBase64.Length + " Compressed size: " + CompressedState.Length);
}
return Ok(await GetStateAsync(RomId, (long)(ulong)data.Rows[0][0], IsMediaGroup));
}
@@ -224,7 +236,7 @@ namespace gaseous_server.Controllers.v1_1
{
var user = await _userManager.GetUserAsync(User);
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT State FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
string sql = "SELECT Zipped, State FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "id", StateId },
@@ -242,7 +254,15 @@ namespace gaseous_server.Controllers.v1_1
else
{
string filename = "savestate.state";
byte[] bytes = (byte[])data.Rows[0][0];
byte[] bytes;
if ((bool)data.Rows[0]["Zipped"] == false)
{
bytes = (byte[])data.Rows[0]["State"];
}
else
{
bytes = Common.Decompress((byte[])data.Rows[0]["State"]);
}
string contentType = "application/octet-stream";
var cd = new System.Net.Mime.ContentDisposition

View File

@@ -2,6 +2,8 @@
using System.ComponentModel.Design.Serialization;
using System.Data;
using gaseous_server.Classes;
using gaseous_server.Controllers;
using Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal;
using NuGet.Common;
using NuGet.Packaging;
@@ -13,25 +15,63 @@ namespace gaseous_server
public class QueueItem
{
public QueueItem(QueueItemType ItemType, bool AllowManualStart = true, bool RemoveWhenStopped = false)
{
_ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted;
_LastRunTime = Config.ReadSetting<DateTime>("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.AddMinutes(-5));
_AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
// load queueitem configuration
BackgroundTaskItem defaultItem = new BackgroundTaskItem(ItemType);
Enabled(defaultItem.Enabled);
_Interval = defaultItem.Interval;
_AllowedDays = defaultItem.AllowedDays;
AllowedStartHours = defaultItem.AllowedStartHours;
AllowedStartMinutes = defaultItem.AllowedStartMinutes;
AllowedEndHours = defaultItem.AllowedEndHours;
AllowedEndMinutes = defaultItem.AllowedEndMinutes;
_Blocks = defaultItem.Blocks;
}
public QueueItem(QueueItemType ItemType, int ExecutionInterval, bool AllowManualStart = true, bool RemoveWhenStopped = false)
{
_ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
_LastRunTime = Config.ReadSetting<DateTime>("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.AddMinutes(-5));
_Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
// load timing defaults
BackgroundTaskItem defaultItem = new BackgroundTaskItem(ItemType);
Enabled(defaultItem.Enabled);
_AllowedDays = defaultItem.AllowedDays;
AllowedStartHours = defaultItem.AllowedStartHours;
AllowedStartMinutes = defaultItem.AllowedStartMinutes;
AllowedEndHours = defaultItem.AllowedEndHours;
AllowedEndMinutes = defaultItem.AllowedEndMinutes;
}
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks, bool AllowManualStart = true, bool RemoveWhenStopped = false)
{
_ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
_LastRunTime = Config.ReadSetting<DateTime>("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.AddMinutes(-5));
_Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
_Blocks = Blocks;
// load timing defaults
BackgroundTaskItem defaultItem = new BackgroundTaskItem(ItemType);
Enabled(defaultItem.Enabled);
_AllowedDays = defaultItem.AllowedDays;
AllowedStartHours = defaultItem.AllowedStartHours;
AllowedStartMinutes = defaultItem.AllowedStartMinutes;
AllowedEndHours = defaultItem.AllowedEndHours;
AllowedEndMinutes = defaultItem.AllowedEndMinutes;
}
private QueueItemType _ItemType = QueueItemType.NotConfigured;
@@ -42,13 +82,15 @@ namespace gaseous_server
{
get
{
return DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
// return DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
return Config.ReadSetting<DateTime>("LastRun_" + _ItemType.ToString(), DateTime.UtcNow);
}
set
{
if (_SaveLastRunTime == true)
{
Config.SetSetting("LastRun_" + _ItemType.ToString(), value.ToString("yyyy-MM-ddThh:mm:ssZ"));
//Config.SetSetting("LastRun_" + _ItemType.ToString(), value.ToString("yyyy-MM-ddThh:mm:ssZ"));
Config.SetSetting<DateTime>("LastRun_" + _ItemType.ToString(), value);
}
}
}
@@ -61,8 +103,33 @@ namespace gaseous_server
private bool _RemoveWhenStopped = false;
private bool _IsBlocked = false;
private string _CorrelationId = "";
private List<DayOfWeek> _AllowedDays = new List<DayOfWeek>
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
private List<QueueItemType> _Blocks = new List<QueueItemType>();
public List<DayOfWeek> AllowedDays
{
get
{
return _AllowedDays;
}
set
{
_AllowedDays = value;
}
}
public int AllowedStartHours { get; set; } = 0;
public int AllowedStartMinutes { get; set; } = 0;
public int AllowedEndHours { get; set; } = 23;
public int AllowedEndMinutes { get; set; } = 59;
public QueueItemType ItemType => _ItemType;
public QueueItemState ItemState => _ItemState;
public DateTime LastRunTime => _LastRunTime;
@@ -72,9 +139,56 @@ namespace gaseous_server
{
get
{
return LastRunTime.AddMinutes(Interval);
// next run time
DateTime tempNextRun = LastRunTime.ToLocalTime().AddMinutes(Interval);
// if (tempNextRun < DateTime.Now)
// {
// tempNextRun = DateTime.Now;
// }
DayOfWeek nextWeekDay = tempNextRun.DayOfWeek;
// create local start and end times
DateTime tempStartTime = new DateTime(tempNextRun.Year, tempNextRun.Month, tempNextRun.Day, AllowedStartHours, AllowedStartMinutes, 0, DateTimeKind.Local);
DateTime tempEndTime = new DateTime(tempNextRun.Year, tempNextRun.Month, tempNextRun.Day, AllowedEndHours, AllowedEndMinutes, 0, DateTimeKind.Local);
// bump the next run time to the next allowed day and hour range
if (AllowedDays.Contains(nextWeekDay))
{
// next run day is allowed, nothing to do
}
else
{
// keep bumping the day forward until the a weekday is found
do
{
tempNextRun = tempNextRun.AddDays(1);
nextWeekDay = tempNextRun.DayOfWeek;
}
while (!AllowedDays.Contains(nextWeekDay));
// update windows
tempStartTime = new DateTime(tempNextRun.Year, tempNextRun.Month, tempNextRun.Day, AllowedStartHours, AllowedStartMinutes, 0, DateTimeKind.Local);
tempEndTime = new DateTime(tempNextRun.Year, tempNextRun.Month, tempNextRun.Day, AllowedEndHours, AllowedEndMinutes, 0, DateTimeKind.Local);
}
// are the hours in the right range
TimeSpan spanNextRun = tempNextRun.TimeOfDay;
if (LastRunTime.ToLocalTime().AddMinutes(Interval) < tempStartTime)
{
return tempStartTime.ToUniversalTime();
}
else if (spanNextRun >= tempStartTime.TimeOfDay && spanNextRun <= tempEndTime.TimeOfDay)
{
// all good - return nextRun
return tempNextRun.ToUniversalTime();
}
else
{
return tempStartTime.ToUniversalTime();
}
}
}
public int Interval
{
get
@@ -233,12 +347,25 @@ namespace gaseous_server
DatabaseMigration.UpgradeScriptBackgroundTasks();
break;
case QueueItemType.Maintainer:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Maintenance");
case QueueItemType.DailyMaintainer:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Daily Maintenance");
Classes.Maintenance maintenance = new Maintenance{
CallingQueueItem = this
};
maintenance.RunMaintenance();
maintenance.RunDailyMaintenance();
_SaveLastRunTime = true;
break;
case QueueItemType.WeeklyMaintainer:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Weekly Maintenance");
Classes.Maintenance weeklyMaintenance = new Maintenance{
CallingQueueItem = this
};
weeklyMaintenance.RunWeeklyMaintenance();
_SaveLastRunTime = true;
break;
case QueueItemType.TempCleanup:
@@ -277,7 +404,14 @@ namespace gaseous_server
}
_ForceExecute = false;
_ItemState = QueueItemState.Stopped;
if (_DisableWhenComplete == false)
{
_ItemState = QueueItemState.Stopped;
}
else
{
_ItemState = QueueItemState.Disabled;
}
_LastFinishTime = DateTime.UtcNow;
_LastRunDuration = Math.Round((DateTime.UtcNow - _LastRunTime).TotalSeconds, 2);
@@ -296,6 +430,26 @@ namespace gaseous_server
_IsBlocked = BlockState;
}
private bool _DisableWhenComplete = false;
public void Enabled(bool Enabled)
{
_DisableWhenComplete = !Enabled;
if (Enabled == true)
{
if (_ItemState == QueueItemState.Disabled)
{
_ItemState = QueueItemState.Stopped;
}
}
else
{
if (_ItemState == QueueItemState.Stopped || _ItemState == QueueItemState.NeverStarted)
{
_ItemState = QueueItemState.Disabled;
}
}
}
public HasErrorsItem HasErrors
{
get
@@ -420,9 +574,14 @@ namespace gaseous_server
BackgroundDatabaseUpgrade,
/// <summary>
/// Performs a clean up of old files, and optimises the database
/// Performs a clean up of old files, and purge old logs
/// </summary>
Maintainer,
DailyMaintainer,
/// <summary>
/// Performs more intensive cleanups and optimises the database
/// </summary>
WeeklyMaintainer,
/// <summary>
/// Cleans up marked paths in the temporary directory

View File

@@ -55,15 +55,6 @@ Communications.MetadataSource = Config.MetadataConfiguration.MetadataSource;
// set up hasheous client
HasheousClient.WebApp.HttpHelper.BaseUri = Config.MetadataConfiguration.HasheousHost;
// set initial values
Guid APIKey = Guid.NewGuid();
if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")
{
// it's a new api key save it
Logging.Log(Logging.LogType.Information, "Startup", "Setting initial API key");
Config.SetSetting("API Key", APIKey.ToString());
}
// clean up storage
if (Directory.Exists(Config.LibraryConfiguration.LibraryTempDirectory))
{
@@ -421,69 +412,38 @@ var platformMap = PlatformMapping.PlatformMap;
// add background tasks
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.SignatureIngestor,
int.Parse(Config.ReadSetting("Interval_SignatureIngestor", "60"))
)
ProcessQueue.QueueItemType.SignatureIngestor)
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.TitleIngestor,
int.Parse(Config.ReadSetting("Interval_TitleIngestor", "1")),
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.LibraryScan
})
ProcessQueue.QueueItemType.TitleIngestor)
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.MetadataRefresh,
int.Parse(Config.ReadSetting("Interval_MetadataRefresh", "360"))
)
ProcessQueue.QueueItemType.MetadataRefresh)
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.OrganiseLibrary,
int.Parse(Config.ReadSetting("Interval_OrganiseLibrary", "1440")),
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.LibraryScan,
ProcessQueue.QueueItemType.TitleIngestor,
ProcessQueue.QueueItemType.Rematcher
})
ProcessQueue.QueueItemType.OrganiseLibrary)
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.LibraryScan,
int.Parse(Config.ReadSetting("Interval_LibraryScan", "1440")),
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.Rematcher
})
ProcessQueue.QueueItemType.LibraryScan)
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.Rematcher,
int.Parse(Config.ReadSetting("Interval_Rematcher", "1440")),
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.OrganiseLibrary,
ProcessQueue.QueueItemType.LibraryScan
})
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.Maintainer,
int.Parse(Config.ReadSetting("Interval_Maintainer", "10080")),
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.All
})
ProcessQueue.QueueItemType.Rematcher)
);
ProcessQueue.QueueItem tempCleanup = new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.TempCleanup,
1,
new List<ProcessQueue.QueueItemType>(),
false,
false
// maintenance tasks
ProcessQueue.QueueItem dailyMaintenance = new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.DailyMaintainer
);
ProcessQueue.QueueItems.Add(dailyMaintenance);
ProcessQueue.QueueItem weeklyMaintenance = new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.WeeklyMaintainer
);
ProcessQueue.QueueItems.Add(weeklyMaintenance);
ProcessQueue.QueueItem tempCleanup = new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.TempCleanup
);
tempCleanup.ForceExecute();
ProcessQueue.QueueItems.Add(tempCleanup);
Logging.WriteToDiskOnly = false;

View File

@@ -0,0 +1,6 @@
ALTER TABLE `Settings`
ADD COLUMN `ValueType` INT NULL DEFAULT 0 AFTER `Setting`,
ADD COLUMN `ValueDate` DATETIME NULL DEFAULT NULL AFTER `Value`;
ALTER TABLE `GameState`
ADD COLUMN `Zipped` BOOLEAN NOT NULL DEFAULT 0;

View File

@@ -20,8 +20,8 @@ namespace gaseous_server
//_logger.LogInformation("Timed Hosted Service running.");
Logging.Log(Logging.LogType.Debug, "Background", "Starting background task monitor");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
_timer = new Timer(DoWork, null, TimeSpan.FromSeconds(30),
TimeSpan.FromSeconds(30));
return Task.CompletedTask;
}
@@ -36,20 +36,23 @@ namespace gaseous_server
List<ProcessQueue.QueueItem> ActiveList = new List<ProcessQueue.QueueItem>();
ActiveList.AddRange(ProcessQueue.QueueItems);
foreach (ProcessQueue.QueueItem qi in ActiveList) {
if (CheckIfProcessIsBlockedByOthers(qi) == false) {
qi.BlockedState(false);
if (DateTime.UtcNow > qi.NextRunTime || qi.Force == true)
{
qi.Execute();
if (qi.RemoveWhenStopped == true && qi.ItemState == ProcessQueue.QueueItemState.Stopped)
if (qi.ItemState != ProcessQueue.QueueItemState.Disabled)
{
if (CheckIfProcessIsBlockedByOthers(qi) == false) {
qi.BlockedState(false);
if (DateTime.UtcNow > qi.NextRunTime || qi.Force == true)
{
ProcessQueue.QueueItems.Remove(qi);
qi.Execute();
if (qi.RemoveWhenStopped == true && qi.ItemState == ProcessQueue.QueueItemState.Stopped)
{
ProcessQueue.QueueItems.Remove(qi);
}
}
}
}
else
{
qi.BlockedState(true);
else
{
qi.BlockedState(true);
}
}
}
}

View File

@@ -60,6 +60,7 @@
<None Remove="Support\Database\MySQL\gaseous-1013.sql" />
<None Remove="Support\Database\MySQL\gaseous-1014.sql" />
<None Remove="Support\Database\MySQL\gaseous-1015.sql" />
<None Remove="Support\Database\MySQL\gaseous-1016.sql" />
<None Remove="Classes\Metadata\" />
</ItemGroup>
<ItemGroup>
@@ -97,5 +98,6 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1013.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1014.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1015.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1016.sql" />
</ItemGroup>
</Project>

View File

@@ -29,6 +29,7 @@
EJS_pathtodata = '/emulators/EmulatorJS/data/';
EJS_DEBUG_XX = false;
console.log("Debug enabled: " + EJS_DEBUG_XX);
EJS_backgroundImage = emuBackground;
EJS_backgroundBlur = true;

View File

@@ -268,7 +268,7 @@
if (newPassword.length > 0) {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length > 10) {
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
return true;

View File

@@ -49,7 +49,7 @@
if (userNameVal.includes("@")) {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length > 10) {
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
} else {

View File

@@ -285,7 +285,7 @@
} else {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length > 10) {
if (newPassword.length >= 10) {
errorLabel.innerHTML = "";
submitButton.removeAttribute('disabled');
} else {

View File

@@ -117,7 +117,7 @@
} else {
if (newPassword == conPassword) {
// check if password meets requirements
if (newPassword.length > 10) {
if (newPassword.length >= 10) {
errorLabel.innerHTML = "&nbsp;";
submitButton.removeAttribute('disabled');
} else {

View File

@@ -11,7 +11,6 @@
<h2>Advanced Settings</h2>
<p><strong>Warning</strong> Do not modify the below settings unless you know what you're doing.</p>
<h3>Background Task Timers</h3>
<p>All intervals are in minutes.</p>
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
</table>
@@ -104,44 +103,241 @@
function getBackgroundTaskTimers() {
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Intervals',
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'GET',
function(result) {
var targetTable = document.getElementById('settings_tasktimers');
targetTable.innerHTML = '';
targetTable.appendChild(
createTableRow(true, ['Background Task', 'Timer Interval', 'Default Interval', 'Minimum Allowed Interval'])
);
for (const [key, value] of Object.entries(result)) {
var newTableRow = createTableRow(
var newTableRowBody = document.createElement('tbody');
newTableRowBody.className = 'romrow';
var enabledString = "";
if (value.enabled == true) {
enabledString = 'checked="checked"';
}
var newTableIntervalRow = createTableRow(
false,
[
GetTaskFriendlyName(value.task),
'<input id="settings_tasktimers_' + value.task + '" name="settings_tasktimers_values" data-name="' + value.task + '" data-default="' + value.defaultInterval + '" type="number" placeholder="0" min="' + value.minimumAllowedValue + '" value="' + value.interval + '" />',
value.defaultInterval,
value.minimumAllowedValue
'Enabled',
'<input id="settings_enabled_' + value.task + '" name="settings_tasktimers_enabled" type="checkbox" ' + enabledString + '/>',
],
'romrow',
'',
'romcell'
);
targetTable.appendChild(newTableRow);
newTableRowBody.appendChild(newTableIntervalRow);
var newTableRow = createTableRow(
false,
[
'',
'Minimum Interval (Minutes):',
'<input id="settings_tasktimers_' + value.task + '" name="settings_tasktimers_values" data-name="' + value.task + '" data-default="' + value.defaultInterval + '" type="number" placeholder="' + value.defaultInterval + '" min="' + value.minimumAllowedInterval + '" value="' + value.interval + '" />'
],
'',
'romcell'
);
newTableRowBody.appendChild(newTableRow);
// allowed time periods row
var newTableRowTime = document.createElement('tr');
var rowTimeSpace = document.createElement('td');
newTableRowTime.appendChild(rowTimeSpace);
var rowTimeContentTitle = document.createElement('td');
rowTimeContentTitle.className = 'romcell';
rowTimeContentTitle.innerHTML = "Allowed Days:";
newTableRowTime.appendChild(rowTimeContentTitle);
var rowTimeContent = document.createElement('td');
// rowTimeContent.setAttribute('colspan', 2);
rowTimeContent.className = 'romcell';
var daySelector = document.createElement('select');
daySelector.id = 'settings_alloweddays_' + value.task;
daySelector.name = 'settings_alloweddays';
daySelector.multiple = 'multiple';
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
daySelector.style.width = '95%';
var days = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ];
for (var d = 0; d < days.length; d++) {
var dayOpt = document.createElement('option');
dayOpt.value = days[d];
dayOpt.innerHTML = days[d];
if (value.allowedDays.includes(days[d])) {
dayOpt.selected = 'selected';
}
daySelector.appendChild(dayOpt);
}
rowTimeContent.appendChild(daySelector);
$(daySelector).select2({
tags: false
});
newTableRowTime.appendChild(rowTimeContent);
newTableRowBody.appendChild(newTableRowTime);
// add start and end times
var newTableRowClock = document.createElement('tr');
var rowClockSpace = document.createElement('td');
newTableRowClock.appendChild(rowClockSpace);
var rowClockContentTitle = document.createElement('td');
rowClockContentTitle.className = 'romcell';
rowClockContentTitle.innerHTML = "Time Range:";
newTableRowClock.appendChild(rowClockContentTitle);
var rowClockContent = document.createElement('td');
rowClockContent.className = 'romcell';
// rowClockContent.setAttribute('colspan', 2);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'Start', value.defaultAllowedStartHours, value.defaultAllowedStartMinutes, value.allowedStartHours, value.allowedStartMinutes));
rowClockContentSeparator = document.createElement('span');
rowClockContentSeparator.innerHTML = '&nbsp;-&nbsp;';
rowClockContent.appendChild(rowClockContentSeparator);
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'End', value.defaultAllowedEndHours, value.defaultAllowedEndMinutes, value.allowedEndHours, value.allowedEndMinutes));
newTableRowClock.appendChild(rowClockContent);
newTableRowBody.appendChild(newTableRowClock);
// blocks tasks
var newTableRowBlocks = document.createElement('tr');
var rowBlocksSpace = document.createElement('td');
newTableRowBlocks.appendChild(rowBlocksSpace);
var rowBlocksContentTitle = document.createElement('td');
rowBlocksContentTitle.className = 'romcell';
rowBlocksContentTitle.innerHTML = "Blocks:";
newTableRowBlocks.appendChild(rowBlocksContentTitle);
var rowBlocksContent = document.createElement('td');
rowBlocksContent.className = 'romcell';
// rowBlocksContent.setAttribute('colspan', 2);
var blocksString = "";
for (var i = 0; i < value.blocks.length; i++) {
if (blocksString.length > 0) { blocksString += ", "; }
blocksString += GetTaskFriendlyName(value.blocks[i]);
}
if (blocksString.length == 0) { blocksString = 'None'; }
rowBlocksContent.innerHTML = blocksString;
newTableRowBlocks.appendChild(rowBlocksContent);
newTableRowBody.appendChild(newTableRowBlocks);
// blocked by tasks
var newTableRowBlockedBy = document.createElement('tr');
var rowBlockedBySpace = document.createElement('td');
newTableRowBlockedBy.appendChild(rowBlockedBySpace);
var rowBlockedByContentTitle = document.createElement('td');
rowBlockedByContentTitle.className = 'romcell';
rowBlockedByContentTitle.innerHTML = "Blocked By:";
newTableRowBlockedBy.appendChild(rowBlockedByContentTitle);
var rowBlockedByContent = document.createElement('td');
rowBlockedByContent.className = 'romcell';
// rowBlockedByContent.setAttribute('colspan', 2);
var BlockedByString = "";
for (var i = 0; i < value.blockedBy.length; i++) {
if (BlockedByString.length > 0) { BlockedByString += ", "; }
BlockedByString += GetTaskFriendlyName(value.blockedBy[i]);
}
if (BlockedByString.length == 0) { BlockedByString = 'None'; }
rowBlockedByContent.innerHTML = BlockedByString;
newTableRowBlockedBy.appendChild(rowBlockedByContent);
newTableRowBody.appendChild(newTableRowBlockedBy);
// complete row
targetTable.appendChild(newTableRowBody);
}
}
);
}
function generateTimeDropDowns(taskName, rangeName, defaultHour, defaultMinute, valueHour, valueMinute) {
var container = document.createElement('div');
container.style.display = 'inline';
var elementName = 'settings_tasktimers_time';
var hourSelector = document.createElement('input');
hourSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Hour';
hourSelector.name = elementName;
hourSelector.setAttribute('data-name', taskName);
hourSelector.setAttribute('type', 'number');
hourSelector.setAttribute('min', '0');
hourSelector.setAttribute('max', '23');
hourSelector.setAttribute('placeholder', defaultHour);
hourSelector.value = valueHour;
container.appendChild(hourSelector);
var separator = document.createElement('span');
separator.innerHTML = " : ";
container.appendChild(separator);
var minSelector = document.createElement('input');
minSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Minute';
minSelector.name = elementName;
minSelector.setAttribute('type', 'number');
minSelector.setAttribute('min', '0');
minSelector.setAttribute('max', '59');
minSelector.setAttribute('placeholder', defaultMinute);
minSelector.value = valueMinute;
container.appendChild(minSelector);
return container;
}
function saveTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_values');
var model = {};
var model = [];
for (var i = 0; i < timerValues.length; i++) {
model[timerValues[i].getAttribute('data-name')] = timerValues[i].value;
var taskName = timerValues[i].getAttribute('data-name');
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
var taskInterval = function() { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
var taskDays = [];
if (taskDaysRaw.length > 0) {
for (var d = 0; d < taskDaysRaw.length; d++) {
taskDays.push(taskDaysRaw[d].id);
}
} else {
taskDays.push("Monday");
}
var taskStartHourObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Hour');
var taskStartMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Minute');
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
var taskStartHour = function() { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
var taskStartMinute = function() { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
var taskEndHour = function() { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
var taskEndMinute = function() { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
model.push(
{
"task": taskName,
"enabled": taskEnabled,
"interval": taskInterval(),
"allowedDays": taskDays,
"allowedStartHours": taskStartHour(),
"allowedStartMinutes": taskStartMinute(),
"allowedEndHours": taskEndHour(),
"allowedEndMinutes": taskEndMinute()
}
);
}
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Intervals',
'/api/v1/System/Settings/BackgroundTasks/Configuration',
'POST',
function(result) {
getBackgroundTaskTimers();
@@ -154,12 +350,32 @@
}
function defaultTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_enabled');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].checked = true;
}
var timerValues = document.getElementsByName('settings_tasktimers_values');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].value = timerValues[i].getAttribute('data-default');
}
var timerValues = document.getElementsByName('settings_alloweddays');
for (var i = 0; i < timerValues.length; i++) {
var defaultSelections = timerValues[i].getAttribute('data-default').split(',');
$(timerValues[i]).val(defaultSelections);
$(timerValues[i]).trigger('change');
}
var timerValues = document.getElementsByName('settings_tasktimers_time');
for (var i = 0; i < timerValues.length; i++) {
timerValues[i].value = timerValues[i].getAttribute('placeholder');
}
saveTaskTimers();
}

View File

@@ -410,13 +410,25 @@ function GetTaskFriendlyName(TaskName, options) {
case 'LibraryScan':
return "Library scan";
case 'LibraryScanWorker':
return "Library scan worker: " + options.name;
if (options) {
return "Library scan worker: " + options.name;
} else {
return "Library scan worker";
}
case 'CollectionCompiler':
return "Compress collection id: " + options;
if (options) {
return "Compress collection id: " + options;
} else {
return "Compress collection";
}
case 'BackgroundDatabaseUpgrade':
return "Background database upgrade";
case 'TempCleanup':
return "Temporary directory cleanup";
case 'DailyMaintainer':
return "Daily maintenance";
case 'WeeklyMaintainer':
return "Weekly maintenance";
default:
return TaskName;
}