From d34a6fd75a0aef2875fd5cd820aa876e573cb5b1 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 11 Jun 2020 16:46:17 +0200 Subject: [PATCH] Starting to implement a dispose pattern for the library manager/repositories --- Kyoo.Common/Controllers/ILibraryManager.cs | 5 ++-- Kyoo.Common/Controllers/IRepository.cs | 3 +- .../Exceptions/DuplicatedItemException.cs | 14 +++++++++ Kyoo/Controllers/LibraryManager.cs | 22 ++++++++++++++ .../Repositories/CollectionRepository.cs | 29 ++++++++++++++++--- Kyoo/Tasks/Crawler.cs | 18 +++++++----- 6 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index c345bf38..72c211ae 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -1,11 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using JetBrains.Annotations; using Kyoo.Models; namespace Kyoo.Controllers { - public interface ILibraryManager + public interface ILibraryManager : IDisposable, IAsyncDisposable { // Get by slug Task GetLibrary(string slug); diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 0993ca69..e1587908 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using JetBrains.Annotations; @@ -5,7 +6,7 @@ using Kyoo.Models; namespace Kyoo.Controllers { - public interface IRepository + public interface IRepository : IDisposable, IAsyncDisposable { Task Get(int id); Task Get(string slug); diff --git a/Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs b/Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs new file mode 100644 index 00000000..c8836c0d --- /dev/null +++ b/Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Kyoo.Models.Exceptions +{ + public class DuplicatedItemException : Exception + { + public override string Message { get; } + + public DuplicatedItemException(string message) + { + Message = message; + } + } +} \ No newline at end of file diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index c4f1432a..726675ce 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -40,6 +40,28 @@ namespace Kyoo.Controllers _providers = providers; _people = people; } + + public void Dispose() + { + _libraries?.Dispose(); + _collections?.Dispose(); + _shows?.Dispose(); + _seasons?.Dispose(); + _episodes?.Dispose(); + _tracks?.Dispose(); + _genres?.Dispose(); + _studios?.Dispose(); + _people?.Dispose(); + _providers?.Dispose(); + } + + public async ValueTask DisposeAsync() + { + return ValueTask.(new [] + { + _libraries.DisposeAsync() + }); + } public Task GetLibrary(string slug) { diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs index c09bbc94..69f059ce 100644 --- a/Kyoo/Controllers/Repositories/CollectionRepository.cs +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Npgsql; namespace Kyoo.Controllers { @@ -45,9 +46,19 @@ namespace Kyoo.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - - await _database.Collections.AddAsync(obj); - await _database.SaveChangesAsync(); + + try + { + await _database.Collections.AddAsync(obj); + await _database.SaveChangesAsync(); + } + catch (DbUpdateException ex) + { + if (ex.InnerException is PostgresException inner && inner.SqlState == PostgresErrorCodes.UniqueViolation) + throw new DuplicatedItemException($"Trying to insert a duplicated collection (slug {obj.Slug} already exists)."); + throw; + } + return obj.ID; } @@ -59,7 +70,17 @@ namespace Kyoo.Controllers Collection old = await Get(obj.Slug); if (old != null) return old.ID; - return await Create(obj); + try + { + return await Create(obj); + } + catch (DuplicatedItemException) + { + old = await Get(obj.Slug); + if (old == null) + throw new SystemException("Unknown database state."); + return old.ID; + } } public async Task Edit(Collection edited, bool resetOld) diff --git a/Kyoo/Tasks/Crawler.cs b/Kyoo/Tasks/Crawler.cs index 3a5c8ae9..a0388769 100644 --- a/Kyoo/Tasks/Crawler.cs +++ b/Kyoo/Tasks/Crawler.cs @@ -63,6 +63,10 @@ namespace Kyoo.Controllers await libraryManager.DeleteEpisode(episode); } + // TODO replace this grotesque way to load the providers. + foreach (Library library in libraries) + library.Providers = library.Providers; + await Task.WhenAll(libraries.Select(x => Scan(x, episodes, cancellationToken))); } catch (Exception ex) @@ -72,7 +76,7 @@ namespace Kyoo.Controllers Console.WriteLine("Scan finished!"); } - private Task Scan(Library library, ICollection episodes, CancellationToken cancellationToken) + private Task Scan(Library library, IEnumerable episodes, CancellationToken cancellationToken) { Console.WriteLine($"Scanning library {library.Name} at {string.Join(", ", library.Paths)}."); return Task.WhenAll(library.Paths.Select(async path => @@ -106,16 +110,16 @@ namespace Kyoo.Controllers return Task.CompletedTask; } - // return Task.WhenAll(files.Select(file => - foreach (string file in files) + return Task.WhenAll(files.Select(file => + //foreach (string file in files) { if (!IsVideo(file) || episodes.Any(x => x.Path == file)) - continue; //return Task.CompletedTask; + /*continue;*/ return Task.CompletedTask; string relativePath = file.Substring(path.Length); - /*return*/ await RegisterFile(file, relativePath, library, cancellationToken); - }//)); + return /*await*/ RegisterFile(file, relativePath, library, cancellationToken); + })); - return Task.CompletedTask; + // return Task.CompletedTask; })); }