Skip to content

Split module settings into their own files.#1054

Open
dlamkins wants to merge 3 commits intodevfrom
feat/split-module-settings-into-their-own-file
Open

Split module settings into their own files.#1054
dlamkins wants to merge 3 commits intodevfrom
feat/split-module-settings-into-their-own-file

Conversation

@dlamkins
Copy link
Member

Problem

Module settings are stored along with all other settings within the setting.json file. To avoid deserializing module-specific types when a module isn't loaded, the settings are kept as raw JSON strings (via SettingCollection's lazy loading). However, this means the full JSON blob for every module (including those that are disabled) is held in memory at all times. For users with many modules, this results in a large settings.json and unnecessary memory usage.

Solution

Module settings are migrated out of settings.json into individual files under a new settings/ directory, named by module namespace (e.g. settings/bh.community.pathing.json). Settings are only loaded into memory when a module is enabled, and flushed back to disk and freed when it's disabled.

Settings migration

  • A migration takes place if module settings are detected in the settings.json file. When the migration occurs, a backup of the original settings file is made (if one doesn't already exist), just in case.

Results

image image

}

if (File.Exists(filePath)) {
File.Replace(tempPath, filePath, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File.Replace can fail if the file is opened somewhere. A more conservative approach would be to move the existing file, if that fails choose another name and try again, move the new file to the intended location, then try to delete the existing file, ignore failures. Failed deletes can be retried on subsequent calls to this function.

If you choose to implement this then please consider writing a separate method for MoveOrReplaceFile.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this is the same pattern we use currently and haven't had any reports of issues.

In the current implementation, failing to write leaves the last save there and the save services continues to consider the save as dirty (meaning it will try to save again in about 4 seconds. With this implementation, the most you'll lose is the delta between the actually saved version and the .new version (which can be manually restored).

Your approach has a few extra moving parts that I worry could result in losing a settings file because there isn't a settings file in the right spot at all times.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me, since it's a one time migration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is used during normal operations, on every save of any settings file.
I have no strong opinion on this either way.

Copy link
Member

@entrhopi entrhopi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked into the file saving mechanic again, and I think it is sufficiently safe. In case of it not working we still have the .new file for recovery.

@greaka greaka requested a review from Denrage February 18, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants