Starting to implement a dispose pattern for the library manager/repositories

This commit is contained in:
Zoe Roux 2020-06-11 16:46:17 +02:00
parent b0eab43d52
commit d34a6fd75a
6 changed files with 77 additions and 14 deletions

View File

@ -1,11 +1,12 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Kyoo.Models; using Kyoo.Models;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public interface ILibraryManager public interface ILibraryManager : IDisposable, IAsyncDisposable
{ {
// Get by slug // Get by slug
Task<Library> GetLibrary(string slug); Task<Library> GetLibrary(string slug);

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -5,7 +6,7 @@ using Kyoo.Models;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public interface IRepository<T> public interface IRepository<T> : IDisposable, IAsyncDisposable
{ {
Task<T> Get(int id); Task<T> Get(int id);
Task<T> Get(string slug); Task<T> Get(string slug);

View File

@ -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;
}
}
}

View File

@ -40,6 +40,28 @@ namespace Kyoo.Controllers
_providers = providers; _providers = providers;
_people = people; _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<Library> GetLibrary(string slug) public Task<Library> GetLibrary(string slug)
{ {

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Kyoo.Models; using Kyoo.Models;
using Kyoo.Models.Exceptions; using Kyoo.Models.Exceptions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Npgsql;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
@ -45,9 +46,19 @@ namespace Kyoo.Controllers
{ {
if (obj == null) if (obj == null)
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
await _database.Collections.AddAsync(obj); try
await _database.SaveChangesAsync(); {
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; return obj.ID;
} }
@ -59,7 +70,17 @@ namespace Kyoo.Controllers
Collection old = await Get(obj.Slug); Collection old = await Get(obj.Slug);
if (old != null) if (old != null)
return old.ID; 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) public async Task Edit(Collection edited, bool resetOld)

View File

@ -63,6 +63,10 @@ namespace Kyoo.Controllers
await libraryManager.DeleteEpisode(episode); 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))); await Task.WhenAll(libraries.Select(x => Scan(x, episodes, cancellationToken)));
} }
catch (Exception ex) catch (Exception ex)
@ -72,7 +76,7 @@ namespace Kyoo.Controllers
Console.WriteLine("Scan finished!"); Console.WriteLine("Scan finished!");
} }
private Task Scan(Library library, ICollection<Episode> episodes, CancellationToken cancellationToken) private Task Scan(Library library, IEnumerable<Episode> episodes, CancellationToken cancellationToken)
{ {
Console.WriteLine($"Scanning library {library.Name} at {string.Join(", ", library.Paths)}."); Console.WriteLine($"Scanning library {library.Name} at {string.Join(", ", library.Paths)}.");
return Task.WhenAll(library.Paths.Select(async path => return Task.WhenAll(library.Paths.Select(async path =>
@ -106,16 +110,16 @@ namespace Kyoo.Controllers
return Task.CompletedTask; return Task.CompletedTask;
} }
// return Task.WhenAll(files.Select(file => return Task.WhenAll(files.Select(file =>
foreach (string file in files) //foreach (string file in files)
{ {
if (!IsVideo(file) || episodes.Any(x => x.Path == file)) if (!IsVideo(file) || episodes.Any(x => x.Path == file))
continue; //return Task.CompletedTask; /*continue;*/ return Task.CompletedTask;
string relativePath = file.Substring(path.Length); 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;
})); }));
} }