Skip to content

Commit

Permalink
Background task execution intervals are now user configurable (#209)
Browse files Browse the repository at this point in the history
* Store background task intervals in database

* Background task intervals are now user customisable
  • Loading branch information
michael-j-green authored Dec 1, 2023
1 parent 0bf2ba5 commit b564edb
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 29 deletions.
130 changes: 130 additions & 0 deletions gaseous-server/Controllers/V1.0/SystemController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using System.Data;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using gaseous_server.Classes;
using gaseous_server.Classes.Metadata;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Razor.Hosting;

namespace gaseous_server.Controllers
{
Expand Down Expand Up @@ -99,6 +101,75 @@ public FileContentResult GetSystemVersionAsFile() {
return File(bytes, "text/javascript");
}

[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
[Route("Settings/BackgroundTasks/Intervals")]
[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));

return Ok(Intervals);
}

[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpPost]
[Route("Settings/BackgroundTasks/Intervals")]
[Authorize(Roles = "Admin")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult SetBackgroundTasks(Dictionary<string, int> Intervals)
{
foreach (KeyValuePair<string, int> Interval in Intervals)
{
if (Enum.IsDefined(typeof(ProcessQueue.QueueItemType), Interval.Key))
{
try
{
BackgroundTaskItem taskItem = new BackgroundTaskItem(
(ProcessQueue.QueueItemType)Enum.Parse(typeof(ProcessQueue.QueueItemType), Interval.Key)
);

if (Interval.Value >= taskItem.MinimumAllowedValue)
{
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + Interval.Key + " with new interval " + Interval.Value);

Config.SetSetting("Interval_" + Interval.Key, Interval.Value.ToString());

// update existing process
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
{
if (item.ItemType.ToString().ToLower() == Interval.Key.ToLower())
{
item.Interval = Interval.Value;
}
}
}
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.");
}
}
catch
{
// task name not defined
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Task " + Interval.Key + " is not user definable. Skipping.");
}
}
}

return Ok();
}

private SystemInfo.PathItem GetDisk(string Path)
{
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
Expand Down Expand Up @@ -139,4 +210,63 @@ public class PlatformStatisticsItem
}
}
}

public class BackgroundTaskItem
{
public BackgroundTaskItem(ProcessQueue.QueueItemType TaskName)
{
this.Task = TaskName.ToString();

switch (TaskName)
{
case ProcessQueue.QueueItemType.SignatureIngestor:
this.DefaultInterval = 60;
this.MinimumAllowedValue = 20;
break;

case ProcessQueue.QueueItemType.TitleIngestor:
this.DefaultInterval = 1;
this.MinimumAllowedValue = 1;
break;

case ProcessQueue.QueueItemType.MetadataRefresh:
this.DefaultInterval = 360;
this.MinimumAllowedValue = 360;
break;

case ProcessQueue.QueueItemType.OrganiseLibrary:
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 120;
break;

case ProcessQueue.QueueItemType.LibraryScan:
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 120;
break;

case ProcessQueue.QueueItemType.Rematcher:
this.DefaultInterval = 1440;
this.MinimumAllowedValue = 360;
break;

case ProcessQueue.QueueItemType.Maintainer:
this.DefaultInterval = 10080;
this.MinimumAllowedValue = 10080;
break;

default:
throw new Exception("Invalid task");
}
}

public string Task { get; set; }
public int Interval {
get
{
return int.Parse(Config.ReadSetting("Interval_" + Task, DefaultInterval.ToString()));
}
}
public int DefaultInterval { get; set; }
public int MinimumAllowedValue { get; set; }
}
}
12 changes: 11 additions & 1 deletion gaseous-server/ProcessQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,17 @@ public DateTime NextRunTime {
return LastRunTime.AddMinutes(Interval);
}
}
public int Interval => _Interval;
public int Interval
{
get
{
return _Interval;
}
set
{
_Interval = value;
}
}
public string LastResult => _LastResult;
public string? LastError => _LastError;
public bool Force => _ForceExecute;
Expand Down
71 changes: 71 additions & 0 deletions gaseous-server/wwwroot/pages/settings/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ <h3>Libraries</h3>
</table>
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showSubDialog('librarynew');">New Library</button></div>

<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>
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>

<script type="text/javascript">
function drawLibrary() {
ajaxCall(
Expand Down Expand Up @@ -59,5 +68,67 @@ <h3>Libraries</h3>
);
}

function getBackgroundTaskTimers() {
ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Intervals',
'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(
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
],
'romrow',
'romcell'
);
targetTable.appendChild(newTableRow);
}
}
);
}

function saveTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_values');

var model = {};
for (var i = 0; i < timerValues.length; i++) {
model[timerValues[i].getAttribute('data-name')] = timerValues[i].value;
}

ajaxCall(
'/api/v1/System/Settings/BackgroundTasks/Intervals',
'POST',
function(result) {
getBackgroundTaskTimers();
},
function(error) {
getBackgroundTaskTimers();
},
JSON.stringify(model)
);
}

function defaultTaskTimers() {
var timerValues = document.getElementsByName('settings_tasktimers_values');

for (var i = 0; i < timerValues.length; i++) {
timerValues[i].value = timerValues[i].getAttribute('data-default');
}

saveTaskTimers();
}

drawLibrary();
getBackgroundTaskTimers();
</script>
30 changes: 2 additions & 28 deletions gaseous-server/wwwroot/pages/settings/system.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,8 @@ <h3>Signatures</h3>

if (result) {
for (var i = 0; i < result.length; i++) {
var itemTypeName;
switch (result[i].itemType) {
case 'SignatureIngestor':
itemTypeName = "Signature import";
break;
case 'TitleIngestor':
itemTypeName = "Title import";
break;
case 'MetadataRefresh':
itemTypeName = "Metadata refresh"
break;
case 'OrganiseLibrary':
itemTypeName = "Organise library";
break;
case 'LibraryScan':
itemTypeName = "Library scan";
break;
case 'CollectionCompiler':
itemTypeName = "Compress collection id: " + result[i].options;
break;
case 'BackgroundDatabaseUpgrade':
itemTypeName = "Background database upgrade";
break;
default:
itemTypeName = result[i].itemType;
break;
}

var itemTypeName = GetTaskFriendlyName(result[i].itemType, result[i].options);

var itemStateName;
var itemLastStart;
if (result[i].isBlocked == false) {
Expand Down
21 changes: 21 additions & 0 deletions gaseous-server/wwwroot/scripts/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,4 +388,25 @@ function CreateBadge(BadgeText, ColourOverride) {
badgeItem.style.borderColor = ColourOverride;
}
return badgeItem;
}

function GetTaskFriendlyName(TaskName, options) {
switch (TaskName) {
case 'SignatureIngestor':
return "Signature import";
case 'TitleIngestor':
return "Title import";
case 'MetadataRefresh':
return "Metadata refresh";
case 'OrganiseLibrary':
return "Organise library";
case 'LibraryScan':
return "Library scan";
case 'CollectionCompiler':
return "Compress collection id: " + options;
case 'BackgroundDatabaseUpgrade':
return "Background database upgrade";
default:
return TaskName;
}
}

0 comments on commit b564edb

Please sign in to comment.