mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-02 13:14:28 -04:00
Refactored ScanLibrary to accept and library id rather than DTO. Refactored ScanLibrary to use Task.Run() rather than having synchronous repo methods.
This commit is contained in:
parent
9168e12483
commit
7b1714349d
@ -71,7 +71,8 @@ namespace API.Controllers
|
|||||||
|
|
||||||
if (await _userRepository.SaveAllAsync())
|
if (await _userRepository.SaveAllAsync())
|
||||||
{
|
{
|
||||||
//TODO: Enqueue scan library task
|
var createdLibrary = await _libraryRepository.GetLibraryForNameAsync(library.Name);
|
||||||
|
BackgroundJob.Enqueue(() => _directoryService.ScanLibrary(createdLibrary.Id));
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,27 +129,22 @@ namespace API.Controllers
|
|||||||
|
|
||||||
[Authorize(Policy = "RequireAdminRole")]
|
[Authorize(Policy = "RequireAdminRole")]
|
||||||
[HttpPost("scan")]
|
[HttpPost("scan")]
|
||||||
public async Task<ActionResult> ScanLibrary(int libraryId)
|
public ActionResult ScanLibrary(int libraryId)
|
||||||
{
|
{
|
||||||
var library = await _libraryRepository.GetLibraryDtoForIdAsync(libraryId);
|
BackgroundJob.Enqueue(() => _directoryService.ScanLibrary(libraryId));
|
||||||
|
|
||||||
// We have to send a json encoded Library (aka a DTO) to the Background Job thread.
|
|
||||||
// Because we use EF, we have circular dependencies back to Library and it will crap out
|
|
||||||
// TODO: Refactor this to use libraryId and move Library call in method.
|
|
||||||
BackgroundJob.Enqueue(() => _directoryService.ScanLibrary(library));
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("libraries-for")]
|
[HttpGet("libraries-for")]
|
||||||
public async Task<ActionResult<IEnumerable<LibraryDto>>> GetLibrariesForUser(string username)
|
public async Task<ActionResult<IEnumerable<LibraryDto>>> GetLibrariesForUser(string username)
|
||||||
{
|
{
|
||||||
return Ok(await _libraryRepository.GetLibrariesForUsernameAysnc(username));
|
return Ok(await _libraryRepository.GetLibrariesDtoForUsernameAsync(username));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("series")]
|
[HttpGet("series")]
|
||||||
public async Task<ActionResult<IEnumerable<Series>>> GetSeriesForLibrary(int libraryId)
|
public async Task<ActionResult<IEnumerable<Series>>> GetSeriesForLibrary(int libraryId)
|
||||||
{
|
{
|
||||||
return Ok(await _seriesRepository.GetSeriesForLibraryIdAsync(libraryId));
|
return Ok(await _seriesRepository.GetSeriesDtoForLibraryIdAsync(libraryId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,13 +27,13 @@ namespace API.Controllers
|
|||||||
[HttpGet("{seriesId}")]
|
[HttpGet("{seriesId}")]
|
||||||
public async Task<ActionResult<SeriesDto>> GetSeries(int seriesId)
|
public async Task<ActionResult<SeriesDto>> GetSeries(int seriesId)
|
||||||
{
|
{
|
||||||
return Ok(await _seriesRepository.GetSeriesByIdAsync(seriesId));
|
return Ok(await _seriesRepository.GetSeriesDtoByIdAsync(seriesId));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("volumes")]
|
[HttpGet("volumes")]
|
||||||
public async Task<ActionResult<IEnumerable<VolumeDto>>> GetVolumes(int seriesId)
|
public async Task<ActionResult<IEnumerable<VolumeDto>>> GetVolumes(int seriesId)
|
||||||
{
|
{
|
||||||
return Ok(await _seriesRepository.GetVolumesAsync(seriesId));
|
return Ok(await _seriesRepository.GetVolumesDtoAsync(seriesId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using API.DTOs;
|
using API.DTOs;
|
||||||
using API.Entities;
|
|
||||||
using API.Extensions;
|
using API.Extensions;
|
||||||
using API.Interfaces;
|
using API.Interfaces;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@ -51,7 +50,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
if (user == null) return BadRequest("Could not validate user");
|
if (user == null) return BadRequest("Could not validate user");
|
||||||
|
|
||||||
var libs = await _libraryRepository.GetLibrariesForUsernameAysnc(user.UserName);
|
var libs = await _libraryRepository.GetLibrariesDtoForUsernameAsync(user.UserName);
|
||||||
|
|
||||||
return Ok(libs.Any(x => x.Id == libraryId));
|
return Ok(libs.Any(x => x.Id == libraryId));
|
||||||
}
|
}
|
||||||
|
@ -36,16 +36,7 @@ namespace API.Data
|
|||||||
return _context.SaveChanges() > 0;
|
return _context.SaveChanges() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Library GetLibraryForName(string libraryName)
|
public async Task<IEnumerable<LibraryDto>> GetLibrariesDtoForUsernameAsync(string userName)
|
||||||
{
|
|
||||||
return _context.Library
|
|
||||||
.Where(x => x.Name == libraryName)
|
|
||||||
.Include(f => f.Folders)
|
|
||||||
.Include(s => s.Series)
|
|
||||||
.Single();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<LibraryDto>> GetLibrariesForUsernameAysnc(string userName)
|
|
||||||
{
|
{
|
||||||
return await _context.Library
|
return await _context.Library
|
||||||
.Include(l => l.AppUsers)
|
.Include(l => l.AppUsers)
|
||||||
@ -53,6 +44,15 @@ namespace API.Data
|
|||||||
.ProjectTo<LibraryDto>(_mapper.ConfigurationProvider).ToListAsync();
|
.ProjectTo<LibraryDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Library> GetLibraryForNameAsync(string libraryName)
|
||||||
|
{
|
||||||
|
return await _context.Library
|
||||||
|
.Where(x => x.Name == libraryName)
|
||||||
|
.Include(f => f.Folders)
|
||||||
|
.Include(s => s.Series)
|
||||||
|
.SingleAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<LibraryDto>> GetLibrariesAsync()
|
public async Task<IEnumerable<LibraryDto>> GetLibrariesAsync()
|
||||||
{
|
{
|
||||||
return await _context.Library
|
return await _context.Library
|
||||||
@ -60,14 +60,6 @@ namespace API.Data
|
|||||||
.ProjectTo<LibraryDto>(_mapper.ConfigurationProvider).ToListAsync();
|
.ProjectTo<LibraryDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LibraryDto> GetLibraryDtoForIdAsync(int libraryId)
|
|
||||||
{
|
|
||||||
return await _context.Library
|
|
||||||
.Where(x => x.Id == libraryId)
|
|
||||||
.Include(f => f.Folders)
|
|
||||||
.ProjectTo<LibraryDto>(_mapper.ConfigurationProvider).SingleAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Library> GetLibraryForIdAsync(int libraryId)
|
public async Task<Library> GetLibraryForIdAsync(int libraryId)
|
||||||
{
|
{
|
||||||
return await _context.Library
|
return await _context.Library
|
||||||
|
@ -46,7 +46,7 @@ namespace API.Data
|
|||||||
return _context.Series.SingleOrDefault(x => x.Name == name);
|
return _context.Series.SingleOrDefault(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<SeriesDto>> GetSeriesForLibraryIdAsync(int libraryId)
|
public async Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId)
|
||||||
{
|
{
|
||||||
return await _context.Series
|
return await _context.Series
|
||||||
.Where(series => series.LibraryId == libraryId)
|
.Where(series => series.LibraryId == libraryId)
|
||||||
@ -54,7 +54,7 @@ namespace API.Data
|
|||||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider).ToListAsync();
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<VolumeDto>> GetVolumesAsync(int seriesId)
|
public async Task<IEnumerable<VolumeDto>> GetVolumesDtoAsync(int seriesId)
|
||||||
{
|
{
|
||||||
return await _context.Volume
|
return await _context.Volume
|
||||||
.Where(vol => vol.SeriesId == seriesId)
|
.Where(vol => vol.SeriesId == seriesId)
|
||||||
@ -62,14 +62,6 @@ namespace API.Data
|
|||||||
.ProjectTo<VolumeDto>(_mapper.ConfigurationProvider).ToListAsync();
|
.ProjectTo<VolumeDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<VolumeDto> GetVolumesDto(int seriesId)
|
|
||||||
{
|
|
||||||
return _context.Volume
|
|
||||||
.Where(vol => vol.SeriesId == seriesId)
|
|
||||||
.OrderBy(vol => vol.Number)
|
|
||||||
.ProjectTo<VolumeDto>(_mapper.ConfigurationProvider).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Volume> GetVolumes(int seriesId)
|
public IEnumerable<Volume> GetVolumes(int seriesId)
|
||||||
{
|
{
|
||||||
return _context.Volume
|
return _context.Volume
|
||||||
@ -78,7 +70,7 @@ namespace API.Data
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SeriesDto> GetSeriesByIdAsync(int seriesId)
|
public async Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId)
|
||||||
{
|
{
|
||||||
return await _context.Series.Where(x => x.Id == seriesId)
|
return await _context.Series.Where(x => x.Id == seriesId)
|
||||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider).SingleAsync();
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider).SingleAsync();
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using API.DTOs;
|
|
||||||
|
|
||||||
namespace API.Interfaces
|
namespace API.Interfaces
|
||||||
{
|
{
|
||||||
@ -7,6 +6,6 @@ namespace API.Interfaces
|
|||||||
{
|
{
|
||||||
IEnumerable<string> ListDirectory(string rootPath);
|
IEnumerable<string> ListDirectory(string rootPath);
|
||||||
|
|
||||||
void ScanLibrary(LibraryDto library);
|
void ScanLibrary(int libraryId);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,16 +10,10 @@ namespace API.Interfaces
|
|||||||
void Update(Library library);
|
void Update(Library library);
|
||||||
Task<bool> SaveAllAsync();
|
Task<bool> SaveAllAsync();
|
||||||
Task<IEnumerable<LibraryDto>> GetLibrariesAsync();
|
Task<IEnumerable<LibraryDto>> GetLibrariesAsync();
|
||||||
/// <summary>
|
|
||||||
/// Checks to see if a library of the same name exists. We only allow unique library names, no duplicates per LibraryType.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="libraryName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<bool> LibraryExists(string libraryName);
|
Task<bool> LibraryExists(string libraryName);
|
||||||
Task<LibraryDto> GetLibraryDtoForIdAsync(int libraryId);
|
|
||||||
Task<Library> GetLibraryForIdAsync(int libraryId);
|
Task<Library> GetLibraryForIdAsync(int libraryId);
|
||||||
bool SaveAll();
|
bool SaveAll();
|
||||||
Library GetLibraryForName(string libraryName);
|
Task<IEnumerable<LibraryDto>> GetLibrariesDtoForUsernameAsync(string userName);
|
||||||
Task<IEnumerable<LibraryDto>> GetLibrariesForUsernameAysnc(string userName);
|
Task<Library> GetLibraryForNameAsync(string libraryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,11 +12,10 @@ namespace API.Interfaces
|
|||||||
Task<Series> GetSeriesByNameAsync(string name);
|
Task<Series> GetSeriesByNameAsync(string name);
|
||||||
Series GetSeriesByName(string name);
|
Series GetSeriesByName(string name);
|
||||||
bool SaveAll();
|
bool SaveAll();
|
||||||
Task<IEnumerable<SeriesDto>> GetSeriesForLibraryIdAsync(int libraryId);
|
Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId);
|
||||||
Task<IEnumerable<VolumeDto>> GetVolumesAsync(int seriesId);
|
Task<IEnumerable<VolumeDto>> GetVolumesDtoAsync(int seriesId);
|
||||||
IEnumerable<VolumeDto> GetVolumesDto(int seriesId);
|
|
||||||
IEnumerable<Volume> GetVolumes(int seriesId);
|
IEnumerable<Volume> GetVolumes(int seriesId);
|
||||||
Task<SeriesDto> GetSeriesByIdAsync(int seriesId);
|
Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,11 +5,9 @@ using System.Collections.Immutable;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using API.DTOs;
|
|
||||||
using API.Entities;
|
using API.Entities;
|
||||||
using API.Interfaces;
|
using API.Interfaces;
|
||||||
using API.Parser;
|
using API.Parser;
|
||||||
@ -149,6 +147,7 @@ namespace API.Services
|
|||||||
|
|
||||||
// BUG: This is creating new volume entries and not resetting each run.
|
// BUG: This is creating new volume entries and not resetting each run.
|
||||||
IList<Volume> existingVolumes = _seriesRepository.GetVolumes(series.Id).ToList();
|
IList<Volume> existingVolumes = _seriesRepository.GetVolumes(series.Id).ToList();
|
||||||
|
//IList<Volume> existingVolumes = Task.Run(() => _seriesRepository.GetVolumesAsync(series.Id)).Result.ToList();
|
||||||
foreach (var info in infos)
|
foreach (var info in infos)
|
||||||
{
|
{
|
||||||
var existingVolume = existingVolumes.SingleOrDefault(v => v.Name == info.Volumes);
|
var existingVolume = existingVolumes.SingleOrDefault(v => v.Name == info.Volumes);
|
||||||
@ -189,46 +188,45 @@ namespace API.Services
|
|||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScanLibrary(LibraryDto library)
|
public void ScanLibrary(int libraryId)
|
||||||
{
|
{
|
||||||
|
var library = Task.Run(() => _libraryRepository.GetLibraryForIdAsync(libraryId)).Result;
|
||||||
_scannedSeries = new ConcurrentDictionary<string, ConcurrentBag<ParserInfo>>();
|
_scannedSeries = new ConcurrentDictionary<string, ConcurrentBag<ParserInfo>>();
|
||||||
_logger.LogInformation($"Beginning scan on {library.Name}");
|
_logger.LogInformation($"Beginning scan on {library.Name}");
|
||||||
|
|
||||||
foreach (var folderPath in library.Folders)
|
foreach (var folderPath in library.Folders)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
TraverseTreeParallelForEach(folderPath, (f) =>
|
TraverseTreeParallelForEach(folderPath.Path, (f) =>
|
||||||
{
|
{
|
||||||
// Exceptions are no-ops.
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process(f);
|
Process(f);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException) {}
|
catch (FileNotFoundException exception)
|
||||||
catch (IOException) {}
|
{
|
||||||
catch (UnauthorizedAccessException) {}
|
_logger.LogError(exception, "The file could not be found");
|
||||||
catch (SecurityException) {}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (ArgumentException ex) {
|
catch (ArgumentException ex) {
|
||||||
_logger.LogError(ex, "The directory '{folderPath}' does not exist");
|
_logger.LogError(ex, $"The directory '{folderPath}' does not exist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var filtered = _scannedSeries.Where(kvp => !kvp.Value.IsEmpty);
|
var filtered = _scannedSeries.Where(kvp => !kvp.Value.IsEmpty);
|
||||||
var series = filtered.ToImmutableDictionary(v => v.Key, v => v.Value);
|
var series = filtered.ToImmutableDictionary(v => v.Key, v => v.Value);
|
||||||
|
|
||||||
// Perform DB activities on ImmutableDictionary
|
// Perform DB activities
|
||||||
var libraryEntity = _libraryRepository.GetLibraryForName(library.Name);
|
library.Series = new List<Series>(); // Temp delete everything until we can mark items Unavailable
|
||||||
libraryEntity.Series = new List<Series>(); // Temp delete everything for testing
|
|
||||||
foreach (var seriesKey in series.Keys)
|
foreach (var seriesKey in series.Keys)
|
||||||
{
|
{
|
||||||
var s = UpdateSeries(seriesKey, series[seriesKey].ToArray());
|
var s = UpdateSeries(seriesKey, series[seriesKey].ToArray());
|
||||||
_logger.LogInformation($"Created/Updated series {s.Name}");
|
_logger.LogInformation($"Created/Updated series {s.Name}");
|
||||||
libraryEntity.Series.Add(s);
|
library.Series.Add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
_libraryRepository.Update(libraryEntity);
|
_libraryRepository.Update(library);
|
||||||
|
|
||||||
if (_libraryRepository.SaveAll())
|
if (_libraryRepository.SaveAll())
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user