Bugfix/reader progress (#435)

Fixed: Fixed an issue where marking a series as Unread when the DB gets skewed with duplicate progress rows for that item, would break. Now we cleanup any extra rows we see during the operation.
This commit is contained in:
Joseph Milazzo 2021-07-25 17:31:42 -05:00 committed by GitHub
parent 2209a65d52
commit 66f40656dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 20 deletions

View File

@ -106,8 +106,9 @@ namespace API.Controllers
{
foreach (var chapter in volume.Chapters)
{
var userProgress = user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id);
if (userProgress == null) // I need to get all chapters and generate new user progresses for them?
var userProgress = GetUserProgressForChapter(user, chapter);
if (userProgress == null)
{
user.Progresses.Add(new AppUserProgress
{
@ -137,6 +138,31 @@ namespace API.Controllers
return BadRequest("There was an issue saving progress");
}
private static AppUserProgress GetUserProgressForChapter(AppUser user, Chapter chapter)
{
AppUserProgress userProgress = null;
try
{
userProgress =
user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id);
}
catch (Exception)
{
// There is a very rare chance that user progress will duplicate current row. If that happens delete one with less pages
var progresses = user.Progresses.Where(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id).ToList();
if (progresses.Count > 1)
{
user.Progresses = new List<AppUserProgress>()
{
user.Progresses.First()
};
userProgress = user.Progresses.First();
}
}
return userProgress;
}
[HttpPost("mark-unread")]
public async Task<ActionResult> MarkUnread(MarkReadDto markReadDto)
{
@ -147,23 +173,12 @@ namespace API.Controllers
{
foreach (var chapter in volume.Chapters)
{
var userProgress = user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id);
if (userProgress == null)
{
user.Progresses.Add(new AppUserProgress
{
PagesRead = 0,
VolumeId = volume.Id,
SeriesId = markReadDto.SeriesId,
ChapterId = chapter.Id
});
}
else
{
userProgress.PagesRead = 0;
userProgress.SeriesId = markReadDto.SeriesId;
userProgress.VolumeId = volume.Id;
}
var userProgress = GetUserProgressForChapter(user, chapter);
if (userProgress == null) continue;
userProgress.PagesRead = 0;
userProgress.SeriesId = markReadDto.SeriesId;
userProgress.VolumeId = volume.Id;
}
}

View File

@ -9,6 +9,7 @@ using API.Entities.Enums;
using API.Services;
using Kavita.Common;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace API.Data
{
@ -69,5 +70,21 @@ namespace API.Data
await context.SaveChangesAsync();
}
public static async Task SeedSeriesMetadata(DataContext context)
{
await context.Database.EnsureCreatedAsync();
context.Database.EnsureCreated();
var series = await context.Series
.Include(s => s.Metadata).ToListAsync();
foreach (var s in series)
{
s.Metadata ??= new SeriesMetadata();
}
await context.SaveChangesAsync();
}
}
}

28
Dockerfile.alpine Normal file
View File

@ -0,0 +1,28 @@
#This Dockerfile is for the musl alpine build of Kavita.
FROM alpine:latest
MAINTAINER Chris P
#Installs the needed dependencies
RUN apk update && apk add --no-cache wget curl pwgen icu-dev bash
#Downloads Kavita, unzips and moves the folders to where they need to be
RUN wget https://github.com/Kareadita/Kavita/releases/download/v0.3.7/kavita-linux-musl-x64.tar.gz \
&& tar -xzf kavita*.tar.gz \
&& mv Kavita/ /kavita/ \
&& rm kavita*.gz \
&& chmod +x /kavita/Kavita
#Creates the needed folders
RUN mkdir /manga /kavita/data /kavita/temp /kavita/cache
RUN sed -i 's/Data source=kavita.db/Data source=data\/kavita.db/g' /kavita/appsettings.json
COPY entrypoint.sh /entrypoint.sh
EXPOSE 5000
WORKDIR /kavita
ENTRYPOINT ["/bin/bash"]
CMD ["/entrypoint.sh"]

27
Dockerfile.arm Normal file
View File

@ -0,0 +1,27 @@
#This Dockerfile pulls the latest git commit and builds Kavita from source
#Production image
FROM ubuntu:focal
#Move the output files to where they need to be
COPY Kavita /kavita
#Installs program dependencies
RUN apt-get update \
&& apt-get install -y libicu-dev libssl1.1 pwgen \
&& rm -rf /var/lib/apt/lists/*
#Creates the manga storage directory
RUN mkdir /kavita/data
RUN cp /kavita/appsettings.Development.json /kavita/appsettings.json \
&& sed -i 's/Data source=kavita.db/Data source=data\/kavita.db/g' /kavita/appsettings.json
COPY entrypoint.sh /entrypoint.sh
EXPOSE 5000
WORKDIR /kavita
ENTRYPOINT ["/bin/bash"]
CMD ["/entrypoint.sh"]

View File

@ -4,7 +4,7 @@
<TargetFramework>net5.0</TargetFramework>
<Company>kavitareader.com</Company>
<Product>Kavita</Product>
<AssemblyVersion>0.4.3.0</AssemblyVersion>
<AssemblyVersion>0.4.3.1</AssemblyVersion>
<NeutralLanguage>en</NeutralLanguage>
</PropertyGroup>

27
build_target.sh Normal file
View File

@ -0,0 +1,27 @@
#!/bin/bash
mkdir Projects
cd Projects
git clone https://github.com/Kareadita/Kavita.git
git clone https://github.com/Kareadita/Kavita-webui.git
cd Kavita
chmod +x build.sh
#Builds program based on the target platform
if [ "$TARGETPLATFORM" == "linux/amd64" ]
then
./build.sh linux-x64
mv /Projects/Kavita/_output/linux-x64 /Projects/Kavita/_output/build
elif [ "$TARGETPLATFORM" == "linux/arm/v7" ]
then
./build.sh linux-arm
mv /Projects/Kavita/_output/linux-arm /Projects/Kavita/_output/build
elif [ "$TARGETPLATFORM" == "linux/arm64" ]
then
./build.sh linux-arm64
mv /Projects/Kavita/_output/linux-arm64 /Projects/Kavita/_output/build
fi