Is this a valid rollback approach?

The idea is: if XP is updated successfully, then I try to update the level. If updating the level fails, I restore the previous XP value.

Relevant code:

local success, err = SetXp(player, xp, replica)
if not success then
	return false, err
end

if level > oldLevel then
	success, err = self:SetLevel(player, level, replica, isCmdr)
	if not success then
		SetXp(player, oldXp, replica) -- rollback XP
		return false, err
	end
end


My concern is whether this is a safe rollback pattern. Since SetLevel can fail after SetXp already changed the replica data, restoring XP manually feels a bit fragile.

Is this a valid rollback approach?

Seems ok as long as getReplica() isnt yielding the thread. But the design is very weird. In my head, the set xp function should be the one adjusting the level BEFORE the replica is touched. That seems to be the only way to not get this “sorry for sending the wrong XP haha, revert back to this:”