From 37ebf0ffa041f1020dce5f6dfd2e6a99ef6c7853 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Tue, 22 Aug 2023 12:44:05 +0500 Subject: [PATCH] Add periodic guild data saving (every 5 minutes) (#99) This PR adds a BackgroundGuildDataSaverService which will save all guild data to disk every 5 minutes using a PeriodicTimer. Closes #96 Signed-off-by: Octol1ttle --- src/Boyfriend.cs | 1 + .../BackgroundGuildDataSaverService.cs | 23 +++++++++++++++++++ src/Services/GuildDataService.cs | 12 ++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 src/Services/BackgroundGuildDataSaverService.cs diff --git a/src/Boyfriend.cs b/src/Boyfriend.cs index 7fdbbb2..246869e 100644 --- a/src/Boyfriend.cs +++ b/src/Boyfriend.cs @@ -92,6 +92,7 @@ public sealed class Boyfriend .AddHostedService() .AddHostedService() .AddHostedService() + .AddHostedService() // Slash commands .AddCommandTree() .WithCommandGroup() diff --git a/src/Services/BackgroundGuildDataSaverService.cs b/src/Services/BackgroundGuildDataSaverService.cs new file mode 100644 index 0000000..76a7ddb --- /dev/null +++ b/src/Services/BackgroundGuildDataSaverService.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Hosting; + +namespace Boyfriend.Services; + +public sealed class BackgroundGuildDataSaverService : BackgroundService +{ + private readonly GuildDataService _guildData; + + public BackgroundGuildDataSaverService(GuildDataService guildData) + { + _guildData = guildData; + } + + protected override async Task ExecuteAsync(CancellationToken ct) + { + using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5)); + + while (await timer.WaitForNextTickAsync(ct)) + { + await _guildData.SaveAsync(ct); + } + } +} diff --git a/src/Services/GuildDataService.cs b/src/Services/GuildDataService.cs index 0ded110..26147d2 100644 --- a/src/Services/GuildDataService.cs +++ b/src/Services/GuildDataService.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Nodes; using Boyfriend.Data; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Remora.Discord.API.Abstractions.Rest; using Remora.Rest.Core; @@ -15,12 +16,14 @@ public sealed class GuildDataService : IHostedService { private readonly ConcurrentDictionary _datas = new(); private readonly IDiscordRestGuildAPI _guildApi; + private readonly ILogger _logger; // https://github.com/dotnet/aspnetcore/issues/39139 public GuildDataService( - IHostApplicationLifetime lifetime, IDiscordRestGuildAPI guildApi) + IHostApplicationLifetime lifetime, IDiscordRestGuildAPI guildApi, ILogger logger) { _guildApi = guildApi; + _logger = logger; lifetime.ApplicationStopping.Register(ApplicationStopping); } @@ -39,8 +42,9 @@ public sealed class GuildDataService : IHostedService SaveAsync(CancellationToken.None).GetAwaiter().GetResult(); } - private async Task SaveAsync(CancellationToken ct) + public async Task SaveAsync(CancellationToken ct) { + _logger.LogInformation("Saving guild data..."); var tasks = new List(); foreach (var data in _datas.Values) { @@ -89,7 +93,7 @@ public sealed class GuildDataService : IHostedService await using var eventsStream = File.OpenRead(scheduledEventsPath); var events - = JsonSerializer.DeserializeAsync>( + = await JsonSerializer.DeserializeAsync>( eventsStream, cancellationToken: ct); var memberData = new Dictionary(); @@ -113,7 +117,7 @@ public sealed class GuildDataService : IHostedService var finalData = new GuildData( jsonSettings ?? new JsonObject(), settingsPath, - await events ?? new Dictionary(), scheduledEventsPath, + events ?? new Dictionary(), scheduledEventsPath, memberData, memberDataPath); _datas.TryAdd(guildId, finalData);