Handling Players Status on Crash Events

I would like to have some opinions about a bug not being discussed enough IMHO.

The original discussion can be found on GitHub here: On crash players lose xp, rep but quests can’t be redone - #11187

To sum up B[/B]:

The bug:

When the server crashes between player updates, players lose XP and rep but quests that have been completed are still marked as rewarded which means they cannot be done again to regain the XP and rep.

The possible solutions found:

Implementing the saving Function directly as +Shauren pointed out it might have already been done:

The problem here is caused by these lines
// StoreNewItem, mail reward, etc. save data directly to the database
// to prevent exploitable data desynchronisation we save the quest status to the database too
// (to prevent rewarding this quest another time while rewards were already given out)
SQLTransaction trans = SQLTransaction(NULL);
_SaveQuestStatus(trans);
I may have forgotten something but I’m almost sure that items created/destroyed by quest are not saved instantly - only mail reward is

with maybe heavy impact on big servers because it basically means running a “lightweight” saving function each time a quest is completed.

VS

Changing the quest status flow, by adding a new status “quest_pending” to specifically handle quests in this status when is needed, as +MrSmite suggested:

Think of it this way:

[ul][li]Player completes quest[/li][li]Quest marked as completed in character_queststatus (existing feature)[/li]
[li]Quest inserted into quest_pending (new feature)[/li][/ul]
Then either

[ul][li]Core does a player save (existing feature)[/li]
[li]All quests are removed from quest_pending based on player GUID (new feature)[/li][/ul]
Or

[ul][li]Core crashes before a player save (existing feature)[/li]
[li]At startup, quests in character_queststatus are switched from completed back to in progress if they are found in quest_pending and then removed from quest_pending (new feature)[/li][/ul]
So at most you’re adding one INSERT and one DELETE statement during normal operation and during startup a SELECT, UPDATE and DELETE if necessary, which is also trivial.
Remember, currently the core only marks the quest as completed in character_queststatus but does nothing else until the player is saved. On a crash that potential XP and rep is lost. Providing a simple rollback mechanism is essential.

with undoubtedly better performances but without really avoiding players to repeating quests.

Final notes:

The aim of this post was just to make the community discuss about the problem and find maybe an even better solution than the ones from the original post.

I did my best to sum up without changing original words and thoughts.

Any change and correction of the post and its content from the original debaters or any other member of the community is strongly encouraged.

simply call the repMgr’s save function when rewarding a quest, it will only save reputations which have changed, so it shouldnt use too much resources

  • add a new async query which only saves the character’s xp field, this is a light weight query too, so it wont effect performance

UPDATE characters SET xp = ? WHERE guid = ? or something like that

or fix crashes /emoticons/default_smile.png

Who needs fault tolerant systems when there are no faults? “Just” fix the crashes /emoticons/default_tongue.png

Now in a more serious note, the solution that adds a new table is probably not optimal. It simply creates a new layer where (even more) bad things can happen.