Fix preference loading bugs (#27742)
First bug: if an error occured during pref loading code, it would fail. If the person then readied up, it would likely cause the round to fail to start. Why could they ready up? The code only checks that the prefs finished loading, not that they finished loading *successfully*. Whoops. Anyways, now people get kicked if their prefs fail to load. And I improved the error handling. Second bug: if a user disconnected while their prefs were loading, it would cause an exception. This exception would go unobserved on lobby servers or raise through gameticker on non-lobby servers. This happened even on a live server once and then triggered the first bug, but idk how. Fixed this by properly plumbing through cancellation into the preferences loading code. The stuff is now cancelled properly. Third bug: if somebody has a loadout item with a playtime requirement active, load-time sanitization of player prefs could run into a race condition because the sanitization can happen *before* play time was loaded. Fixed by moving pref sanitizations to a later stage in the load process.
This commit is contained in:
committed by
GitHub
parent
61c1aeddf3
commit
7a38b22ddb
@@ -33,9 +33,11 @@ namespace Content.Server.Database
|
||||
}
|
||||
|
||||
#region Preferences
|
||||
public async Task<PlayerPreferences?> GetPlayerPreferencesAsync(NetUserId userId)
|
||||
public async Task<PlayerPreferences?> GetPlayerPreferencesAsync(
|
||||
NetUserId userId,
|
||||
CancellationToken cancel = default)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
var prefs = await db.DbContext
|
||||
.Preference
|
||||
@@ -47,7 +49,7 @@ namespace Content.Server.Database
|
||||
.ThenInclude(l => l.Groups)
|
||||
.ThenInclude(group => group.Loadouts)
|
||||
.AsSingleQuery()
|
||||
.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
|
||||
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
|
||||
|
||||
if (prefs is null)
|
||||
return null;
|
||||
@@ -515,13 +517,13 @@ namespace Content.Server.Database
|
||||
#endregion
|
||||
|
||||
#region Playtime
|
||||
public async Task<List<PlayTime>> GetPlayTimes(Guid player)
|
||||
public async Task<List<PlayTime>> GetPlayTimes(Guid player, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
return await db.DbContext.PlayTime
|
||||
.Where(p => p.PlayerId == player)
|
||||
.ToListAsync();
|
||||
.ToListAsync(cancel);
|
||||
}
|
||||
|
||||
public async Task UpdatePlayTimes(IReadOnlyCollection<PlayTimeUpdate> updates)
|
||||
@@ -673,7 +675,7 @@ namespace Content.Server.Database
|
||||
*/
|
||||
public async Task<Admin?> GetAdminDataForAsync(NetUserId userId, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
return await db.DbContext.Admin
|
||||
.Include(p => p.Flags)
|
||||
@@ -688,7 +690,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task<AdminRank?> GetAdminRankDataForAsync(int id, CancellationToken cancel = default)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
return await db.DbContext.AdminRank
|
||||
.Include(r => r.Flags)
|
||||
@@ -697,7 +699,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task RemoveAdminAsync(NetUserId userId, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
var admin = await db.DbContext.Admin.SingleAsync(a => a.UserId == userId.UserId, cancel);
|
||||
db.DbContext.Admin.Remove(admin);
|
||||
@@ -707,7 +709,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task AddAdminAsync(Admin admin, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
db.DbContext.Admin.Add(admin);
|
||||
|
||||
@@ -716,7 +718,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task UpdateAdminAsync(Admin admin, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
var existing = await db.DbContext.Admin.Include(a => a.Flags).SingleAsync(a => a.UserId == admin.UserId, cancel);
|
||||
existing.Flags = admin.Flags;
|
||||
@@ -728,7 +730,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task RemoveAdminRankAsync(int rankId, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
var admin = await db.DbContext.AdminRank.SingleAsync(a => a.Id == rankId, cancel);
|
||||
db.DbContext.AdminRank.Remove(admin);
|
||||
@@ -738,7 +740,7 @@ namespace Content.Server.Database
|
||||
|
||||
public async Task AddAdminRankAsync(AdminRank rank, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
db.DbContext.AdminRank.Add(rank);
|
||||
|
||||
@@ -811,7 +813,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
public async Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
await using var db = await GetDb(cancel);
|
||||
|
||||
var existing = await db.DbContext.AdminRank
|
||||
.Include(r => r.Flags)
|
||||
@@ -1594,7 +1596,9 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return db.DbContext.Database.HasPendingModelChanges();
|
||||
}
|
||||
|
||||
protected abstract Task<DbGuard> GetDb([CallerMemberName] string? name = null);
|
||||
protected abstract Task<DbGuard> GetDb(
|
||||
CancellationToken cancel = default,
|
||||
[CallerMemberName] string? name = null);
|
||||
|
||||
protected void LogDbOp(string? name)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user