From ada40add8bd680695408ae19a796d0740e6552c6 Mon Sep 17 00:00:00 2001 From: Xurkon Date: Sat, 6 Jun 2026 10:07:28 -0500 Subject: [PATCH] fix: invalidate caches after learner updates --- Modules/QuestieLearner.lua | 22 ++++++++++++++++++++++ Tests/QuestieLearner_performance_spec.lua | 17 ++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index a1b7185..2ffd1dd 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -1281,6 +1281,7 @@ local function CrossLinkAfterItem(itemId) if not iData then return end local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled() local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil + local activeRefs = {} -- If this item starts a quest (item[5]=startQuest), ensure that quest knows -- about it via quest[2][3] (starter items slot) @@ -1302,11 +1303,14 @@ local function CrossLinkAfterItem(itemId) if entry[1] == itemId and iData[2] then for _, dropNpcId in ipairs(iData[2]) do _AddToQuestObjective(qData, 1, dropNpcId, nil, qOvr, questId) + activeRefs[questId] = true end end end end end + + _RefreshActiveQuestPins(activeRefs) end ------------------------------------------------------------------------ @@ -1860,6 +1864,9 @@ function QuestieLearner:LearnQuest(questId, data) if ovr[k] == nil and not IsAscensionProtected("QUEST", questId, k) then ovr[k] = v end end end + if QuestieDB.private and QuestieDB.private.questCache then + QuestieDB.private.questCache[questId] = nil + end end if isNew then @@ -1906,6 +1913,9 @@ function QuestieLearner:LearnQuestGiver(questId, entityId, entityType, isStart) if id == entityId then found = true; break end end if not found then table.insert(ovrList, entityId) end + if QuestieDB.private and QuestieDB.private.questCache then + QuestieDB.private.questCache[questId] = nil + end end -- Cross-link both directions for all entity types @@ -1979,6 +1989,9 @@ function QuestieLearner:LearnQuestObjectiveNPC(questId, npcId, objText, objectiv ovr.objIndex = ovr.objIndex or {} ovr.objIndex[objectiveIndex] = existing.objIndex[objectiveIndex] end + if QuestieDB.private and QuestieDB.private.questCache then + QuestieDB.private.questCache[questId] = nil + end end -- 3. Re-process the quest so PopulateObjective registers tooltips & map pins @@ -2058,6 +2071,9 @@ function QuestieLearner:LearnQuestObjectiveObject(questId, objectId, objText, ob ovr.objIndex = ovr.objIndex or {} ovr.objIndex[objectiveIndex] = existing.objIndex[objectiveIndex] end + if QuestieDB.private and QuestieDB.private.questCache then + QuestieDB.private.questCache[questId] = nil + end end if self:IsLearnerLiveEnabled() then @@ -2112,6 +2128,9 @@ function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemCl if ovr[k] == nil and not IsAscensionProtected("ITEM", itemId, k) then ovr[k] = v end end end + if QuestieDB.private and QuestieDB.private.itemCache then + QuestieDB.private.itemCache[itemId] = nil + end end if isNew then @@ -2151,6 +2170,9 @@ function QuestieLearner:LearnItemDrop(itemId, npcId) if id == npcId then found = true; break end end if not found then table.insert(ovr[2], npcId) end + if QuestieDB.private and QuestieDB.private.itemCache then + QuestieDB.private.itemCache[itemId] = nil + end end -- New drop relationship: re-run item cross-link to chain drop NPC → quest objectives diff --git a/Tests/QuestieLearner_performance_spec.lua b/Tests/QuestieLearner_performance_spec.lua index 31f2f1e..7d395eb 100644 --- a/Tests/QuestieLearner_performance_spec.lua +++ b/Tests/QuestieLearner_performance_spec.lua @@ -143,13 +143,28 @@ describe("QuestieLearner kill-path batching", function() it("records item drop sources even when the item class is not available on first pass", function() Questie.dbLearner.global.settings.dataSourceMode = "learner" + QuestieDB.private.itemCache = { + [2301] = { cached = true }, + } QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0) QuestieLearner:LearnItemDrop(2301, 7301) assert.is_table(Questie.dbLearner.global.items[2301][2]) assert.equals(7301, Questie.dbLearner.global.items[2301][2][1]) - assert.equals(7301, QuestieDB.itemDataOverrides[2301][2][1]) + assert.is_nil(QuestieDB.private.itemCache[2301]) + end) + + it("clears cached quest data when learner adds questgiver links", function() + Questie.dbLearner.global.settings.dataSourceMode = "learner" + QuestieDB.private.questCache = { + [6004] = { cached = true }, + } + + QuestieLearner:LearnQuestGiver(6004, 4001, 1, true) + + assert.is_table(Questie.dbLearner.global.quests[6004]) + assert.is_nil(QuestieDB.private.questCache[6004]) end) it("force-flushes active quest pins within the NPC live-update flush (no second debounce)", function()