Check the action queue when scheduling auto save - #1254
Merged
Conversation
AutoSave guarded on World.contains("auto_save"). World is a VariableStore,
so that reads a world variable of that name rather than the action queue
World.queue writes to. Nothing sets such a variable, so it was always
false and the queue check was World.containsQueue all along.
Two effects. With auto save enabled every ::reload settings re-queued,
and since actions are keyed by name that replaced the entry with a fresh
deadline, so reloading more often than the interval meant auto save never
fired. With it disabled the clearQueue branch was unreachable, so turning
auto save off at runtime left the queued action to fire once more.
The queue check now lives in autoSave() so every caller is covered.
Rescheduling from inside the queued block still works because World.run()
removes the entry before invoking it.
GregHib
approved these changes
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1251.
AutoSaveguarded its scheduling onWorld.contains("auto_save").Worldis declaredobject World : Entity, VariableStore, Runnable, KoinComponent, so that resolves toVariableStore.contains(key) = variables.contains(key), reading a world variable rather than theactionsmapWorld.queuewrites to. Nothing sets a variable by that name, so it was always false. The intended check isWorld.containsQueue(World.kt:48).With auto save enabled, the
else ifbranch fired on every::reload settings, andactionsis keyed by name:so the existing entry was replaced with a fresh deadline rather than duplicated. Reloading settings more often than
storage.autoSave.minutesmeant auto save never ran. Easy to hit on a dev server while testing, and the first symptom is a rolled back save.With it disabled, neither branch could fire, so
World.clearQueue("auto_save")was unreachable and settingstorage.autoSave.minutesto0at runtime left the queued action to fire once more before the chain ended on its own.The queue check now sits in
autoSave()rather than at the call site, soworldSpawn,settingsReloadand the block's own rescheduling all go through it. Rescheduling from inside the queued block still works, sinceWorld.run()removes the entry before invoking it:iterator.remove() try { block.invoke() }AutoSaveTestcovers the unreachable branch and fails without the change withDisabling auto save left the queue running.I didn't add a test for the deadline being pushed out.
World.actionsis private, so observing the deadline needs eithermockkObject(World)or a 100+ tick test driving real file IO, and neither seemed worth the flakiness for a defect that shares its root cause and fix with the one that is covered. Happy to add one if you'd rather have it.Full suite green.