From f66316161b4d34c767be2ad808bf822372211f81 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Sat, 16 May 2026 12:16:08 +0200 Subject: [PATCH] fix(autotells): preload tell history fully up to the user-configured limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PreloadHistory had a hardcoded 500-row SQL scan window that capped the per-partner history pull regardless of the AutoTellTabsHistoryPreload setting. For active users with many tell partners, the scan window filled up with chatter from other partners and pushed less-frequent partners' history off the back end — pinned tabs reloaded empty even though the messages were still in the database. Drops the hardcoded scan cap. The (Receiver, Date) index keeps SQL fast on the now-unbounded read, and the client-side loop still breaks as soon as the configured per-tab limit is hit, so decode cost stays proportional to the depth at which `limit` matches accumulate (typically shallow even for chatty users). --- HellionChat/MessageStore.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/HellionChat/MessageStore.cs b/HellionChat/MessageStore.cs index dd5f51f..bce9cae 100644 --- a/HellionChat/MessageStore.cs +++ b/HellionChat/MessageStore.cs @@ -1001,12 +1001,18 @@ internal class MessageStore : IDisposable // SQL narrows by Receiver + ChatType (indexed); client does the final // PlayerPayload comparison. sqlScanLimit caps the scan to stay within // the message-processing worker thread budget. + // Walks the full receiver-filtered tell history newest-first and stops + // as soon as the per-partner match count reaches `limit`. The previous + // hardcoded 500-row scan window cut active users' less-frequent pinned + // partners out of the result whenever other partners' chatter pushed + // them off the back of the window. Index on (Receiver, Date) keeps the + // SQL side cheap; the client-side break bounds the actual decode cost + // to roughly the depth at which `limit` partner matches accumulate. internal IReadOnlyList GetTellHistoryWithSender( ulong receiver, string senderName, uint senderWorld, - int limit, - int sqlScanLimit = 500 + int limit ) { if (limit <= 0) @@ -1024,14 +1030,12 @@ internal class MessageStore : IDisposable WHERE deleted = false AND Receiver = $Receiver AND ChatType IN ($TellIncoming, $TellOutgoing) - ORDER BY Date DESC - LIMIT $ScanLimit; + ORDER BY Date DESC; "; cmd.CommandTimeout = 60; cmd.Parameters.AddWithValue("$Receiver", receiver); cmd.Parameters.AddWithValue("$TellIncoming", (int)ChatType.TellIncoming); cmd.Parameters.AddWithValue("$TellOutgoing", (int)ChatType.TellOutgoing); - cmd.Parameters.AddWithValue("$ScanLimit", sqlScanLimit); var collected = new List(); using var enumerator = new MessageEnumerator(cmd.ExecuteReader(), _logger);