Well, this is embarrassing.
Instead of publishing a new geeky widget I have for you, I've spent the whole evening creating huge saved vars with varying layouts, up to 300k lines / 80MB, trying to replicate the corruption I'm seeing with the combat log. Without success. It's a tiny add-on my friend had written, and I modified it a bit... two bits, actually... and months ago. You see where this is heading?
Mod #1 is that I do
Lua Code:
charvars = ZO_SavedVars:New("SV", 1, nil, {combatlog = {}})
setmetatable(charvars.combatlog, {__index = autovivify})
-- autovivify is a function that creates nested tables for nonexistent keys
I suspect that when I wrote that, I didn't realize ZO_SavedVars used metatables for the defaults magic; but even taking that into account, I can't see anything wrong with this. I'm simply replacing their metatable with my own, I don't want defaults at that level anyway.
Mod #2 is pruning old logs. Basically I have a flat array of log messages for each day, saved under charvars.combatlog[date]. When the add-on loads, I do
Lua Code:
for date, log in pairs(charvars.combatlog) do
if date < today - 14 then
charvars.combatlog[date] = nil
end
end
For a plain table, modifying/nilling existing keys during traversal is allowed. I'm not quite sure whether it's okay with the metatables from ZO_SavedVars.
Anyway, I cleaned the saved file by hand, and added some checks to the add-on, so that next time it gets corrupted, it'll give a hint. I shall let it keep growing naturally and see.