Skip to content

Commit

Permalink
Use precached giveaways rather than fetching from DB separately
Browse files Browse the repository at this point in the history
Fixed a bug where modification of disparate instances caused winner selection to fail in spectacular ways
  • Loading branch information
oliverbooth committed Dec 28, 2022
1 parent e7d0918 commit 5871aae
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 14 deletions.
21 changes: 7 additions & 14 deletions Present/Services/ActiveGiveawayService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Timers;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
using Present.Data;
using Humanizer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog;
using Timer = System.Timers.Timer;
Expand All @@ -17,19 +16,16 @@ namespace Present.Services;
internal sealed class ActiveGiveawayService : BackgroundService
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly GiveawayService _giveawayService;
private readonly ConcurrentDictionary<ulong, List<Giveaway>> _activeGiveaways = new();
private readonly Timer _giveawayTimer = new();

/// <summary>
/// Initializes a new instance of the <see cref="ActiveGiveawayService" /> class.
/// </summary>
/// <param name="serviceScopeFactory">The service scope factory.</param>
/// <param name="giveawayService">The giveaway service.</param>
public ActiveGiveawayService(IServiceScopeFactory serviceScopeFactory, GiveawayService giveawayService)
public ActiveGiveawayService(GiveawayService giveawayService)
{
_serviceScopeFactory = serviceScopeFactory;
_giveawayService = giveawayService;

_giveawayTimer.Interval = 1000;
Expand Down Expand Up @@ -115,12 +111,13 @@ public void RemoveActiveGiveaway(Giveaway giveaway)
}

/// <inheritdoc />
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Logger.Debug($"Starting timer with interval {_giveawayTimer.Interval}");
_giveawayTimer.Start();

await UpdateFromDatabaseAsync(stoppingToken).ConfigureAwait(false);
UpdateFromDatabase();
return Task.CompletedTask;
}

private async void GiveawayTimerOnElapsed(object? sender, ElapsedEventArgs e)
Expand Down Expand Up @@ -169,15 +166,11 @@ private async Task HandleExpiredGiveawayAsync(Giveaway giveaway)
}
}

private async Task UpdateFromDatabaseAsync(CancellationToken cancellationToken)
private void UpdateFromDatabase()
{
Logger.Info("Loading active giveaways from the database...");

await using AsyncServiceScope scope = _serviceScopeFactory.CreateAsyncScope();
await using var context = scope.ServiceProvider.GetRequiredService<GiveawayContext>();
await context.Database.EnsureCreatedAsync(cancellationToken: cancellationToken).ConfigureAwait(false);

await foreach (Giveaway giveaway in context.Giveaways)
foreach (Giveaway giveaway in _giveawayService.Giveaways)
AddActiveGiveaway(giveaway);

Logger.Info($"Loaded {"active giveaway".ToQuantity(_activeGiveaways.Count)} from the database");
Expand Down
6 changes: 6 additions & 0 deletions Present/Services/GiveawayService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Random random
_random = random;
}

/// <summary>
/// Gets a read-only view of every loaded giveaway.
/// </summary>
/// <value>A <see cref="IReadOnlyList{T}" /> of giveaways.</value>
public IReadOnlyList<Giveaway> Giveaways => _giveaways.Values.ToArray();

/// <summary>
/// Announces the giveaway in the channel which the giveaway is hosted.
/// </summary>
Expand Down

0 comments on commit 5871aae

Please sign in to comment.