2021-05-13 20:03:07 +02:00
|
|
|
|
using Serilog;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
2021-06-26 20:57:55 +02:00
|
|
|
|
using TINK.Repository.Exception;
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
|
|
|
|
namespace TINK.ViewModel
|
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Object to periodically actuate an action.
|
|
|
|
|
/// </summary>
|
2021-05-13 20:03:07 +02:00
|
|
|
|
public class PollingUpdateTask
|
|
|
|
|
{
|
|
|
|
|
/// <summary> Object to control canelling. </summary>
|
2022-06-17 14:17:58 +02:00
|
|
|
|
private CancellationTokenSource CanellationTokenSource { get; }
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
|
|
|
|
/// <summary> Task to perform update. </summary>
|
2022-06-17 14:17:58 +02:00
|
|
|
|
private Task UpdateTask { get; }
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
|
|
|
|
/// <summary> Action which performs an update.</summary>
|
2022-06-17 14:17:58 +02:00
|
|
|
|
private Action UpdateAction { get; }
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
|
|
|
|
/// <summary> Obects which does a periodic update. </summary>
|
2022-06-17 14:17:58 +02:00
|
|
|
|
/// <param name="updateAction">Update action to perform.</param>
|
|
|
|
|
/// <param name="polling"> Holds whether to poll or not and the periode leght is polling is on. </param>
|
2021-05-13 20:03:07 +02:00
|
|
|
|
public PollingUpdateTask(
|
2022-06-17 14:17:58 +02:00
|
|
|
|
Action updateAction,
|
|
|
|
|
TimeSpan? polling)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
UpdateAction = updateAction
|
|
|
|
|
?? throw new ArgumentException($"Can not construct {GetType().Name}- obect. Argument {nameof(updateAction)} must not be null.");
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
if (!polling.HasValue)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// Automatic update is switched off.
|
|
|
|
|
Log.ForContext<PollingUpdateTask>().Debug($"Automatic update is off, context {GetType().Name} at {DateTime.Now}.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
var updatePeriodeSet = polling.Value;
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
CanellationTokenSource = new CancellationTokenSource();
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
int cycleIndex = 2;
|
|
|
|
|
UpdateTask = Task.Run(
|
2021-05-13 20:03:07 +02:00
|
|
|
|
async () =>
|
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
while (!CanellationTokenSource.IsCancellationRequested)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
await Task.Delay(updatePeriodeSet, CanellationTokenSource.Token);
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// N. update cycle
|
2022-06-17 14:17:58 +02:00
|
|
|
|
Log.ForContext<PollingUpdateTask>().Information($"Actuating {cycleIndex} update cycle, context {GetType().Name} at {DateTime.Now}.");
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
UpdateAction();
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
2022-06-17 14:17:58 +02:00
|
|
|
|
cycleIndex = cycleIndex < int.MaxValue ? ++cycleIndex : 0;
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-06-17 14:17:58 +02:00
|
|
|
|
CanellationTokenSource.Token);
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Invoked when pages is closed/ hidden.
|
|
|
|
|
/// Stops update process.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public async Task Terminate()
|
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
if (UpdateTask == null)
|
|
|
|
|
{
|
|
|
|
|
// Nothing to do if no task was created.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-13 20:03:07 +02:00
|
|
|
|
// Cancel update task;
|
2022-06-17 14:17:58 +02:00
|
|
|
|
if (CanellationTokenSource == null)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
throw new Exception($"Can not terminate periodical update task, context {GetType().Name} at {DateTime.Now}. No task running.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.Information($"Request to terminate update cycle, context {GetType().Name} at {DateTime.Now}.");
|
2022-06-17 14:17:58 +02:00
|
|
|
|
CanellationTokenSource.Cancel();
|
2021-05-13 20:03:07 +02:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
await UpdateTask;
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
catch (TaskCanceledException)
|
|
|
|
|
{
|
|
|
|
|
// Polling update was canceled.
|
|
|
|
|
// Nothing to notice/ worry about.
|
|
|
|
|
}
|
2022-06-17 14:17:58 +02:00
|
|
|
|
catch (Exception exception)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// An error occurred updating pin.
|
2022-06-17 14:17:58 +02:00
|
|
|
|
var aggregateException = exception as AggregateException;
|
|
|
|
|
if (aggregateException == null)
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// Unexpected exception detected. Exception should alyways be of type AggregateException
|
2022-06-17 14:17:58 +02:00
|
|
|
|
Log.Error("An/ several errors occurred on update task. {@Exceptions}.", exception);
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-06-17 14:17:58 +02:00
|
|
|
|
if (aggregateException.InnerExceptions.Count == 1
|
|
|
|
|
&& aggregateException.InnerExceptions[0].GetType() == typeof(TaskCanceledException))
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// Polling update was canceled.
|
|
|
|
|
// Nothing to notice/ worry about.
|
|
|
|
|
}
|
2022-06-17 14:17:58 +02:00
|
|
|
|
else if (aggregateException.InnerExceptions.Count() > 0 &&
|
|
|
|
|
aggregateException.InnerExceptions.First(x => !x.GetIsConnectFailureException()) == null) // There is no exception which is not of type connect failure.
|
2021-05-13 20:03:07 +02:00
|
|
|
|
{
|
|
|
|
|
// All exceptions were caused by communication error
|
2022-06-17 14:17:58 +02:00
|
|
|
|
Log.Information("An/ several web related connect failure exceptions occurred on update task. {@Exceptions}.", exception);
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// All exceptions were caused by communication errors.
|
2022-06-17 14:17:58 +02:00
|
|
|
|
Log.Error("An/ several exceptions occurred on update task. {@Exception}.", exception);
|
2021-05-13 20:03:07 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|