2020-04-02 18:27:55 +00:00
|
|
|
|
using BirthdayBot.BackgroundServices;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace BirthdayBot
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the execution of periodic background tasks.
|
|
|
|
|
/// </summary>
|
|
|
|
|
class BackgroundServiceRunner
|
|
|
|
|
{
|
2020-04-04 03:26:18 +00:00
|
|
|
|
// Amount of idle time between each round of task execution, in seconds.
|
2020-05-22 04:17:38 +00:00
|
|
|
|
#if DEBUG
|
|
|
|
|
// Amount of idle time between each round of task execution, in seconds.
|
|
|
|
|
const int Interval = 10;
|
|
|
|
|
|
|
|
|
|
// Amount of time between start and first round of processing, in seconds.
|
|
|
|
|
const int StartDelay = 15;
|
|
|
|
|
#else
|
|
|
|
|
// Amount of idle time between each round of task execution, in seconds.
|
2020-04-04 03:26:18 +00:00
|
|
|
|
const int Interval = 8 * 60;
|
2020-05-22 04:17:38 +00:00
|
|
|
|
|
2020-04-04 03:26:18 +00:00
|
|
|
|
// Amount of time between start and first round of processing, in seconds.
|
|
|
|
|
const int StartDelay = 60;
|
2020-05-22 04:17:38 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2020-04-04 03:26:18 +00:00
|
|
|
|
|
|
|
|
|
const string LogName = nameof(BackgroundServiceRunner);
|
2020-04-02 18:27:55 +00:00
|
|
|
|
|
|
|
|
|
private List<BackgroundService> _workers;
|
|
|
|
|
private readonly CancellationTokenSource _workerCancel;
|
|
|
|
|
private Task _workerTask;
|
|
|
|
|
|
|
|
|
|
internal BirthdayRoleUpdate BirthdayUpdater { get; }
|
|
|
|
|
|
|
|
|
|
public BackgroundServiceRunner(BirthdayBot instance)
|
|
|
|
|
{
|
|
|
|
|
_workerCancel = new CancellationTokenSource();
|
|
|
|
|
BirthdayUpdater = new BirthdayRoleUpdate(instance);
|
|
|
|
|
_workers = new List<BackgroundService>()
|
|
|
|
|
{
|
|
|
|
|
{new GuildStatistics(instance)},
|
|
|
|
|
{new Heartbeat(instance)},
|
|
|
|
|
{BirthdayUpdater}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Start()
|
|
|
|
|
{
|
|
|
|
|
_workerTask = Task.Factory.StartNew(WorkerLoop, _workerCancel.Token,
|
|
|
|
|
TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Cancel()
|
|
|
|
|
{
|
|
|
|
|
_workerCancel.Cancel();
|
|
|
|
|
await _workerTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// *The* background task. Executes service tasks and handles errors.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private async Task WorkerLoop()
|
|
|
|
|
{
|
2020-04-04 03:26:18 +00:00
|
|
|
|
// Start an initial delay before tasks begin running
|
|
|
|
|
Program.Log(LogName, $"Delaying first background execution by {StartDelay} seconds.");
|
|
|
|
|
try { await Task.Delay(StartDelay * 1000, _workerCancel.Token); }
|
|
|
|
|
catch (TaskCanceledException) { return; }
|
2020-04-02 18:27:55 +00:00
|
|
|
|
while (!_workerCancel.IsCancellationRequested)
|
|
|
|
|
{
|
2020-04-04 03:26:18 +00:00
|
|
|
|
// Initiate background tasks
|
|
|
|
|
var tasks = new List<Task>();
|
|
|
|
|
foreach (var service in _workers) tasks.Add(service.OnTick());
|
|
|
|
|
var alltasks = Task.WhenAll(tasks);
|
2020-04-02 18:27:55 +00:00
|
|
|
|
|
2020-04-04 03:26:18 +00:00
|
|
|
|
// Await and check result
|
|
|
|
|
// Cancellation token not checked at this point...
|
|
|
|
|
try
|
2020-04-02 18:27:55 +00:00
|
|
|
|
{
|
2020-04-04 03:26:18 +00:00
|
|
|
|
await alltasks;
|
2020-04-02 18:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2020-04-04 03:26:18 +00:00
|
|
|
|
var exs = alltasks.Exception;
|
|
|
|
|
if (exs != null)
|
|
|
|
|
{
|
|
|
|
|
Program.Log(LogName, $"{exs.InnerExceptions.Count} exception(s) during background task execution:");
|
2020-05-22 07:27:31 +00:00
|
|
|
|
// TODO webhook log
|
2020-04-04 03:26:18 +00:00
|
|
|
|
foreach (var iex in exs.InnerExceptions)
|
|
|
|
|
{
|
2020-05-22 07:27:31 +00:00
|
|
|
|
Program.Log(LogName, iex.ToString());
|
2020-04-04 03:26:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Program.Log(LogName, ex.ToString());
|
|
|
|
|
}
|
2020-04-02 18:27:55 +00:00
|
|
|
|
}
|
2020-04-04 03:26:18 +00:00
|
|
|
|
|
|
|
|
|
try { await Task.Delay(Interval * 1000, _workerCancel.Token); }
|
|
|
|
|
catch (TaskCanceledException) { return; }
|
2020-04-02 18:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|