mirror of
https://github.com/Kareadita/Kavita.git
synced 2026-06-06 06:45:18 -04:00
OPDS Performance Enhancements (#4332)
Co-authored-by: Amelia <77553571+Fesaa@users.noreply.github.com>
This commit is contained in:
@@ -52,8 +52,7 @@ public interface IChapterRepository
|
||||
Task<IList<string>> GetAllCoverImagesAsync();
|
||||
Task<IList<Chapter>> GetAllChaptersWithCoversInDifferentEncoding(EncodeFormat format);
|
||||
Task<IEnumerable<string>> GetCoverImagesForLockedChaptersAsync();
|
||||
Task AddChapterModifiers(int userId, ChapterDto chapter);
|
||||
IEnumerable<Chapter> GetChaptersForSeries(int seriesId);
|
||||
IQueryable<Chapter> GetChaptersForSeries(int seriesId);
|
||||
Task<IList<Chapter>> GetAllChaptersForSeries(int seriesId);
|
||||
Task<int> GetAverageUserRating(int chapterId, int userId);
|
||||
Task<IList<UserReviewDto>> GetExternalChapterReviewDtos(int chapterId);
|
||||
@@ -63,6 +62,7 @@ public interface IChapterRepository
|
||||
Task<ChapterDto?> GetCurrentlyReadingChapterAsync(int seriesId, int userId);
|
||||
Task<ChapterDto?> GetFirstChapterForSeriesAsync(int seriesId, int userId);
|
||||
Task<ChapterDto?> GetFirstChapterForVolumeAsync(int volumeId, int userId);
|
||||
Task<IList<ChapterDto>> GetChapterDtosAsync(IEnumerable<int> chapterIds, int userId);
|
||||
}
|
||||
public class ChapterRepository : IChapterRepository
|
||||
{
|
||||
@@ -163,15 +163,10 @@ public class ChapterRepository : IChapterRepository
|
||||
{
|
||||
var chapter = await _context.Chapter
|
||||
.Includes(ChapterIncludes.Files | ChapterIncludes.People)
|
||||
.ProjectTo<ChapterDto>(_mapper.ConfigurationProvider)
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.AsSplitQuery()
|
||||
.FirstOrDefaultAsync(c => c.Id == chapterId);
|
||||
|
||||
if (userId > 0 && chapter != null)
|
||||
{
|
||||
await AddChapterModifiers(userId, chapter);
|
||||
}
|
||||
|
||||
return chapter;
|
||||
}
|
||||
|
||||
@@ -180,15 +175,10 @@ public class ChapterRepository : IChapterRepository
|
||||
var chapters = await _context.Chapter
|
||||
.Where(c => chapterIds.Contains(c.Id))
|
||||
.Includes(ChapterIncludes.Files | ChapterIncludes.People)
|
||||
.ProjectTo<ChapterDto>(_mapper.ConfigurationProvider)
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.AsSplitQuery()
|
||||
.ToListAsync() ;
|
||||
|
||||
foreach (var chapter in chapters)
|
||||
{
|
||||
await AddChapterModifiers(userId, chapter);
|
||||
}
|
||||
|
||||
return chapters;
|
||||
}
|
||||
|
||||
@@ -252,19 +242,12 @@ public class ChapterRepository : IChapterRepository
|
||||
/// <returns></returns>
|
||||
public async Task<IList<ChapterDto>> GetChapterDtosAsync(int volumeId, int userId)
|
||||
{
|
||||
var chapts = await _context.Chapter
|
||||
return await _context.Chapter
|
||||
.Where(c => c.VolumeId == volumeId)
|
||||
.Includes(ChapterIncludes.Files | ChapterIncludes.People)
|
||||
.OrderBy(c => c.SortOrder)
|
||||
.ProjectTo<ChapterDto>(_mapper.ConfigurationProvider)
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var chapter in chapts)
|
||||
{
|
||||
await AddChapterModifiers(userId, chapter);
|
||||
}
|
||||
|
||||
return chapts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -322,41 +305,17 @@ public class ChapterRepository : IChapterRepository
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task AddChapterModifiers(int userId, ChapterDto? chapter)
|
||||
{
|
||||
if (chapter == null) return;
|
||||
|
||||
var progress = await _context.AppUserProgresses.Where(x =>
|
||||
x.AppUserId == userId && x.ChapterId == chapter.Id)
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync();
|
||||
if (progress != null)
|
||||
{
|
||||
chapter.PagesRead = progress.PagesRead ;
|
||||
chapter.LastReadingProgressUtc = progress.LastModifiedUtc;
|
||||
chapter.LastReadingProgress = progress.LastModified;
|
||||
chapter.TotalReads = progress.TotalReads;
|
||||
}
|
||||
else
|
||||
{
|
||||
chapter.PagesRead = 0;
|
||||
chapter.LastReadingProgressUtc = DateTime.MinValue;
|
||||
chapter.LastReadingProgress = DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Includes Volumes
|
||||
/// </summary>
|
||||
/// <param name="seriesId"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Chapter> GetChaptersForSeries(int seriesId)
|
||||
public IQueryable<Chapter> GetChaptersForSeries(int seriesId)
|
||||
{
|
||||
return _context.Chapter
|
||||
.Where(c => c.Volume.SeriesId == seriesId)
|
||||
.OrderBy(c => c.SortOrder)
|
||||
.Include(c => c.Volume)
|
||||
.AsEnumerable();
|
||||
.Include(c => c.Volume);
|
||||
}
|
||||
|
||||
public async Task<IList<Chapter>> GetAllChaptersForSeries(int seriesId)
|
||||
@@ -453,62 +412,37 @@ public class ChapterRepository : IChapterRepository
|
||||
public async Task<ChapterDto?> GetFirstChapterForSeriesAsync(int seriesId, int userId)
|
||||
{
|
||||
// Get the chapter entity with proper ordering
|
||||
var firstChapter = await _context.Chapter
|
||||
return await _context.Chapter
|
||||
.Include(c => c.Volume)
|
||||
.Include(c => c.Files)
|
||||
.Where(c => c.Volume.SeriesId == seriesId)
|
||||
.OrderBy(c =>
|
||||
// Priority 1: Regular volumes (not loose leaf, not special)
|
||||
c.Volume.Number == Parser.LooseLeafVolumeNumber ||
|
||||
c.Volume.Number == Parser.SpecialVolumeNumber ? 1 : 0)
|
||||
.ThenBy(c =>
|
||||
// Priority 2: Loose leaf over specials
|
||||
c.Volume.Number == Parser.SpecialVolumeNumber ? 1 : 0)
|
||||
.ThenBy(c =>
|
||||
// Priority 3: Non-special chapters
|
||||
c.IsSpecial ? 1 : 0)
|
||||
.ThenBy(c => c.Volume.Number)
|
||||
.ThenBy(c => c.SortOrder)
|
||||
.ApplyDefaultChapterOrdering()
|
||||
.AsNoTracking()
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (firstChapter == null) return null;
|
||||
|
||||
var dto = _mapper.Map<ChapterDto>(firstChapter);
|
||||
|
||||
await AddChapterModifiers(userId, dto);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
public async Task<ChapterDto?> GetFirstChapterForVolumeAsync(int volumeId, int userId)
|
||||
{
|
||||
// Get the chapter entity with proper ordering
|
||||
var firstChapter = await _context.Chapter
|
||||
return await _context.Chapter
|
||||
.Include(c => c.Volume)
|
||||
.Include(c => c.Files)
|
||||
.Where(c => c.Volume.Id == volumeId)
|
||||
.OrderBy(c =>
|
||||
// Priority 1: Regular volumes (not loose leaf, not special)
|
||||
c.Volume.Number == Parser.LooseLeafVolumeNumber ||
|
||||
c.Volume.Number == Parser.SpecialVolumeNumber ? 1 : 0)
|
||||
.ThenBy(c =>
|
||||
// Priority 2: Loose leaf over specials
|
||||
c.Volume.Number == Parser.SpecialVolumeNumber ? 1 : 0)
|
||||
.ThenBy(c =>
|
||||
// Priority 3: Non-special chapters
|
||||
c.IsSpecial ? 1 : 0)
|
||||
.ThenBy(c => c.Volume.Number)
|
||||
.ThenBy(c => c.SortOrder)
|
||||
.ApplyDefaultChapterOrdering()
|
||||
.AsNoTracking()
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
if (firstChapter == null) return null;
|
||||
public async Task<IList<ChapterDto>> GetChapterDtosAsync(IEnumerable<int> chapterIds, int userId)
|
||||
{
|
||||
var chapterIdList = chapterIds.ToList();
|
||||
if (chapterIdList.Count == 0) return [];
|
||||
|
||||
var dto = _mapper.Map<ChapterDto>(firstChapter);
|
||||
|
||||
await AddChapterModifiers(userId, dto);
|
||||
|
||||
return dto;
|
||||
return await _context.Chapter
|
||||
.Where(c => chapterIdList.Contains(c.Id))
|
||||
.ProjectToWithProgress<Chapter, ChapterDto>(_mapper, userId)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user