mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Lots of Hangfire attempts to solve the lock issue. Not sure how to fix it. Added some APIs for streams.
This commit is contained in:
parent
bb0a59448f
commit
fad4ca4414
@ -128,9 +128,18 @@ namespace API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("recently-added")]
|
[HttpGet("recently-added")]
|
||||||
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetRecentlyAdded(int libraryId = 0)
|
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetRecentlyAdded(int libraryId = 0, int limit = 20)
|
||||||
{
|
{
|
||||||
return Ok(await _unitOfWork.SeriesRepository.GetRecentlyAdded(libraryId));
|
return Ok(await _unitOfWork.SeriesRepository.GetRecentlyAdded(libraryId, limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("in-progress")]
|
||||||
|
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetInProgress(int libraryId = 0, int limit = 20)
|
||||||
|
{
|
||||||
|
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||||
|
return Ok(await _unitOfWork.SeriesRepository.GetInProgress(user.Id, libraryId, limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ using API.Interfaces;
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using AutoMapper.QueryableExtensions;
|
using AutoMapper.QueryableExtensions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace API.Data
|
namespace API.Data
|
||||||
@ -282,20 +283,55 @@ namespace API.Data
|
|||||||
/// Returns a list of Series that were added within 2 weeks.
|
/// Returns a list of Series that were added within 2 weeks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="libraryId">Library to restrict to, if 0, will apply to all libraries</param>
|
/// <param name="libraryId">Library to restrict to, if 0, will apply to all libraries</param>
|
||||||
|
/// <param name="limit"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<IEnumerable<SeriesDto>> GetRecentlyAdded(int libraryId)
|
public async Task<IEnumerable<SeriesDto>> GetRecentlyAdded(int libraryId, int limit)
|
||||||
{
|
{
|
||||||
// && (libraryId <= 0 || s.LibraryId == libraryId)
|
// TODO: Remove 2 week condition
|
||||||
var twoWeeksAgo = DateTime.Today.Subtract(TimeSpan.FromDays(14));
|
var twoWeeksAgo = DateTime.Today.Subtract(TimeSpan.FromDays(14));
|
||||||
_logger.LogDebug("2 weeks from today is: {Date}", twoWeeksAgo);
|
_logger.LogDebug("2 weeks from today is: {Date}", twoWeeksAgo);
|
||||||
return await _context.Series
|
return await _context.Series
|
||||||
.Where(s => s.Created > twoWeeksAgo)
|
.Where(s => s.Created > twoWeeksAgo && (libraryId <= 0 || s.LibraryId == libraryId))
|
||||||
.Take(20)
|
.Take(limit)
|
||||||
|
.OrderBy(s => s.Created)
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<SeriesDto>> GetInProgress(int userId, int libraryId, int limit)
|
||||||
|
{
|
||||||
|
//&& (libraryId <= 0 || s.Series.LibraryId == libraryId)
|
||||||
|
var twoWeeksAgo = DateTime.Today.Subtract(TimeSpan.FromDays(14));
|
||||||
|
_logger.LogInformation("GetInProgress");
|
||||||
|
_logger.LogDebug("2 weeks from today is: {Date}", twoWeeksAgo);
|
||||||
|
// var series = await _context.Series
|
||||||
|
// .Join(_context.AppUserProgresses, s => s.Id, progress => progress.SeriesId, (s, progress) => new
|
||||||
|
// {
|
||||||
|
// Series = s,
|
||||||
|
// Progress = progress
|
||||||
|
// })
|
||||||
|
// .DefaultIfEmpty()
|
||||||
|
// .Where(s => s.Series.Created > twoWeeksAgo
|
||||||
|
// && s.Progress.AppUserId == userId
|
||||||
|
// && s.Progress.PagesRead > s.Series.Pages)
|
||||||
|
// .Take(limit)
|
||||||
|
// .OrderBy(s => s.Series.Created)
|
||||||
|
// .AsNoTracking()
|
||||||
|
// .Select(s => s.Series)
|
||||||
|
// .ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||||
|
// .ToListAsync();
|
||||||
|
var series = await _context.Series
|
||||||
|
.Where(s => s.Created > twoWeeksAgo) // && (libraryId <= 0 || s.LibraryId == libraryId)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
await AddSeriesModifiers(userId, series);
|
||||||
|
|
||||||
|
return series.Where(s => s.PagesRead > 0).Take(limit).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<IEnumerable<SeriesDto>> GetSeriesStream(int userId)
|
public async Task<IEnumerable<SeriesDto>> GetSeriesStream(int userId)
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
namespace API.Extensions
|
using API.Interfaces.Services;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace API.Extensions
|
||||||
{
|
{
|
||||||
public class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
|
public static IServiceCollection AddStartupTask<T>(this IServiceCollection services)
|
||||||
|
where T : class, IStartupTask
|
||||||
|
=> services.AddTransient<IStartupTask, T>();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -55,6 +55,7 @@ namespace API.Interfaces
|
|||||||
|
|
||||||
Task<byte[]> GetVolumeCoverImageAsync(int volumeId);
|
Task<byte[]> GetVolumeCoverImageAsync(int volumeId);
|
||||||
Task<byte[]> GetSeriesCoverImageAsync(int seriesId);
|
Task<byte[]> GetSeriesCoverImageAsync(int seriesId);
|
||||||
Task<IEnumerable<SeriesDto>> GetRecentlyAdded(int libraryId);
|
Task<IEnumerable<SeriesDto>> GetInProgress(int userId, int libraryId, int limit);
|
||||||
|
Task<IEnumerable<SeriesDto>> GetRecentlyAdded(int libraryId, int limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,6 +25,7 @@ namespace API.Middleware
|
|||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext context)
|
||||||
{
|
{
|
||||||
|
// BUG: I think Hangfire timeouts are triggering the middleware to hijack an API call
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _next(context); // downstream middlewares or http call
|
await _next(context); // downstream middlewares or http call
|
||||||
|
@ -3,6 +3,8 @@ using System.Threading.Tasks;
|
|||||||
using API.Data;
|
using API.Data;
|
||||||
using API.Entities;
|
using API.Entities;
|
||||||
using API.Interfaces;
|
using API.Interfaces;
|
||||||
|
using API.Interfaces.Services;
|
||||||
|
using API.Services;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -40,6 +42,15 @@ namespace API
|
|||||||
var logger = services.GetRequiredService < ILogger<Program>>();
|
var logger = services.GetRequiredService < ILogger<Program>>();
|
||||||
logger.LogError(ex, "An error occurred during migration");
|
logger.LogError(ex, "An error occurred during migration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load all tasks from DI (TODO: This is not working)
|
||||||
|
var startupTasks = host.Services.GetServices<WarmupServicesStartupTask>();
|
||||||
|
|
||||||
|
// Execute all the tasks
|
||||||
|
foreach (var startupTask in startupTasks)
|
||||||
|
{
|
||||||
|
await startupTask.ExecuteAsync();
|
||||||
|
}
|
||||||
|
|
||||||
await host.RunAsync();
|
await host.RunAsync();
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ namespace API.Services
|
|||||||
private readonly ICleanupService _cleanupService;
|
private readonly ICleanupService _cleanupService;
|
||||||
private readonly IDirectoryService _directoryService;
|
private readonly IDirectoryService _directoryService;
|
||||||
|
|
||||||
public static BackgroundJobServer Client => new BackgroundJobServer();
|
public static BackgroundJobServer Client => new BackgroundJobServer(new BackgroundJobServerOptions()
|
||||||
// new BackgroundJobServerOptions()
|
{
|
||||||
// {
|
WorkerCount = 1
|
||||||
// WorkerCount = 1
|
});
|
||||||
// }
|
|
||||||
|
|
||||||
public TaskScheduler(ICacheService cacheService, ILogger<TaskScheduler> logger, IScannerService scannerService,
|
public TaskScheduler(ICacheService cacheService, ILogger<TaskScheduler> logger, IScannerService scannerService,
|
||||||
IUnitOfWork unitOfWork, IMetadataService metadataService, IBackupService backupService, ICleanupService cleanupService,
|
IUnitOfWork unitOfWork, IMetadataService metadataService, IBackupService backupService, ICleanupService cleanupService,
|
||||||
|
@ -33,7 +33,7 @@ namespace API.Services.Tasks
|
|||||||
_metadataService = metadataService;
|
_metadataService = metadataService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DisableConcurrentExecution(timeoutInSeconds: 5)]
|
//[DisableConcurrentExecution(timeoutInSeconds: 5)]
|
||||||
[AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
[AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||||
public void ScanLibraries()
|
public void ScanLibraries()
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ namespace API.Services.Tasks
|
|||||||
_scannedSeries = null;
|
_scannedSeries = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DisableConcurrentExecution(5)]
|
//[DisableConcurrentExecution(5)]
|
||||||
[AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
[AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||||
public void ScanLibrary(int libraryId, bool forceUpdate)
|
public void ScanLibrary(int libraryId, bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
@ -18,14 +18,13 @@ namespace API.Services
|
|||||||
_provider = provider;
|
_provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ExecuteAsync(CancellationToken cancellationToken)
|
public Task ExecuteAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using (var scope = _provider.CreateScope())
|
using var scope = _provider.CreateScope();
|
||||||
|
foreach (var singleton in GetServices(_services))
|
||||||
{
|
{
|
||||||
foreach (var singleton in GetServices(_services))
|
Console.WriteLine("DI preloading of " + singleton.FullName);
|
||||||
{
|
scope.ServiceProvider.GetServices(singleton);
|
||||||
scope.ServiceProvider.GetServices(singleton);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
@ -64,10 +64,9 @@ namespace API
|
|||||||
services.AddResponseCaching();
|
services.AddResponseCaching();
|
||||||
|
|
||||||
|
|
||||||
services
|
// services
|
||||||
.AddStartupTask<WarmupServicesStartupTask>()
|
// .AddStartupTask<WarmupServicesStartupTask>()
|
||||||
.TryAddSingleton(services);
|
// //.TryAddSingleton(services);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -134,7 +133,7 @@ namespace API
|
|||||||
{
|
{
|
||||||
Console.WriteLine("Server is shutting down. Going to dispose Hangfire");
|
Console.WriteLine("Server is shutting down. Going to dispose Hangfire");
|
||||||
//this code is called when the application stops
|
//this code is called when the application stops
|
||||||
//TaskScheduler.Client.Dispose();
|
TaskScheduler.Client.Dispose();
|
||||||
System.Threading.Thread.Sleep(1000);
|
System.Threading.Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user