fixes id of image on download and adds cancellation support for spectre commands
All checks were successful
PiwigoDirectorySync/pipeline/head This commit looks good

This commit is contained in:
Philipp Häfelfinger 2023-09-04 23:12:18 +02:00
parent 96bce7c83a
commit d43235bca1
9 changed files with 75 additions and 25 deletions

View File

@ -1,11 +1,12 @@
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Commands; namespace PiwigoDirectorySync.Commands;
internal class DownloadImagesCommand : AsyncCommand<DownloadImagesSettings> internal class DownloadImagesCommand : CancellableAsyncCommand<DownloadImagesSettings>
{ {
private readonly IImageSynchronizer _imageSynchronizer; private readonly IImageSynchronizer _imageSynchronizer;
private readonly ILogger<DownloadImagesCommand> _logger; private readonly ILogger<DownloadImagesCommand> _logger;
@ -16,13 +17,12 @@ internal class DownloadImagesCommand : AsyncCommand<DownloadImagesSettings>
_logger = logger; _logger = logger;
} }
public override async Task<int> ExecuteAsync(CommandContext context, DownloadImagesSettings settings) protected override async Task<int> ExecuteAsync(CommandContext context, DownloadImagesSettings settings, CancellationToken cancellationToken)
{ {
_logger.LogInformation("Starting image download for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId); _logger.LogInformation("Starting image download for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId);
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var cancellationTokenSource = new CancellationTokenSource(); await _imageSynchronizer.DownloadImagesAsync(settings.PiwigoServerId, cancellationToken);
await _imageSynchronizer.DownloadImagesAsync(settings.PiwigoServerId, cancellationTokenSource.Token);
stopWatch.Stop(); stopWatch.Stop();
_logger.LogInformation("Synchronized all images with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId, _logger.LogInformation("Synchronized all images with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId,

View File

@ -1,12 +1,13 @@
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Channels; using System.Threading.Channels;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Commands; namespace PiwigoDirectorySync.Commands;
internal class ScanCommand : AsyncCommand<ScanSettings> internal class ScanCommand : CancellableAsyncCommand<ScanSettings>
{ {
private readonly IFileIndexer _fileIndexer; private readonly IFileIndexer _fileIndexer;
private readonly IFileSystemScanner _fileSystemScanner; private readonly IFileSystemScanner _fileSystemScanner;
@ -19,11 +20,9 @@ internal class ScanCommand : AsyncCommand<ScanSettings>
_fileSystemScanner = fileSystemScanner; _fileSystemScanner = fileSystemScanner;
} }
public override async Task<int> ExecuteAsync(CommandContext context, ScanSettings settings) protected override async Task<int> ExecuteAsync(CommandContext context, ScanSettings settings, CancellationToken cancellationToken)
{ {
var cancellationTokenSource = new CancellationTokenSource(); await ScanDirectory(_logger, _fileIndexer, _fileSystemScanner, settings.PiwigoServerId, cancellationToken);
await ScanDirectory(_logger, _fileIndexer, _fileSystemScanner, settings.PiwigoServerId, cancellationTokenSource.Token);
return 0; return 0;
} }

View File

@ -1,11 +1,12 @@
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Commands; namespace PiwigoDirectorySync.Commands;
internal class SyncAlbumsCommand : AsyncCommand<SyncAlbumsSettings> internal class SyncAlbumsCommand : CancellableAsyncCommand<SyncAlbumsSettings>
{ {
private readonly IAlbumSynchronizer _albumSynchronizer; private readonly IAlbumSynchronizer _albumSynchronizer;
private readonly ILogger<SyncAlbumsCommand> _logger; private readonly ILogger<SyncAlbumsCommand> _logger;
@ -16,14 +17,13 @@ internal class SyncAlbumsCommand : AsyncCommand<SyncAlbumsSettings>
_albumSynchronizer = albumSynchronizer; _albumSynchronizer = albumSynchronizer;
} }
public override async Task<int> ExecuteAsync(CommandContext context, SyncAlbumsSettings settings) protected override async Task<int> ExecuteAsync(CommandContext context, SyncAlbumsSettings settings, CancellationToken cancellationToken)
{ {
_logger.LogInformation("Starting album synchronization for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId); _logger.LogInformation("Starting album synchronization for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId);
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var cancellationTokenSource = new CancellationTokenSource(); await _albumSynchronizer.SynchronizeAlbums(settings.PiwigoServerId, cancellationToken);
await _albumSynchronizer.SynchronizeAlbums(settings.PiwigoServerId, cancellationTokenSource.Token);
stopWatch.Stop(); stopWatch.Stop();
_logger.LogInformation("Synchronized all albums with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId, _logger.LogInformation("Synchronized all albums with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId,

View File

@ -1,11 +1,12 @@
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Commands; namespace PiwigoDirectorySync.Commands;
internal class SyncFullCommand : AsyncCommand<SyncFullSettings> internal class SyncFullCommand : CancellableAsyncCommand<SyncFullSettings>
{ {
private readonly IAlbumSynchronizer _albumSynchronizer; private readonly IAlbumSynchronizer _albumSynchronizer;
private readonly IFileIndexer _fileIndexer; private readonly IFileIndexer _fileIndexer;
@ -23,21 +24,19 @@ internal class SyncFullCommand : AsyncCommand<SyncFullSettings>
_logger = logger; _logger = logger;
} }
public override async Task<int> ExecuteAsync(CommandContext context, SyncFullSettings settings) protected override async Task<int> ExecuteAsync(CommandContext context, SyncFullSettings settings, CancellationToken cancellationToken)
{ {
_logger.LogInformation("Starting full synchronization for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId); _logger.LogInformation("Starting full synchronization for piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId);
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var cancellationTokenSource = new CancellationTokenSource();
_logger.LogInformation("running file system scan"); _logger.LogInformation("running file system scan");
await ScanCommand.ScanDirectory(_logger, _fileIndexer, _fileSystemScanner, settings.PiwigoServerId, cancellationTokenSource.Token); await ScanCommand.ScanDirectory(_logger, _fileIndexer, _fileSystemScanner, settings.PiwigoServerId, cancellationToken);
_logger.LogInformation("running album synchronization"); _logger.LogInformation("running album synchronization");
await _albumSynchronizer.SynchronizeAlbums(settings.PiwigoServerId, cancellationTokenSource.Token); await _albumSynchronizer.SynchronizeAlbums(settings.PiwigoServerId, cancellationToken);
_logger.LogInformation("running image synchronization"); _logger.LogInformation("running image synchronization");
await _imageSynchronizer.SynchronizeImagesAsync(settings.PiwigoServerId, cancellationTokenSource.Token); await _imageSynchronizer.SynchronizeImagesAsync(settings.PiwigoServerId, cancellationToken);
stopWatch.Stop(); stopWatch.Stop();
_logger.LogInformation("Full synchronization for piwigo server {SettingsPiwigoServerId} finished in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId, _logger.LogInformation("Full synchronization for piwigo server {SettingsPiwigoServerId} finished in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId,

View File

@ -1,11 +1,12 @@
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Commands; namespace PiwigoDirectorySync.Commands;
internal class SyncImagesCommand : AsyncCommand<SyncImagesSettings> internal class SyncImagesCommand : CancellableAsyncCommand<SyncImagesSettings>
{ {
private readonly IImageSynchronizer _imageSynchronizer; private readonly IImageSynchronizer _imageSynchronizer;
private readonly ILogger<SyncImagesCommand> _logger; private readonly ILogger<SyncImagesCommand> _logger;
@ -16,13 +17,12 @@ internal class SyncImagesCommand : AsyncCommand<SyncImagesSettings>
_imageSynchronizer = imageSynchronizer; _imageSynchronizer = imageSynchronizer;
} }
public override async Task<int> ExecuteAsync(CommandContext context, SyncImagesSettings settings) protected override async Task<int> ExecuteAsync(CommandContext context, SyncImagesSettings settings, CancellationToken cancellationToken)
{ {
_logger.LogInformation("Starting image synchronization of piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId); _logger.LogInformation("Starting image synchronization of piwigo server {SettingsPiwigoServerId}", settings.PiwigoServerId);
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var cancellationTokenSource = new CancellationTokenSource(); await _imageSynchronizer.SynchronizeImagesAsync(settings.PiwigoServerId, cancellationToken);
await _imageSynchronizer.SynchronizeImagesAsync(settings.PiwigoServerId, cancellationTokenSource.Token);
stopWatch.Stop(); stopWatch.Stop();
_logger.LogInformation("Synchronized all images with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId, _logger.LogInformation("Synchronized all images with piwigo server {SettingsPiwigoServerId} in {ElapsedTotalSeconds} seconds", settings.PiwigoServerId,

View File

@ -0,0 +1,12 @@
using Spectre.Console.Cli;
namespace PiwigoDirectorySync.Infrastructure;
public abstract class CancellableAsyncCommand<TSettings> : AsyncCommand<TSettings> where TSettings : CommandSettings
{
private readonly ConsoleAppCancellationTokenSource _cancellationTokenSource = new();
protected abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellation);
public sealed override async Task<int> ExecuteAsync(CommandContext context, TSettings settings) => await ExecuteAsync(context, settings, _cancellationTokenSource.Token);
}

View File

@ -0,0 +1,39 @@
namespace PiwigoDirectorySync.Infrastructure;
internal sealed class ConsoleAppCancellationTokenSource
{
private readonly CancellationTokenSource _cts = new();
public ConsoleAppCancellationTokenSource()
{
Console.CancelKeyPress += OnCancelKeyPress;
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
using var _ = _cts.Token.Register(() =>
{
AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
Console.CancelKeyPress -= OnCancelKeyPress;
});
}
public CancellationToken Token => _cts.Token;
private void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e)
{
// NOTE: cancel event, don't terminate the process
e.Cancel = true;
_cts.Cancel();
}
private void OnProcessExit(object? sender, EventArgs e)
{
if (_cts.IsCancellationRequested)
{
// NOTE: SIGINT (cancel key was pressed, this shouldn't ever actually hit however,
// as we remove the event handler upon cancellation of the `cancellationSource`)
return;
}
_cts.Cancel();
}
}

View File

@ -54,4 +54,4 @@ app.Configure(config =>
}); });
}); });
return app.Run(args); return await app.RunAsync(args);

View File

@ -127,6 +127,7 @@ internal class ImageSynchronizer : IImageSynchronizer
{ {
AlbumId = album.Id, AlbumId = album.Id,
Album = album, Album = album,
ServerImageId = image.Id,
FilePath = Path.Combine(album.Path, image.File!), FilePath = Path.Combine(album.Path, image.File!),
UploadRequired = false, UploadRequired = false,
DeleteRequired = false DeleteRequired = false