PiwigoDirectorySync/PiwigoDirectorySync/Commands/Scan/FileSystemScanner.cs

76 lines
2.7 KiB
C#

using System.Threading.Channels;
using NLog;
using PiwigoDirectorySync.Persistence;
namespace PiwigoDirectorySync.Commands.Scan;
public class FileSystemScanner
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
private readonly Channel<string> _fileQueue;
private readonly int _piwigoServerId;
public FileSystemScanner(Channel<string> fileQueue, int piwigoServerId)
{
_fileQueue = fileQueue ?? throw new ArgumentNullException(nameof(fileQueue));
_piwigoServerId = piwigoServerId;
}
public async Task ScanAsync(CancellationToken ct)
{
await using var db = new PersistenceContext();
var piwigoServer = await db.PiwigoServers.GetByIdAsync(_piwigoServerId, ct);
Logger.Info($"Scanning files for piwigo server {piwigoServer.Name} in directory {piwigoServer.RootDirectory}");
await ScanRootDirectory(new DirectoryInfo(piwigoServer.RootDirectory), ct);
}
private async ValueTask ScanRootDirectory(DirectoryInfo directory, CancellationToken ct)
{
Logger.Info($"Scanning root directory {directory.FullName} for sidecars to delete");
var parallelOptions = new ParallelOptions
{
CancellationToken = ct
};
await Parallel.ForEachAsync(GetDirectories(directory), parallelOptions, FindAndEnqueueFilesToAdd);
}
private async ValueTask FindAndEnqueueFilesToAdd(DirectoryInfo directory, CancellationToken ct)
{
try
{
Logger.Info($"Scanning directory {directory.FullName} for images");
var imageFiles = AppSettings.SupportedExtensions.SelectMany(ext => directory.GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly))
.Select(f => f.FullName)
.ToHashSet(StringComparer.OrdinalIgnoreCase);
if (!imageFiles.Any())
{
Logger.Debug($"No iamges in {directory.FullName} found, skipping");
return;
}
foreach (var imageFile in imageFiles.Select(f => new FileInfo(f)))
{
Logger.Debug($"Found image {imageFile.FullName}, enqueue index");
await _fileQueue.Writer.WriteAsync(imageFile.FullName, ct);
}
}
catch (Exception ex)
{
Logger.Error(ex, $"could not scan directory {directory.FullName}");
}
}
private static IEnumerable<DirectoryInfo> GetDirectories(DirectoryInfo directoryInfo)
{
yield return directoryInfo;
foreach (var directory in directoryInfo.EnumerateDirectories().SelectMany(GetDirectories))
{
yield return directory;
}
}
}