From 80c831b0a23ebcff4921c54bb8f7ffa9f85c383c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Kore=C4=8Dko?= Date: Fri, 26 Dec 2025 14:53:33 +0100 Subject: [PATCH 1/2] done --- .../Services/Hosted/AbstractHostedService.cs | 34 ++++++++---- .../Services/Hosted/CleanupHostedService.cs | 8 +-- .../Services/Hosted/ReminderHostedService.cs | 14 ++--- .../Services/Hosted/RepeatHostedService.cs | 55 ++++++++----------- .../Services/Hosted/SnoozeHostedService.cs | 18 +++--- Ticky.Web/Components/Pages/UserSettings.razor | 1 - 6 files changed, 59 insertions(+), 71 deletions(-) diff --git a/Ticky.Internal/Services/Hosted/AbstractHostedService.cs b/Ticky.Internal/Services/Hosted/AbstractHostedService.cs index 47ec71c..8fdaa68 100644 --- a/Ticky.Internal/Services/Hosted/AbstractHostedService.cs +++ b/Ticky.Internal/Services/Hosted/AbstractHostedService.cs @@ -11,7 +11,7 @@ public abstract class AbstractHostedService : IHostedService private TimeSpan _untilStart; private TimeSpan _frequency; - public AbstractHostedService( + protected AbstractHostedService( IServiceScopeFactory serviceScopeFactory, TimeSpan untilStart, TimeSpan frequency @@ -34,7 +34,7 @@ public Task StartAsync(CancellationToken cancellationToken) { using var scope = ServiceScopeFactory.CreateScope(); - Logger.LogDebug($"{GetType().Name} starting."); + Logger.LogDebug("{Name} starting.", GetType().Name); OnStart(); @@ -45,7 +45,7 @@ public Task StopAsync(CancellationToken cancellationToken) { using var scope = ServiceScopeFactory.CreateScope(); - Logger.LogDebug($"{GetType().Name} stopping."); + Logger.LogDebug("{Name} stopping.", GetType().Name); _timer!.Change(Timeout.Infinite, 0); Dispose(); @@ -53,18 +53,25 @@ public Task StopAsync(CancellationToken cancellationToken) return Task.CompletedTask; } - private void DoWork(object? state) + private async void DoWork(object? state) { - var startedAt = DateTime.Now; - using var scope = ServiceScopeFactory.CreateScope(); + try + { + var startedAt = DateTime.Now; + using var scope = ServiceScopeFactory.CreateScope(); - Logger.LogDebug($"{GetType().Name} job running."); + Logger.LogDebug("{Name} job running.", GetType().Name); - OnRun(); + await OnRun(); - Logger.LogDebug( - $"{GetType().Name} job finished, next run will happen at {GetNextRunDateTime(startedAt)}." - ); + Logger.LogDebug( + "{Name} job finished, next run will happen at {GetNextRunDateTime}.", GetType().Name, GetNextRunDateTime(startedAt) + ); + } + catch (Exception ex) + { + Logger.LogError(ex, ex.Message); + } } private string GetNextRunDateTime(DateTime startedAt) @@ -90,7 +97,10 @@ protected virtual void OnStart() { } protected virtual void OnStop() { } - protected virtual void OnRun() { } + protected virtual Task OnRun() + { + return Task.CompletedTask; + } public void Dispose() { diff --git a/Ticky.Internal/Services/Hosted/CleanupHostedService.cs b/Ticky.Internal/Services/Hosted/CleanupHostedService.cs index dd98fd0..72a78ad 100644 --- a/Ticky.Internal/Services/Hosted/CleanupHostedService.cs +++ b/Ticky.Internal/Services/Hosted/CleanupHostedService.cs @@ -1,11 +1,9 @@ namespace Ticky.Internal.Services.Hosted; -public class CleanupHostedService : AbstractHostedService +public class CleanupHostedService(IServiceScopeFactory serviceScopeFactory) + : AbstractHostedService(serviceScopeFactory, TimeSpan.FromMinutes(15), TimeSpan.FromHours(1)) { - public CleanupHostedService(IServiceScopeFactory serviceScopeFactory) - : base(serviceScopeFactory, TimeSpan.FromMinutes(15), TimeSpan.FromHours(1)) { } - - protected override async void OnRun() + protected override async Task OnRun() { await CleanCodes(); await DeleteUnusedProfilePictures(); diff --git a/Ticky.Internal/Services/Hosted/ReminderHostedService.cs b/Ticky.Internal/Services/Hosted/ReminderHostedService.cs index 0c02c09..a31a7b0 100644 --- a/Ticky.Internal/Services/Hosted/ReminderHostedService.cs +++ b/Ticky.Internal/Services/Hosted/ReminderHostedService.cs @@ -1,15 +1,11 @@ namespace Ticky.Internal.Services.Hosted; -public class ReminderHostedService : AbstractHostedService +public class ReminderHostedService(IServiceScopeFactory serviceScopeFactory) + : AbstractHostedService(serviceScopeFactory, + TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), + TimeSpan.FromMinutes(2)) { - public ReminderHostedService(IServiceScopeFactory serviceScopeFactory) - : base( - serviceScopeFactory, - TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), - TimeSpan.FromMinutes(2) - ) { } - - protected override async void OnRun() + protected override async Task OnRun() { using var scope = ServiceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService()!; diff --git a/Ticky.Internal/Services/Hosted/RepeatHostedService.cs b/Ticky.Internal/Services/Hosted/RepeatHostedService.cs index 6204e72..7ea9916 100644 --- a/Ticky.Internal/Services/Hosted/RepeatHostedService.cs +++ b/Ticky.Internal/Services/Hosted/RepeatHostedService.cs @@ -1,15 +1,11 @@ namespace Ticky.Internal.Services.Hosted; -public class RepeatHostedService : AbstractHostedService +public class RepeatHostedService(IServiceScopeFactory serviceScopeFactory) : AbstractHostedService( + serviceScopeFactory, + TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), + TimeSpan.FromMinutes(2)) { - public RepeatHostedService(IServiceScopeFactory serviceScopeFactory) - : base( - serviceScopeFactory, - TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), - TimeSpan.FromMinutes(2) - ) { } - - protected override async void OnRun() + protected override async Task OnRun() { using var scope = ServiceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService()!; @@ -17,7 +13,14 @@ protected override async void OnRun() var cardNumberingService = scope.ServiceProvider.GetRequiredService()!; - var allRepeatCards = await db + var allRepeatCards = await db.Cards.Where(x => x.RepeatInfo != null).ToListAsync(); + + var pendingNextRepeatCardIds = allRepeatCards + .Where(x => x.CalculateNextRepeat(DateTime.Now) < DateTime.Now) + .Select(x => x.Id) + .ToList(); + + var populatedPendingRepeatCards = await db .Cards.Include(x => x.Column) .ThenInclude(x => x.Board) .Include(x => x.Subtasks) @@ -29,14 +32,10 @@ protected override async void OnRun() .Include(x => x.LinkedIssuesOne) .Include(x => x.LinkedIssuesTwo) .ThenInclude(x => x.CardOne) - .Where(x => x.RepeatInfo != null) + .Where(x => pendingNextRepeatCardIds.Contains(x.Id)) .ToListAsync(); - var pendingNextRepeatCards = allRepeatCards - .Where(x => x.CalculateNextRepeat(DateTime.Now) < DateTime.Now) - .ToList(); - - foreach (var card in pendingNextRepeatCards) + foreach (var card in populatedPendingRepeatCards) { card.RepeatInfo!.LastRepeat = DateTime.Now; @@ -119,14 +118,9 @@ protected override async void OnRun() ? Constants.LINK_TYPE_PAIRS[Constants.REPEATED_KEY] : Constants.LINK_TYPE_PAIRS.First(x => x.Value.Equals(Constants.REPEATED_KEY)).Key; - foreach (var linkedIssueOne in card.LinkedIssuesOne) + foreach (var linkedIssueOne in card.LinkedIssuesOne.Where(linkedIssueOne => !linkedIssueOne.Category.Equals(Constants.REPEATED_KEY) + && !linkedIssueOne.Category.Equals(oppositeCategory))) { - if ( - linkedIssueOne.Category.Equals(Constants.REPEATED_KEY) - || linkedIssueOne.Category.Equals(oppositeCategory) - ) - continue; - newCard.LinkedIssuesOne.Add( new() { @@ -137,14 +131,9 @@ protected override async void OnRun() ); } - foreach (var linkedIssueTwo in card.LinkedIssuesTwo) + foreach (var linkedIssueTwo in card.LinkedIssuesTwo.Where(linkedIssueTwo => !linkedIssueTwo.Category.Equals(Constants.REPEATED_KEY) + && !linkedIssueTwo.Category.Equals(oppositeCategory))) { - if ( - linkedIssueTwo.Category.Equals(Constants.REPEATED_KEY) - || linkedIssueTwo.Category.Equals(oppositeCategory) - ) - continue; - newCard.LinkedIssuesTwo.Add( new() { @@ -189,17 +178,17 @@ protected override async void OnRun() targetColumn.Cards.ForEach(x => x.Index++); else if ( card.RepeatInfo.CardPlacement.Equals(CardPlacement.Bottom) - && targetColumn.Cards.Any() + && targetColumn.Cards.Count != 0 ) newCard.Index = targetColumn.Cards.Max(x => x.Index) + 1; else throw new Exception("Unsupported card placement type"); } - if (pendingNextRepeatCards.Any()) + if (populatedPendingRepeatCards.Count != 0) { await db.SaveChangesAsync(); - logger.LogInformation($"{pendingNextRepeatCards.Count()} cards have been repeated."); + logger.LogInformation($"{populatedPendingRepeatCards.Count} cards have been repeated."); } } } diff --git a/Ticky.Internal/Services/Hosted/SnoozeHostedService.cs b/Ticky.Internal/Services/Hosted/SnoozeHostedService.cs index f198bc4..0c09dfd 100644 --- a/Ticky.Internal/Services/Hosted/SnoozeHostedService.cs +++ b/Ticky.Internal/Services/Hosted/SnoozeHostedService.cs @@ -1,15 +1,11 @@ namespace Ticky.Internal.Services.Hosted; -public class SnoozeHostedService : AbstractHostedService +public class SnoozeHostedService(IServiceScopeFactory serviceScopeFactory) : AbstractHostedService( + serviceScopeFactory, + TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), + TimeSpan.FromMinutes(2)) { - public SnoozeHostedService(IServiceScopeFactory serviceScopeFactory) - : base( - serviceScopeFactory, - TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY), - TimeSpan.FromMinutes(2) - ) { } - - protected override async void OnRun() + protected override async Task OnRun() { using var scope = ServiceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService()!; @@ -24,10 +20,10 @@ protected override async void OnRun() card.SnoozedUntil = null; } - if (expiredSnoozes.Any()) + if (expiredSnoozes.Count != 0) { await db.SaveChangesAsync(); - logger.LogInformation($"{expiredSnoozes.Count} cards unsnoozed."); + logger.LogInformation("{ExpiredSnoozesCount} cards unsnoozed.", expiredSnoozes.Count); } } } diff --git a/Ticky.Web/Components/Pages/UserSettings.razor b/Ticky.Web/Components/Pages/UserSettings.razor index 19d15a7..f96fbe3 100644 --- a/Ticky.Web/Components/Pages/UserSettings.razor +++ b/Ticky.Web/Components/Pages/UserSettings.razor @@ -4,7 +4,6 @@ @inject ILogger _logger @inject AvatarService _avatarService @inject UserManager _userManager -@inject ILogger _logger @inject NavigationManager _navigationManager @inherits NotifiableBase @implements IDisposable From 59793db08e2e65e5a988a09074757f23e26ae50c Mon Sep 17 00:00:00 2001 From: dkorecko <22599403+dkorecko@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:55:51 +0100 Subject: [PATCH 2/2] Update Ticky.Internal/Services/Hosted/RepeatHostedService.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Ticky.Internal/Services/Hosted/RepeatHostedService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ticky.Internal/Services/Hosted/RepeatHostedService.cs b/Ticky.Internal/Services/Hosted/RepeatHostedService.cs index 7ea9916..afb716a 100644 --- a/Ticky.Internal/Services/Hosted/RepeatHostedService.cs +++ b/Ticky.Internal/Services/Hosted/RepeatHostedService.cs @@ -188,7 +188,7 @@ protected override async Task OnRun() if (populatedPendingRepeatCards.Count != 0) { await db.SaveChangesAsync(); - logger.LogInformation($"{populatedPendingRepeatCards.Count} cards have been repeated."); + logger.LogInformation("{Count} cards have been repeated.", populatedPendingRepeatCards.Count); } } }