moves db context to injection

This commit is contained in:
Philipp Häfelfinger 2023-09-02 12:03:29 +02:00
parent f705babdc3
commit 647a1e44bd
6 changed files with 62 additions and 54 deletions

View File

@ -4,22 +4,11 @@ namespace PiwigoDirectorySync.Persistence;
public class PersistenceContext : DbContext public class PersistenceContext : DbContext
{ {
public PersistenceContext(DbContextOptions<PersistenceContext> options) : base(options)
{
}
public DbSet<ServerEntity> PiwigoServers { get; set; } = null!; public DbSet<ServerEntity> PiwigoServers { get; set; } = null!;
public DbSet<AlbumEntity> PiwigoAlbums { get; set; } = null!; public DbSet<AlbumEntity> PiwigoAlbums { get; set; } = null!;
public DbSet<ImageEntity> PiwigoImages { get; set; } = null!; public DbSet<ImageEntity> PiwigoImages { get; set; } = null!;
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
switch (AppSettings.Settings.DbProvider)
{
case "Sqlite":
options.UseSqlite(AppSettings.ConnectionString);
break;
case "InMemory":
options.UseInMemoryDatabase(AppSettings.ConnectionString);
break;
default:
throw new InvalidOperationException($"DbProvider {AppSettings.Settings.DbProvider} is not supported");
}
}
} }

View File

@ -1,7 +1,10 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PiwigoDirectorySync;
using PiwigoDirectorySync.Commands; using PiwigoDirectorySync.Commands;
using PiwigoDirectorySync.Infrastructure; using PiwigoDirectorySync.Infrastructure;
using PiwigoDirectorySync.Persistence;
using PiwigoDirectorySync.Services; using PiwigoDirectorySync.Services;
using Spectre.Console.Cli; using Spectre.Console.Cli;
@ -18,6 +21,15 @@ registrations.AddTransient<IFileIndexer, FileIndexer>();
registrations.AddTransient<IFileSystemScanner, FileSystemScanner>(); registrations.AddTransient<IFileSystemScanner, FileSystemScanner>();
registrations.AddTransient<IAlbumSynchronizer, AlbumSynchronizer>(); registrations.AddTransient<IAlbumSynchronizer, AlbumSynchronizer>();
registrations.AddTransient<IImageSynchronizer, ImageSynchronizer>(); registrations.AddTransient<IImageSynchronizer, ImageSynchronizer>();
registrations.AddDbContext<PersistenceContext>(options =>
{
_ = AppSettings.Settings.DbProvider switch
{
"Sqlite" => options.UseSqlite(AppSettings.ConnectionString),
"InMemory" => options.UseInMemoryDatabase(AppSettings.ConnectionString),
_ => throw new Exception($"Unsupported dbType: {AppSettings.Settings.DbProvider}")
};
});
var registrar = new DependencyInjectionTypeRegistrar(registrations); var registrar = new DependencyInjectionTypeRegistrar(registrations);

View File

