From d072cb61440e9eba80f6d9d8dc4a42f94bb8c37d Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 7 May 2023 03:14:23 -0700 Subject: [PATCH] Fix admin logs duplicate id error when running tests (#16203) --- .../Logs/AdminLogManager.Cache.cs | 5 --- .../Logs/AdminLogManager.Json.cs | 10 +++-- .../Administration/Logs/AdminLogManager.cs | 43 +++++++++++-------- .../Administration/Logs/QueuedLog.cs | 22 ---------- Content.Server/Database/ServerDbBase.cs | 21 +-------- Content.Server/Database/ServerDbManager.cs | 4 +- Content.Server/Database/ServerDbSqlite.cs | 38 ---------------- 7 files changed, 35 insertions(+), 108 deletions(-) delete mode 100644 Content.Server/Administration/Logs/QueuedLog.cs diff --git a/Content.Server/Administration/Logs/AdminLogManager.Cache.cs b/Content.Server/Administration/Logs/AdminLogManager.Cache.cs index daa61fbb84..c194527d82 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.Cache.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.Cache.cs @@ -53,11 +53,6 @@ public sealed partial class AdminLogManager CacheLog(record); } - private void CacheLog(QueuedLog log) - { - CacheLog(log.Log); - } - private void CacheLog(SharedAdminLog log) { // TODO ADMIN LOGS remove redundant data and don't do a dictionary lookup per log diff --git a/Content.Server/Administration/Logs/AdminLogManager.Json.cs b/Content.Server/Administration/Logs/AdminLogManager.Json.cs index d5d073ff44..d4026545ee 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.Json.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.Json.cs @@ -2,6 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Content.Server.Administration.Logs.Converters; +using Content.Server.Database; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -32,10 +33,10 @@ public sealed partial class AdminLogManager _sawmill.Debug($"Admin log converters found: {string.Join(" ", converterNames)}"); } - private (JsonDocument json, HashSet players, Dictionary entities) ToJson( + private (JsonDocument Json, HashSet Players, List Entities) ToJson( Dictionary properties) { - var entities = new Dictionary(); + var entities = new Dictionary(); var players = new HashSet(); var parsed = new Dictionary(); @@ -69,7 +70,8 @@ public sealed partial class AdminLogManager ? metadata.EntityName : null; - entities.TryAdd((int) uid, entityName); + // TODO set the id too whenever we feel like running a migration for 10 hours + entities.TryAdd(uid, new AdminLogEntity { Name = entityName }); if (_entityManager.TryGetComponent(uid, out ActorComponent? actor)) { @@ -77,6 +79,6 @@ public sealed partial class AdminLogManager } } - return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities); + return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities.Values.ToList()); } } diff --git a/Content.Server/Administration/Logs/AdminLogManager.cs b/Content.Server/Administration/Logs/AdminLogManager.cs index 8959fb1a13..fe0c3fe24e 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.cs @@ -68,8 +68,8 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa // Per update private TimeSpan _nextUpdateTime; - private readonly ConcurrentQueue _logQueue = new(); - private readonly ConcurrentQueue _preRoundLogQueue = new(); + private readonly ConcurrentQueue _logQueue = new(); + private readonly ConcurrentQueue _preRoundLogQueue = new(); // Per round private int _currentRoundId; @@ -171,7 +171,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa _nextUpdateTime = _timing.RealTime.Add(_queueSendDelay); // TODO ADMIN LOGS array pool - var copy = new List(_logQueue.Count + _preRoundLogQueue.Count); + var copy = new List(_logQueue.Count + _preRoundLogQueue.Count); copy.AddRange(_logQueue); _logQueue.Clear(); @@ -183,10 +183,10 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa } else { - foreach (var queued in _preRoundLogQueue) + foreach (var log in _preRoundLogQueue) { - queued.Log.RoundId = _currentRoundId; - CacheLog(queued); + log.RoundId = _currentRoundId; + CacheLog(log); } copy.AddRange(_preRoundLogQueue); @@ -231,6 +231,17 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa { Interlocked.Exchange(ref _currentLogId, 0); + if (!_preRoundLogQueue.IsEmpty) + { + // This technically means that you could get pre-round logs from + // a previous round passed onto the next one + // If this happens please file a complaint with your nearest lottery + foreach (var log in _preRoundLogQueue) + { + log.Id = NextLogId; + } + } + if (_metricsEnabled) { PreRoundQueueCapReached.Set(0); @@ -240,30 +251,26 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa } } - private async void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players, Dictionary entities) + private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players, List entities) { - var logId = NextLogId; - var date = DateTime.UtcNow; - var log = new AdminLog { - Id = logId, + Id = NextLogId, RoundId = _currentRoundId, Type = type, Impact = impact, - Date = date, + Date = DateTime.UtcNow, Message = message, Json = json, - Players = new List(players.Count) + Players = new List(players.Count), + Entities = entities }; - var queued = new QueuedLog(log, entities); - foreach (var id in players) { var player = new AdminLogPlayer { - LogId = logId, + LogId = log.Id, PlayerUserId = id }; @@ -272,11 +279,11 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa if (_runLevel == GameRunLevel.PreRoundLobby) { - _preRoundLogQueue.Enqueue(queued); + _preRoundLogQueue.Enqueue(log); } else { - _logQueue.Enqueue(queued); + _logQueue.Enqueue(log); CacheLog(log); } } diff --git a/Content.Server/Administration/Logs/QueuedLog.cs b/Content.Server/Administration/Logs/QueuedLog.cs deleted file mode 100644 index ced0480fff..0000000000 --- a/Content.Server/Administration/Logs/QueuedLog.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Content.Server.Database; - -namespace Content.Server.Administration.Logs; - -public readonly struct QueuedLog -{ - public QueuedLog(AdminLog log, Dictionary entities) - { - Log = log; - Entities = entities; - } - - public AdminLog Log { get; } - - public Dictionary Entities { get; } - - public void Deconstruct(out AdminLog log, out Dictionary entities) - { - log = Log; - entities = Entities; - } -} diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index fb8b2e487f..0f7973aa97 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -12,7 +12,6 @@ using Content.Shared.Preferences; using Microsoft.EntityFrameworkCore; using Robust.Shared.Enums; using Robust.Shared.Network; -using Robust.Shared.Utility; namespace Content.Server.Database { @@ -717,26 +716,10 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id} return (server, false); } - public virtual async Task AddAdminLogs(List logs) + public async Task AddAdminLogs(List logs) { await using var db = await GetDb(); - - var entities = new Dictionary(); - - foreach (var (log, entityData) in logs) - { - var logEntities = new List(entityData.Count); - foreach (var (id, name) in entityData) - { - var entity = entities.GetOrNew(id); - entity.Name = name; - logEntities.Add(entity); - } - - log.Entities = logEntities; - db.DbContext.AdminLog.Add(log); - } - + db.DbContext.AdminLog.AddRange(logs); await db.DbContext.SaveChangesAsync(); } diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 718d56293a..0190013a8e 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -201,7 +201,7 @@ namespace Content.Server.Database #region Admin Logs Task AddOrGetServer(string serverName); - Task AddAdminLogs(List logs); + Task AddAdminLogs(List logs); IAsyncEnumerable GetAdminLogMessages(LogFilter? filter = null); IAsyncEnumerable GetAdminLogs(LogFilter? filter = null); IAsyncEnumerable GetAdminLogsJson(LogFilter? filter = null); @@ -564,7 +564,7 @@ namespace Content.Server.Database return server; } - public Task AddAdminLogs(List logs) + public Task AddAdminLogs(List logs) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.AddAdminLogs(logs)); diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index 99c43e8d50..57215d349d 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -3,14 +3,12 @@ using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; -using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Server.Preferences.Managers; using Content.Shared.CCVar; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; -using Robust.Shared.Utility; namespace Content.Server.Database { @@ -475,42 +473,6 @@ namespace Content.Server.Database return round.Id; } - public override async Task AddAdminLogs(List logs) - { - await using var db = await GetDb(); - - var nextId = 1; - if (await db.DbContext.AdminLog.AnyAsync()) - { - nextId = db.DbContext.AdminLog.Max(round => round.Id) + 1; - } - - var entities = new Dictionary(); - - foreach (var (log, entityData) in logs) - { - log.Id = nextId++; - - var logEntities = new List(entityData.Count); - foreach (var (id, name) in entityData) - { - var entity = entities.GetOrNew(id); - entity.Name = name; - logEntities.Add(entity); - } - - foreach (var player in log.Players) - { - player.LogId = log.Id; - } - - log.Entities = logEntities; - db.DbContext.AdminLog.Add(log); - } - - await db.DbContext.SaveChangesAsync(); - } - public override async Task AddAdminNote(AdminNote note) { await using (var db = await GetDb())