diff --git a/API/Services/Tasks/StatsService.cs b/API/Services/Tasks/StatsService.cs index 47087fc8d..70eaecf7d 100644 --- a/API/Services/Tasks/StatsService.cs +++ b/API/Services/Tasks/StatsService.cs @@ -10,6 +10,7 @@ using API.DTOs.Stats; using API.Interfaces; using API.Interfaces.Services; using API.Services.Clients; +using Hangfire; using Kavita.Common; using Kavita.Common.EnvironmentInfo; using Microsoft.EntityFrameworkCore; @@ -67,14 +68,8 @@ namespace API.Services.Tasks { try { - _logger.LogDebug("Finalizing Stats collection flow"); - var data = await GetExistingData(); - - _logger.LogDebug("Sending data to the Stats server"); await _client.SendDataToStatsServer(data); - - _logger.LogDebug("Deleting the file from disk"); if (FileExists) File.Delete(FinalPath); } catch (Exception ex) @@ -84,6 +79,10 @@ namespace API.Services.Tasks } } + /// + /// Due to all instances firing this at the same time, we can DDOS our server. This task when fired will schedule the task to be run + /// randomly over a 6 hour spread + /// public async Task CollectAndSendStatsData() { var allowStatCollection = (await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).AllowStatCollection; @@ -92,6 +91,27 @@ namespace API.Services.Tasks _logger.LogDebug("User has opted out of stat collection, not registering tasks"); return; } + + var rnd = new Random(); + var offset = rnd.Next(0, 6); + if (offset == 0) + { + await SendData(); + } + else + { + _logger.LogInformation("KavitaStats upload has been schedule to run in {Offset} hours", offset); + BackgroundJob.Schedule(() => SendData(), DateTimeOffset.Now.AddHours(offset)); + } + } + + /// + /// This must be public for Hangfire. Do not call this directly. + /// + // ReSharper disable once MemberCanBePrivate.Global + public async Task SendData() + { + _logger.LogDebug("Sending data to the Stats server"); await CollectRelevantData(); await FinalizeStats(); }