Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions GenOnlineService/ExternalLeaderboardsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Polly;

Expand Down Expand Up @@ -122,7 +123,7 @@ private static SocketsHttpHandler CreateLeaderboardsHandler()
};
}

public static async Task PostMatchResultAsync(AppDbContext db, Lobby lobby)
public static async Task PostMatchResultAsync(IDbContextFactory<AppDbContext> dbFactory, Lobby lobby)
{
if (lobby.MatchID == 0)
return;
Expand All @@ -131,8 +132,13 @@ public static async Task PostMatchResultAsync(AppDbContext db, Lobby lobby)
{
GetExternalLeaderboardsConfig(out string postUrl, out _, out string postToken, out _);

// Load the match payload
var matchEntry = await Database.MatchHistory.LoadMatchHistoryEntryAsync(db, (long)lobby.MatchID);
// Dispose the read context before the potentially multi-minute external request below.
Controllers.MatchHistory_Entry? matchEntry;
await using (var readDb = await dbFactory.CreateDbContextAsync())
{
matchEntry = await Database.MatchHistory.LoadMatchHistoryEntryAsync(readDb, (long)lobby.MatchID);
}

if (matchEntry == null)
{
Console.WriteLine($"[WARNING] MatchHistory entry not found for match ID {lobby.MatchID}");
Expand Down Expand Up @@ -206,6 +212,9 @@ await retryPolicy.ExecuteAsync(async () =>
// Only player IDs that were actually part of this match are valid recipients of an ELO update.
var expectedPlayerIds = new HashSet<long>(matchEntry.members.Where(m => m.HasValue).Select(m => m.Value.user_id));

// Fresh, short-lived context just for the persistence writes below.
await using var writeDb = await dbFactory.CreateDbContextAsync();

foreach (var (userId, updatedPlayer) in refreshResponse.data)
{
if (!expectedPlayerIds.Contains(userId))
Expand All @@ -228,7 +237,7 @@ await retryPolicy.ExecuteAsync(async () =>
}

// Call SaveELOData to persist as fallback
await Database.Users.SaveELOData(db, userId, new EloData(newRating, newMonthlyRating, newMatches));
await Database.Users.SaveELOData(writeDb, userId, new EloData(newRating, newMonthlyRating, newMatches));
}
}
catch (Exception ex)
Expand Down
15 changes: 7 additions & 8 deletions GenOnlineService/LobbyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1406,15 +1406,10 @@ public class LobbyManager
private Int64 m_NextLobbyID = 0;

private readonly IServiceProvider _services;
private readonly AppDbContext _db;

public LobbyManager(IServiceProvider services)
{
_services = services;

var scope = _services.CreateScope();
var factory = scope.ServiceProvider.GetRequiredService<IDbContextFactory<AppDbContext>>();
var _db = factory.CreateDbContext();
}

public async Task Cleanup()
Expand Down Expand Up @@ -1720,13 +1715,17 @@ public async Task<bool> DeleteLobby(Lobby lobby)
{
try
{
using var scope = _services.CreateScope();
var factory = scope.ServiceProvider.GetRequiredService<IDbContextFactory<AppDbContext>>();
await using var db = await factory.CreateDbContextAsync();

if (lobby.State != ELobbyState.COMPLETE)
{
// make done
await lobby.UpdateState(ELobbyState.COMPLETE);

// attempt to commit it
await Database.MatchHistory.CommitLobbyToMatchHistory(_db, lobby);
await Database.MatchHistory.CommitLobbyToMatchHistory(db, lobby);
}

// delete
Expand All @@ -1740,11 +1739,11 @@ public async Task<bool> DeleteLobby(Lobby lobby)
lobby.OnLobbyNeedsDestroyed -= HandleLobbyNeedsDestroyed;

// make sure we have a winner
await Database.MatchHistory.DetermineLobbyWinnerIfNotPresent(_db, lobby);
await Database.MatchHistory.DetermineLobbyWinnerIfNotPresent(db, lobby);

// Post match result to external leaderboard API for every lobby type.
// Only QuickMatch responses are expected to carry a ratings body.
await ExternalLeaderboardsClient.PostMatchResultAsync(_db, lobby);
await ExternalLeaderboardsClient.PostMatchResultAsync(factory, lobby);
}

return bRemoved;
Expand Down