@ -10,18 +10,19 @@ namespace PiwigoDirectorySync.Services;
public class AlbumSynchronizer : IAlbumSynchronizer public class AlbumSynchronizer : IAlbumSynchronizer
{ {
private readonly ILogger<AlbumSynchronizer> _logger; private readonly ILogger<AlbumSynchronizer> _logger;
private readonly PersistenceContext _persistenceContext;
private readonly IPiwigoClientFactory _piwigoClientFactory; private readonly IPiwigoClientFactory _piwigoClientFactory;
public AlbumSynchronizer(ILogger<AlbumSynchronizer> logger, IPiwigoClientFactory piwigoClientFactory) public AlbumSynchronizer(ILogger<AlbumSynchronizer> logger, IPiwigoClientFactory piwigoClientFactory, PersistenceContext persistenceContext)
{ {
_logger = logger; _logger = logger;
_piwigoClientFactory = piwigoClientFactory; _piwigoClientFactory = piwigoClientFactory;
_persistenceContext = persistenceContext;
} }
public async Task SynchronizeAlbums(int piwigoServerId, CancellationToken ct) public async Task SynchronizeAlbums(int piwigoServerId, CancellationToken ct)
{ {
await using var dbContext = new PersistenceContext(); var piwigoServer = await _persistenceContext.PiwigoServers.FindAsync(new object?[] { piwigoServerId }, ct);
var piwigoServer = await dbContext.PiwigoServers.FindAsync(new object?[] { piwigoServerId }, ct);
if (piwigoServer is null) if (piwigoServer is null)
{ {
_logger.LogError("Could not sync albums with piwigo server {PiwigoServerId}", piwigoServerId); _logger.LogError("Could not sync albums with piwigo server {PiwigoServerId}", piwigoServerId);
@ -30,30 +31,30 @@ public class AlbumSynchronizer : IAlbumSynchronizer
var piwigoClient = await _piwigoClientFactory.GetPiwigoClientAsync(piwigoServer, ct); var piwigoClient = await _piwigoClientFactory.GetPiwigoClientAsync(piwigoServer, ct);
await UpdatePiwigoAlbumsFromServerAsync(dbContext, piwigoClient, piwigoServer, ct); await UpdatePiwigoAlbumsFromServerAsync(piwigoClient, piwigoServer, ct);
await AddMissingAlbumsToServerAsync(dbContext, piwigoClient, piwigoServer, ct); await AddMissingAlbumsToServerAsync(piwigoClient, piwigoServer, ct);
} }
private static async Task AddMissingAlbumsToServerAsync(PersistenceContext dbContext, IPiwigoClient piwigoClient, ServerEntity piwigoServer, CancellationToken ct) private async Task AddMissingAlbumsToServerAsync(IPiwigoClient piwigoClient, ServerEntity piwigoServer, CancellationToken ct)
{ {
var albumsToCreate = await dbContext.PiwigoAlbums.Where(a => a.ServerAlbumId == null && a.ServerId == piwigoServer.Id) var albumsToCreate = await _persistenceContext.PiwigoAlbums.Where(a => a.ServerAlbumId == null && a.ServerId == piwigoServer.Id)
.OrderBy(a => a.Path) .OrderBy(a => a.Path)
.Select(a => a.Id) .Select(a => a.Id)
.ToListAsync(ct); .ToListAsync(ct);
foreach (var albumId in albumsToCreate) foreach (var albumId in albumsToCreate)
{ {
var albumEntity = await dbContext.PiwigoAlbums.GetByIdAsync(albumId, ct); var albumEntity = await _persistenceContext.PiwigoAlbums.GetByIdAsync(albumId, ct);
var piwigoParentId = albumEntity.ParentId.HasValue ? (await dbContext.PiwigoAlbums.GetByIdAsync(albumEntity.ParentId.Value, ct)).ServerAlbumId : null; var piwigoParentId = albumEntity.ParentId.HasValue ? (await _persistenceContext.PiwigoAlbums.GetByIdAsync(albumEntity.ParentId.Value, ct)).ServerAlbumId : null;
albumEntity.ServerAlbumId = await piwigoClient.Album.AddAsync(albumEntity.Name, piwigoParentId, visible: true, position: AlbumPosition.First, albumEntity.ServerAlbumId = await piwigoClient.Album.AddAsync(albumEntity.Name, piwigoParentId, visible: true, position: AlbumPosition.First,
status: AlbumStatus.Public, cancellationToken: ct); status: AlbumStatus.Public, cancellationToken: ct);
await dbContext.SaveChangesAsync(ct); await _persistenceContext.SaveChangesAsync(ct);
} }
} }
private async Task UpdatePiwigoAlbumsFromServerAsync(PersistenceContext dbContext, IPiwigoClient piwigoClient, ServerEntity piwigoServer, CancellationToken ct) private async Task UpdatePiwigoAlbumsFromServerAsync(IPiwigoClient piwigoClient, ServerEntity piwigoServer, CancellationToken ct)
{ {
var serverAlbums = await piwigoClient.Album.GetListAsync(null, true, false, ThumbnailSize.Thumb, ct); var serverAlbums = await piwigoClient.Album.GetListAsync(null, true, false, ThumbnailSize.Thumb, ct);
var serverAlbumDictionary = serverAlbums.ToDictionary(a => a.Id, a => a); var serverAlbumDictionary = serverAlbums.ToDictionary(a => a.Id, a => a);
@ -62,21 +63,21 @@ public class AlbumSynchronizer : IAlbumSynchronizer
{ {
_logger.LogInformation("Updating piwigo server album {ServerAlbumName} with piwigo id {ServerAlbumId}", serverAlbum.Name, serverAlbum.Id); _logger.LogInformation("Updating piwigo server album {ServerAlbumName} with piwigo id {ServerAlbumId}", serverAlbum.Name, serverAlbum.Id);
var albumEntity = await GetOrAddPiwigoAlbumEntityFromServerAsync(dbContext, piwigoServer, serverAlbum, serverAlbumDictionary, ct); var albumEntity = await GetOrAddPiwigoAlbumEntityFromServerAsync(piwigoServer, serverAlbum, serverAlbumDictionary, ct);
if (serverAlbum.IdUpperCat.HasValue) if (serverAlbum.IdUpperCat.HasValue)
{ {
albumEntity.ParentId = (await dbContext.PiwigoAlbums.FindByServerIdAsync(piwigoServer.Id, serverAlbum.IdUpperCat.Value, ct))?.Id; albumEntity.ParentId = (await _persistenceContext.PiwigoAlbums.FindByServerIdAsync(piwigoServer.Id, serverAlbum.IdUpperCat.Value, ct))?.Id;
} }
await dbContext.SaveChangesAsync(ct); await _persistenceContext.SaveChangesAsync(ct);
} }
} }
private async Task<AlbumEntity> GetOrAddPiwigoAlbumEntityFromServerAsync(PersistenceContext dbContext, ServerEntity piwigoServer, Album serverAlbum, private async Task<AlbumEntity> GetOrAddPiwigoAlbumEntityFromServerAsync(ServerEntity piwigoServer, Album serverAlbum, IDictionary<int, Album> serverAlbumDictionary,
IDictionary<int, Album> serverAlbumDictionary, CancellationToken ct) CancellationToken ct)
{ {
// Already synchronized so it is easy to return // Already synchronized so it is easy to return
var albumEntity = await dbContext.PiwigoAlbums.FindByServerIdAsync(piwigoServer.Id, serverAlbum.Id, ct); var albumEntity = await _persistenceContext.PiwigoAlbums.FindByServerIdAsync(piwigoServer.Id, serverAlbum.Id, ct);
if (albumEntity != null) if (albumEntity != null)
{ {
_logger.LogDebug("Found existing album {AlbumEntityName} with local id {AlbumEntityId} and piwigo server id {ServerAlbumId}", albumEntity.Name, albumEntity.Id, _logger.LogDebug("Found existing album {AlbumEntityName} with local id {AlbumEntityId} and piwigo server id {ServerAlbumId}", albumEntity.Name, albumEntity.Id,
@ -87,7 +88,7 @@ public class AlbumSynchronizer : IAlbumSynchronizer
// might exist already as the file system got scanned and created the local entries // might exist already as the file system got scanned and created the local entries
// In this case we save the server id in our local album and link them. // In this case we save the server id in our local album and link them.
var path = GeneratePath(serverAlbum, serverAlbumDictionary); var path = GeneratePath(serverAlbum, serverAlbumDictionary);
albumEntity = await dbContext.PiwigoAlbums.FindByServerAndPathAsync(piwigoServer.Id, path, ct); albumEntity = await _persistenceContext.PiwigoAlbums.FindByServerAndPathAsync(piwigoServer.Id, path, ct);
if (albumEntity != null) if (albumEntity != null)
{ {
albumEntity.ServerAlbumId = serverAlbum.Id; albumEntity.ServerAlbumId = serverAlbum.Id;
@ -106,7 +107,7 @@ public class AlbumSynchronizer : IAlbumSynchronizer
}; };
_logger.LogInformation("Adding piwigo album {AlbumEntityName} with local id {AlbumEntityId} and piwigo server id {ServerAlbumId}", albumEntity.Name, albumEntity.Id, _logger.LogInformation("Adding piwigo album {AlbumEntityName} with local id {AlbumEntityId} and piwigo server id {ServerAlbumId}", albumEntity.Name, albumEntity.Id,
albumEntity.ServerAlbumId); albumEntity.ServerAlbumId);
dbContext.PiwigoAlbums.Add(albumEntity); _persistenceContext.PiwigoAlbums.Add(albumEntity);
return albumEntity; return albumEntity;
} }

View File

@ -10,10 +10,12 @@ public class FileIndexer : IFileIndexer
{ {
private readonly IList<string> _failedFiles = new List<string>(); private readonly IList<string> _failedFiles = new List<string>();
private readonly ILogger<FileIndexer> _logger; private readonly ILogger<FileIndexer> _logger;
private readonly PersistenceContext _persistenceContext;
public FileIndexer(ILogger<FileIndexer> logger) public FileIndexer(ILogger<FileIndexer> logger, PersistenceContext persistenceContext)
{ {
_logger = logger; _logger = logger;
_persistenceContext = persistenceContext;
} }
public int TotalFilesScanned { get; private set; } public int TotalFilesScanned { get; private set; }
@ -21,8 +23,7 @@ public class FileIndexer : IFileIndexer
public async Task StartProcessingAsync(Channel<string> fileQueue, int piwigoServerId, CancellationToken ct) public async Task StartProcessingAsync(Channel<string> fileQueue, int piwigoServerId, CancellationToken ct)
{ {
await using var db = new PersistenceContext(); var piwigoServer = await _persistenceContext.PiwigoServers.GetByIdAsync(piwigoServerId, ct);
var piwigoServer = await db.PiwigoServers.GetByIdAsync(piwigoServerId, ct);
await foreach (var fullFilePath in fileQueue.Reader.ReadAllAsync(ct)) await foreach (var fullFilePath in fileQueue.Reader.ReadAllAsync(ct))
{ {
@ -46,9 +47,9 @@ public class FileIndexer : IFileIndexer
var relativePath = Path.GetRelativePath(piwigoServer.RootDirectory, fullFilePath); var relativePath = Path.GetRelativePath(piwigoServer.RootDirectory, fullFilePath);
var album = await GetOrAddAlbumAsync(db, piwigoServer, fileInfo.Directory!, ct); var album = await GetOrAddAlbumAsync(piwigoServer, fileInfo.Directory!, ct);
var image = await GetOrAddImageAsync(db, album, relativePath, ct); var image = await GetOrAddImageAsync(album, relativePath, ct);
if (image.LastChange != fileInfo.LastWriteTimeUtc) if (image.LastChange != fileInfo.LastWriteTimeUtc)
{ {
@ -59,7 +60,7 @@ public class FileIndexer : IFileIndexer
image.DeleteRequired = false; image.DeleteRequired = false;
image.LastChange = fileInfo.LastWriteTimeUtc; image.LastChange = fileInfo.LastWriteTimeUtc;
await db.SaveChangesAsync(ct); await _persistenceContext.SaveChangesAsync(ct);
TotalFilesScanned++; TotalFilesScanned++;
} }
@ -71,9 +72,9 @@ public class FileIndexer : IFileIndexer
} }
} }
private static async Task<ImageEntity> GetOrAddImageAsync(PersistenceContext db, AlbumEntity album, string relativePath, CancellationToken ct) private async Task<ImageEntity> GetOrAddImageAsync(AlbumEntity album, string relativePath, CancellationToken ct)
{ {
var imageEntity = await db.PiwigoImages.Where(i => i.AlbumId == album.Id && i.FilePath == relativePath).FirstOrDefaultAsync(ct); var imageEntity = await _persistenceContext.PiwigoImages.Where(i => i.AlbumId == album.Id && i.FilePath == relativePath).FirstOrDefaultAsync(ct);
if (imageEntity is null) if (imageEntity is null)
{ {
imageEntity = new ImageEntity imageEntity = new ImageEntity
@ -84,16 +85,16 @@ public class FileIndexer : IFileIndexer
UploadRequired = true, UploadRequired = true,
DeleteRequired = false DeleteRequired = false
}; };
db.PiwigoImages.Add(imageEntity); _persistenceContext.PiwigoImages.Add(imageEntity);
} }
return imageEntity; return imageEntity;
} }
private async Task<AlbumEntity> GetOrAddAlbumAsync(PersistenceContext db, ServerEntity server, DirectoryInfo directory, CancellationToken ct) private async Task<AlbumEntity> GetOrAddAlbumAsync(ServerEntity server, DirectoryInfo directory, CancellationToken ct)
{ {
var albumPath = Path.GetRelativePath(server.RootDirectory, directory.FullName); var albumPath = Path.GetRelativePath(server.RootDirectory, directory.FullName);
var album = await db.PiwigoAlbums.FindByServerAndPathAsync(server.Id, albumPath, ct); var album = await _persistenceContext.PiwigoAlbums.FindByServerAndPathAsync(server.Id, albumPath, ct);
if (album != null) if (album != null)
{ {
return album; return album;
@ -106,7 +107,7 @@ public class FileIndexer : IFileIndexer
} }
else else
{ {
parentAlbum = await GetOrAddAlbumAsync(db, server, directory.Parent!, ct); parentAlbum = await GetOrAddAlbumAsync(server, directory.Parent!, ct);
} }
album = new AlbumEntity album = new AlbumEntity
@ -118,9 +119,9 @@ public class FileIndexer : IFileIndexer
ParentId = parentAlbum?.Id, ParentId = parentAlbum?.Id,
Parent = parentAlbum Parent = parentAlbum
}; };
db.PiwigoAlbums.Add(album); _persistenceContext.PiwigoAlbums.Add(album);
await db.SaveChangesAsync(ct); await _persistenceContext.SaveChangesAsync(ct);
return album; return album;
} }

View File

@ -7,18 +7,18 @@ namespace PiwigoDirectorySync.Services;
public class FileSystemScanner : IFileSystemScanner public class FileSystemScanner : IFileSystemScanner
{ {
private readonly ILogger<FileSystemScanner> _logger; private readonly ILogger<FileSystemScanner> _logger;
private readonly PersistenceContext _persistenceContext;
public FileSystemScanner(ILogger<FileSystemScanner> logger) public FileSystemScanner(ILogger<FileSystemScanner> logger, PersistenceContext persistenceContext)
{ {
_logger = logger; _logger = logger;
_persistenceContext = persistenceContext;
} }
public async Task ScanAsync(Channel<string> fileQueue, int piwigoServerId, CancellationToken ct) public async Task ScanAsync(Channel<string> fileQueue, int piwigoServerId, CancellationToken ct)
{ {
await using var db = new PersistenceContext(); var piwigoServer = await _persistenceContext.PiwigoServers.GetByIdAsync(piwigoServerId, ct);
var piwigoServer = await db.PiwigoServers.GetByIdAsync(piwigoServerId, ct);
_logger.LogInformation("Scanning files for piwigo server {PiwigoServerName} in directory {PiwigoServerRootDirectory}", piwigoServer.Name, piwigoServer.RootDirectory); _logger.LogInformation("Scanning files for piwigo server {PiwigoServerName} in directory {PiwigoServerRootDirectory}", piwigoServer.Name, piwigoServer.RootDirectory);
await ScanRootDirectory(fileQueue, new DirectoryInfo(piwigoServer.RootDirectory), ct); await ScanRootDirectory(fileQueue, new DirectoryInfo(piwigoServer.RootDirectory), ct);

View File

@ -2,5 +2,10 @@
public class ImageSynchronizer : IImageSynchronizer public class ImageSynchronizer : IImageSynchronizer
{ {
public Task SynchronizeImages(int piwigoServerId, CancellationToken ct) => throw new NotImplementedException(); public Task SynchronizeImages(int piwigoServerId, CancellationToken ct)
{
throw new NotImplementedException();
}
} }