Fix admin logs duplicate id error when running tests (#16203)
This commit is contained in:
@@ -53,11 +53,6 @@ public sealed partial class AdminLogManager
|
|||||||
CacheLog(record);
|
CacheLog(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CacheLog(QueuedLog log)
|
|
||||||
{
|
|
||||||
CacheLog(log.Log);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CacheLog(SharedAdminLog log)
|
private void CacheLog(SharedAdminLog log)
|
||||||
{
|
{
|
||||||
// TODO ADMIN LOGS remove redundant data and don't do a dictionary lookup per log
|
// TODO ADMIN LOGS remove redundant data and don't do a dictionary lookup per log
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Content.Server.Administration.Logs.Converters;
|
using Content.Server.Administration.Logs.Converters;
|
||||||
|
using Content.Server.Database;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
|
||||||
@@ -32,10 +33,10 @@ public sealed partial class AdminLogManager
|
|||||||
_sawmill.Debug($"Admin log converters found: {string.Join(" ", converterNames)}");
|
_sawmill.Debug($"Admin log converters found: {string.Join(" ", converterNames)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private (JsonDocument json, HashSet<Guid> players, Dictionary<int, string?> entities) ToJson(
|
private (JsonDocument Json, HashSet<Guid> Players, List<AdminLogEntity> Entities) ToJson(
|
||||||
Dictionary<string, object?> properties)
|
Dictionary<string, object?> properties)
|
||||||
{
|
{
|
||||||
var entities = new Dictionary<int, string?>();
|
var entities = new Dictionary<EntityUid, AdminLogEntity>();
|
||||||
var players = new HashSet<Guid>();
|
var players = new HashSet<Guid>();
|
||||||
var parsed = new Dictionary<string, object?>();
|
var parsed = new Dictionary<string, object?>();
|
||||||
|
|
||||||
@@ -69,7 +70,8 @@ public sealed partial class AdminLogManager
|
|||||||
? metadata.EntityName
|
? metadata.EntityName
|
||||||
: null;
|
: 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))
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
|||||||
|
|
||||||
// Per update
|
// Per update
|
||||||
private TimeSpan _nextUpdateTime;
|
private TimeSpan _nextUpdateTime;
|
||||||
private readonly ConcurrentQueue<QueuedLog> _logQueue = new();
|
private readonly ConcurrentQueue<AdminLog> _logQueue = new();
|
||||||
private readonly ConcurrentQueue<QueuedLog> _preRoundLogQueue = new();
|
private readonly ConcurrentQueue<AdminLog> _preRoundLogQueue = new();
|
||||||
|
|
||||||
// Per round
|
// Per round
|
||||||
private int _currentRoundId;
|
private int _currentRoundId;
|
||||||
@@ -171,7 +171,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
|||||||
_nextUpdateTime = _timing.RealTime.Add(_queueSendDelay);
|
_nextUpdateTime = _timing.RealTime.Add(_queueSendDelay);
|
||||||
|
|
||||||
// TODO ADMIN LOGS array pool
|
// TODO ADMIN LOGS array pool
|
||||||
var copy = new List<QueuedLog>(_logQueue.Count + _preRoundLogQueue.Count);
|
var copy = new List<AdminLog>(_logQueue.Count + _preRoundLogQueue.Count);
|
||||||
|
|
||||||
copy.AddRange(_logQueue);
|
copy.AddRange(_logQueue);
|
||||||
_logQueue.Clear();
|
_logQueue.Clear();
|
||||||
@@ -183,10 +183,10 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var queued in _preRoundLogQueue)
|
foreach (var log in _preRoundLogQueue)
|
||||||
{
|
{
|
||||||
queued.Log.RoundId = _currentRoundId;
|
log.RoundId = _currentRoundId;
|
||||||
CacheLog(queued);
|
CacheLog(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy.AddRange(_preRoundLogQueue);
|
copy.AddRange(_preRoundLogQueue);
|
||||||
@@ -231,6 +231,17 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
|||||||
{
|
{
|
||||||
Interlocked.Exchange(ref _currentLogId, 0);
|
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)
|
if (_metricsEnabled)
|
||||||
{
|
{
|
||||||
PreRoundQueueCapReached.Set(0);
|
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<Guid> players, Dictionary<int, string?> entities)
|
private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet<Guid> players, List<AdminLogEntity> entities)
|
||||||
{
|
{
|
||||||
var logId = NextLogId;
|
|
||||||
var date = DateTime.UtcNow;
|
|
||||||
|
|
||||||
var log = new AdminLog
|
var log = new AdminLog
|
||||||
{
|
{
|
||||||
Id = logId,
|
Id = NextLogId,
|
||||||
RoundId = _currentRoundId,
|
RoundId = _currentRoundId,
|
||||||
Type = type,
|
Type = type,
|
||||||
Impact = impact,
|
Impact = impact,
|
||||||
Date = date,
|
Date = DateTime.UtcNow,
|
||||||
Message = message,
|
Message = message,
|
||||||
Json = json,
|
Json = json,
|
||||||
Players = new List<AdminLogPlayer>(players.Count)
|
Players = new List<AdminLogPlayer>(players.Count),
|
||||||
|
Entities = entities
|
||||||
};
|
};
|
||||||
|
|
||||||
var queued = new QueuedLog(log, entities);
|
|
||||||
|
|
||||||
foreach (var id in players)
|
foreach (var id in players)
|
||||||
{
|
{
|
||||||
var player = new AdminLogPlayer
|
var player = new AdminLogPlayer
|
||||||
{
|
{
|
||||||
LogId = logId,
|
LogId = log.Id,
|
||||||
PlayerUserId = id
|
PlayerUserId = id
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -272,11 +279,11 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
|||||||
|
|
||||||
if (_runLevel == GameRunLevel.PreRoundLobby)
|
if (_runLevel == GameRunLevel.PreRoundLobby)
|
||||||
{
|
{
|
||||||
_preRoundLogQueue.Enqueue(queued);
|
_preRoundLogQueue.Enqueue(log);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logQueue.Enqueue(queued);
|
_logQueue.Enqueue(log);
|
||||||
CacheLog(log);
|
CacheLog(log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
using Content.Server.Database;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Logs;
|
|
||||||
|
|
||||||
public readonly struct QueuedLog
|
|
||||||
{
|
|
||||||
public QueuedLog(AdminLog log, Dictionary<int, string?> entities)
|
|
||||||
{
|
|
||||||
Log = log;
|
|
||||||
Entities = entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AdminLog Log { get; }
|
|
||||||
|
|
||||||
public Dictionary<int, string?> Entities { get; }
|
|
||||||
|
|
||||||
public void Deconstruct(out AdminLog log, out Dictionary<int, string?> entities)
|
|
||||||
{
|
|
||||||
log = Log;
|
|
||||||
entities = Entities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@ using Content.Shared.Preferences;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Database
|
namespace Content.Server.Database
|
||||||
{
|
{
|
||||||
@@ -717,26 +716,10 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
|||||||
return (server, false);
|
return (server, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task AddAdminLogs(List<QueuedLog> logs)
|
public async Task AddAdminLogs(List<AdminLog> logs)
|
||||||
{
|
{
|
||||||
await using var db = await GetDb();
|
await using var db = await GetDb();
|
||||||
|
db.DbContext.AdminLog.AddRange(logs);
|
||||||
var entities = new Dictionary<int, AdminLogEntity>();
|
|
||||||
|
|
||||||
foreach (var (log, entityData) in logs)
|
|
||||||
{
|
|
||||||
var logEntities = new List<AdminLogEntity>(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.DbContext.SaveChangesAsync();
|
await db.DbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ namespace Content.Server.Database
|
|||||||
#region Admin Logs
|
#region Admin Logs
|
||||||
|
|
||||||
Task<Server> AddOrGetServer(string serverName);
|
Task<Server> AddOrGetServer(string serverName);
|
||||||
Task AddAdminLogs(List<QueuedLog> logs);
|
Task AddAdminLogs(List<AdminLog> logs);
|
||||||
IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null);
|
IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null);
|
||||||
IAsyncEnumerable<SharedAdminLog> GetAdminLogs(LogFilter? filter = null);
|
IAsyncEnumerable<SharedAdminLog> GetAdminLogs(LogFilter? filter = null);
|
||||||
IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null);
|
IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null);
|
||||||
@@ -564,7 +564,7 @@ namespace Content.Server.Database
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task AddAdminLogs(List<QueuedLog> logs)
|
public Task AddAdminLogs(List<AdminLog> logs)
|
||||||
{
|
{
|
||||||
DbWriteOpsMetric.Inc();
|
DbWriteOpsMetric.Inc();
|
||||||
return RunDbCommand(() => _db.AddAdminLogs(logs));
|
return RunDbCommand(() => _db.AddAdminLogs(logs));
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Administration.Logs;
|
|
||||||
using Content.Server.IP;
|
using Content.Server.IP;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Database
|
namespace Content.Server.Database
|
||||||
{
|
{
|
||||||
@@ -475,42 +473,6 @@ namespace Content.Server.Database
|
|||||||
return round.Id;
|
return round.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task AddAdminLogs(List<QueuedLog> 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<int, AdminLogEntity>();
|
|
||||||
|
|
||||||
foreach (var (log, entityData) in logs)
|
|
||||||
{
|
|
||||||
log.Id = nextId++;
|
|
||||||
|
|
||||||
var logEntities = new List<AdminLogEntity>(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<int> AddAdminNote(AdminNote note)
|
public override async Task<int> AddAdminNote(AdminNote note)
|
||||||
{
|
{
|
||||||
await using (var db = await GetDb())
|
await using (var db = await GetDb())
|
||||||
|
|||||||
Reference in New Issue
Block a user