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);