refactor(messagestore): inject IPluginLogProxy for test isolation

MessageStore's Migrate0 (and the Migrate1/2/3 siblings) called
Plugin.Log.Information directly, which prevented an isolated xUnit
construction test from running — Dalamud.dll cannot load in the test
AppDomain. With IPluginLogProxy threaded through the ctor and the inner
MessageEnumerator, the whole MessageStore.cs file is now Dalamud-static
free and the Build-Suite covers it (Floor 688 -> 690).

This is the second half of F12.2; the remaining ~82 Plugin.Log call
sites in the rest of the plugin will be routed through the static
Plugin.LogProxy wrapper in a follow-up commit.
This commit is contained in:
2026-05-13 08:15:20 +02:00
parent 8edc3c70d3
commit dca5de4085
2 changed files with 20 additions and 19 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ internal class MessageManager : IAsyncDisposable
{
Plugin = plugin;
Store = new MessageStore(DatabasePath(), Plugin.PlatformUtil);
Store = new MessageStore(DatabasePath(), Plugin.PlatformUtil, Plugin.LogProxy);
PendingMessageThread = new Thread(() =>
ProcessPendingMessages(PendingThreadCancellationToken.Token)
+19 -18
View File
@@ -137,11 +137,13 @@ internal class MessageStore : IDisposable
);
private readonly IPlatformUtil _platformUtil;
private readonly IPluginLogProxy _logger;
internal MessageStore(string dbPath, IPlatformUtil platformUtil)
internal MessageStore(string dbPath, IPlatformUtil platformUtil, IPluginLogProxy logger)
{
DbPath = dbPath;
_platformUtil = platformUtil;
_logger = logger;
Connection = Connect();
Migrate();
}
@@ -204,7 +206,7 @@ internal class MessageStore : IDisposable
private void Migrate0()
{
Plugin.Log.Information("Running migration 0: Creating tables");
_logger.Information("Running migration 0: Creating tables");
Connection.Execute(
@"
CREATE TABLE IF NOT EXISTS messages (
@@ -231,7 +233,7 @@ internal class MessageStore : IDisposable
private void Migrate1()
{
Plugin.Log.Information("Running migration 1: Adding Deleted column");
_logger.Information("Running migration 1: Adding Deleted column");
Connection.Execute(
@"
ALTER TABLE messages ADD COLUMN Deleted BOOLEAN NOT NULL DEFAULT false;
@@ -243,7 +245,7 @@ internal class MessageStore : IDisposable
private void Migrate2()
{
Plugin.Log.Information("Running migration 2: Adding Channel generated column");
_logger.Information("Running migration 2: Adding Channel generated column");
Connection.Execute(
@"
ALTER TABLE messages ADD COLUMN Channel INTEGER GENERATED ALWAYS AS (Code & 0x7f) VIRTUAL;
@@ -271,15 +273,13 @@ internal class MessageStore : IDisposable
private void Migrate3()
{
Plugin.Log.Information("Running migration 3: Fix log kinds to fit the new format");
_logger.Information("Running migration 3: Fix log kinds to fit the new format");
// Recovery for partially-applied Migrate3: schema already in target
// shape but user_version was never bumped -- just record and exit.
if (ColumnExists("messages", "ChatType") && !ColumnExists("messages", "Code"))
{
Plugin.Log.Information(
"Migration 3: schema already migrated, only bumping user_version"
);
_logger.Information("Migration 3: schema already migrated, only bumping user_version");
SetMigrationVersion(3);
return;
}
@@ -309,7 +309,7 @@ internal class MessageStore : IDisposable
private void SetMigrationVersion(int version)
{
Plugin.Log.Information($"Setting version {version}");
_logger.Information($"Setting version {version}");
using var cmd = Connection.CreateCommand();
// PRAGMA does not accept SQLite parameter bindings; version is a
// compile-time int from the migration sequence, never user input.
@@ -461,7 +461,7 @@ internal class MessageStore : IDisposable
// Privacy filter -- drop disallowed ChatTypes before they reach storage.
if (!Plugin.Config.IsAllowedForStorage(message.Code.Type))
{
Plugin.Log.Verbose($"Privacy filter dropped message: ChatType={message.Code.Type}");
_logger.Verbose($"Privacy filter dropped message: ChatType={message.Code.Type}");
return;
}
@@ -554,7 +554,7 @@ internal class MessageStore : IDisposable
if (to is not null)
cmd.Parameters.AddWithValue("$To", to.Value.ToUnixTimeMilliseconds());
return new MessageEnumerator(cmd.ExecuteReader());
return new MessageEnumerator(cmd.ExecuteReader(), _logger);
}
// Returns the most recent messages, oldest-first.
@@ -602,7 +602,7 @@ internal class MessageStore : IDisposable
cmd.Parameters.AddWithValue("$Count", count);
return new MessageEnumerator(cmd.ExecuteReader());
return new MessageEnumerator(cmd.ExecuteReader(), _logger);
}
// Returns up to limit tells exchanged with the named player, oldest-first.
@@ -640,7 +640,7 @@ internal class MessageStore : IDisposable
cmd.Parameters.AddWithValue("$ScanLimit", sqlScanLimit);
var collected = new List<Message>();
using var enumerator = new MessageEnumerator(cmd.ExecuteReader());
using var enumerator = new MessageEnumerator(cmd.ExecuteReader(), _logger);
foreach (var message in enumerator)
{
if (!ChunkUtil.MatchesSender(message, senderName, senderWorld))
@@ -732,7 +732,7 @@ internal class MessageStore : IDisposable
cmd.Parameters.AddWithValue("$After", ((DateTimeOffset)after).ToUnixTimeMilliseconds());
cmd.Parameters.AddWithValue("$Before", ((DateTimeOffset)before).ToUnixTimeMilliseconds());
return new MessageEnumerator(cmd.ExecuteReader());
return new MessageEnumerator(cmd.ExecuteReader(), _logger);
}
internal MessageEnumerator GetPagedDateRange(
@@ -776,7 +776,7 @@ internal class MessageStore : IDisposable
cmd.Parameters.AddWithValue("$Offset", DbViewer.RowPerPage * page);
cmd.Parameters.AddWithValue("$OffsetCount", DbViewer.RowPerPage);
return new MessageEnumerator(cmd.ExecuteReader());
return new MessageEnumerator(cmd.ExecuteReader(), _logger);
}
// Builds a "$prefix0,$prefix1,..." placeholder list and binds values to the command.
@@ -796,13 +796,14 @@ internal class MessageStore : IDisposable
}
}
internal class MessageEnumerator(DbDataReader reader)
internal class MessageEnumerator(DbDataReader reader, IPluginLogProxy logger)
: IEnumerable<Message>,
IDisposable,
IAsyncDisposable
{
private const int MaxErrorLogs = 10;
private readonly IPluginLogProxy _logger = logger;
private readonly List<Guid> FailedIds = [];
private int FailedCount;
public bool DidError => FailedCount > 0;
@@ -848,10 +849,10 @@ internal class MessageEnumerator(DbDataReader reader)
catch (Exception e)
{
if (FailedCount < MaxErrorLogs)
Plugin.Log.Error($"Exception while reading message '{id}' from database: {e}");
_logger.Error($"Exception while reading message '{id}' from database: {e}");
FailedCount++;
if (FailedCount == MaxErrorLogs)
Plugin.Log.Error("Further parsing errors will not be logged");
_logger.Error("Further parsing errors will not be logged");
if (id != Guid.Empty)
FailedIds.Add(id);