Kavita/API/Controllers/ServerController.cs
Joseph Milazzo af4f35da5b
Better Caching & Global Downloads (#1372)
* Fixed a bug where cache TTL was using a field which always was 0.

* Updated Scan Series task (from UI) to always re-calculate what's on file and not rely on last update. This leads to more reliable results, despite extra overhead.

* Added image range processing on images for the reader, for slower networks or large files

* On manga (single) try to use prefetched image, rather than re-requesting an image on pagination

* Reduced some more latency when rendering first page of next chapter via continuous reading mode

* Fixed a bug where metadata filter, after updating a typeahead, collapsing filter area then re-opening, the filter would still be applied, but the typeahead wouldn't show the modification.

* Coded an idea around download reporting, commiting for history, might not go with it.

* Refactored the download indicator into it's own component. Cleaning up some code for download within card component

* Another throw away commit. Put in some temp code, not working but not sure if I'm ditching entirely.

* Updated download service to enable range processing (so downloads can resume) and to reduce re-zipping if we've just downloaded something.

* Refactored events widget download indicator to the correct design. I will be moving forward with this new functionality.

* Added Required fields to ProgressDTO

* Cleaned up the event widget and updated existing download progress to indicate preparing the download, rather than the download itself.

* Updated dependencies for security alerts

* Refactored all download code to be streamlined and globally handled

* Updated ScanSeries to find the highest folder path before library, not just within the files. This could lead to scan series missing files due to nested folders on same parent level.

* Updated the caching code to use a builtin annotation. Images are now caching correctly.

* Fixed a bad redirect on an auth guard

* Tweaked how long we allow cache for, as the cover update now doesn't work well.

* Fixed a bug on downloading bookmarks from multiple series, where it would just choose the first series id for the temp file.

* Added an extra check for downloading bookmarks

* UI Security updates, Fixed a bug on bookmark reader, the reader on last page would throw some errors and not show No Next Chapter toast.

* After scan, clear temp

* Code smells
2022-07-13 07:45:14 -07:00

175 lines
6.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using API.DTOs.Jobs;
using API.DTOs.Stats;
using API.DTOs.Update;
using API.Extensions;
using API.Services;
using API.Services.Tasks;
using Hangfire;
using Hangfire.Storage;
using Kavita.Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using TaskScheduler = System.Threading.Tasks.TaskScheduler;
namespace API.Controllers
{
[Authorize(Policy = "RequireAdminRole")]
public class ServerController : BaseApiController
{
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly ILogger<ServerController> _logger;
private readonly IConfiguration _config;
private readonly IBackupService _backupService;
private readonly IArchiveService _archiveService;
private readonly IVersionUpdaterService _versionUpdaterService;
private readonly IStatsService _statsService;
private readonly ICleanupService _cleanupService;
private readonly IEmailService _emailService;
private readonly IBookmarkService _bookmarkService;
public ServerController(IHostApplicationLifetime applicationLifetime, ILogger<ServerController> logger, IConfiguration config,
IBackupService backupService, IArchiveService archiveService, IVersionUpdaterService versionUpdaterService, IStatsService statsService,
ICleanupService cleanupService, IEmailService emailService, IBookmarkService bookmarkService)
{
_applicationLifetime = applicationLifetime;
_logger = logger;
_config = config;
_backupService = backupService;
_archiveService = archiveService;
_versionUpdaterService = versionUpdaterService;
_statsService = statsService;
_cleanupService = cleanupService;
_emailService = emailService;
_bookmarkService = bookmarkService;
}
/// <summary>
/// Attempts to Restart the server. Does not work, will shutdown the instance.
/// </summary>
/// <returns></returns>
[HttpPost("restart")]
public ActionResult RestartServer()
{
_logger.LogInformation("{UserName} is restarting server from admin dashboard", User.GetUsername());
_applicationLifetime.StopApplication();
return Ok();
}
/// <summary>
/// Performs an ad-hoc cleanup of Cache
/// </summary>
/// <returns></returns>
[HttpPost("clear-cache")]
public ActionResult ClearCache()
{
_logger.LogInformation("{UserName} is clearing cache of server from admin dashboard", User.GetUsername());
_cleanupService.CleanupCacheDirectory();
return Ok();
}
/// <summary>
/// Performs an ad-hoc backup of the Database
/// </summary>
/// <returns></returns>
[HttpPost("backup-db")]
public ActionResult BackupDatabase()
{
_logger.LogInformation("{UserName} is backing up database of server from admin dashboard", User.GetUsername());
RecurringJob.Trigger("backup");
return Ok();
}
/// <summary>
/// Returns non-sensitive information about the current system
/// </summary>
/// <returns></returns>
[HttpGet("server-info")]
public async Task<ActionResult<ServerInfoDto>> GetVersion()
{
return Ok(await _statsService.GetServerInfo());
}
/// <summary>
/// Triggers the scheduling of the convert bookmarks job. Only one job will run at a time.
/// </summary>
/// <returns></returns>
[HttpPost("convert-bookmarks")]
public ActionResult ScheduleConvertBookmarks()
{
BackgroundJob.Enqueue(() => _bookmarkService.ConvertAllBookmarkToWebP());
return Ok();
}
[HttpGet("logs")]
public ActionResult GetLogs()
{
var files = _backupService.GetLogFiles(_config.GetMaxRollingFiles(), _config.GetLoggingFileName());
try
{
var zipPath = _archiveService.CreateZipForDownload(files, "logs");
return PhysicalFile(zipPath, "application/zip", Path.GetFileName(zipPath), true);
}
catch (KavitaException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// Checks for updates, if no updates that are > current version installed, returns null
/// </summary>
[HttpGet("check-update")]
public async Task<ActionResult<UpdateNotificationDto>> CheckForUpdates()
{
return Ok(await _versionUpdaterService.CheckForUpdate());
}
[HttpGet("changelog")]
public async Task<ActionResult<IEnumerable<UpdateNotificationDto>>> GetChangelog()
{
return Ok(await _versionUpdaterService.GetAllReleases());
}
/// <summary>
/// Is this server accessible to the outside net
/// </summary>
/// <returns></returns>
[HttpGet("accessible")]
[AllowAnonymous]
public async Task<ActionResult<bool>> IsServerAccessible()
{
return await _emailService.CheckIfAccessible(Request.Host.ToString());
}
[HttpGet("jobs")]
public ActionResult<IEnumerable<JobDto>> GetJobs()
{
var recurringJobs = Hangfire.JobStorage.Current.GetConnection().GetRecurringJobs().Select(
dto =>
new JobDto() {
Id = dto.Id,
Title = dto.Id.Replace('-', ' '),
Cron = dto.Cron,
CreatedAt = dto.CreatedAt,
LastExecution = dto.LastExecution,
});
// For now, let's just do something simple
//var enqueuedJobs = JobStorage.Current.GetMonitoringApi().EnqueuedJobs("default", 0, int.MaxValue);
return Ok(recurringJobs);
}
}
}