Ensure data is saved before player changes servers

Discussion in 'Spigot Plugin Development' started by Nogtail, May 3, 2015.

  1. Nogtail

    Artist

    I have a BungeeCord instance which has several servers that players can swap between. When a player joins a server their associated data is loaded from the database. When a player quits or joins another server their data is saved in the database (MongoDB). This seems to work in testing where everything is on a fast local network and under no load but I would assume that if the database or server was under substantial load you may get servers trying to load data before it is saved. Is there a way to not let a player leave the server before their data is saved? Does PlayerQuitEvent return after a player has left and could have possibly joined another server?
     
  2. The PlayerQuitEvent is called when a player quit but he's called just before he disconnects really. ;) Then ... Have you already test that?
     
  3. You should not save data on quit; what if the server crashes?
     
  4. Save on quit and at regular intervals. Problem solved.

    IMO your best option would be to delay the loading by a second or two.
     
  5. @_Cory_
    Don't save on intervals. This may cause lag spikes.

    Just save once something is changed, make sure to do it async though.

    Edit:
    Not sure if you know the meaning of optimistic. I don't see how this can be considered optimistic.
     
    • Optimistic Optimistic x 2
  6. So saving every second is better than saving every 1200 seconds? Yeah makes sense doesn't it... xD
     
  7. I never said saving it every second.

    What he should do is when player data is being updated locally cache it on the server the player is on and at the same time save it to MongoDB (like I said before, do it async).
     
  8. Then you run into the problem that the earlier one takes longer to save then the latter and ends up overriding it. ESPECIALLY a problem when doing this async.

    Just so you're aware, player data is constantly changing, and it will already be cached into memory. How else would you use it? o_O

    Incremental saving and saving upon quit would be your best bet.
     
  9. Do you know sockets? It's better for that than a database ;)
     
    • Funny Funny x 3
  10. If you use a synchronized updating method and use an upsert, that won't be a problem.

    How is player data changing constantly? I don't know what he stores in his DB but I am fairly sure he doesn't save the player's location when they move ;). Also, I am talking about both pushing it to the database AND caching it on the server the player is on.
     
  11. Then tell me, how would you store the amount of tokens a player has in a socket?
     
  12. It's obviously something that is changing before they log out...
    If it wasn't changing constantly then what you're saying would be valid. However then players can potentially put more load on a server if it's not managed correctly.
     
  13. Have a bungee plugin that manages the player disconnects and save it in the database once they disconnect from the whole server?
     
  14. That's a way to do it, yeah. Not a good one though.
     
    • Funny Funny x 1
  15. You create a socket server, that connect all servers and you can store what you want
     
  16. Save onDisable and onQuit, guaranteed to save properly as long as it's not the whole JVM or physical server going down. Just do them asychronously and use conditional updating (add a timestamp, only update if the updated timestamp is larger than the stored timestamp) - I'm pretty sure most databases support such a thing one way or another, and it should eliminate most race conditions assuming their backend was done properly.
    Don't go implement your own database, please.
     
    • Like Like x 1
    • Funny Funny x 1
  17. What if it is?
     
  18. Then you generally have other things to worry about. But if you want to somewhat want to preserve data, use periodic saving like @_Cory_ suggested as well.
     
    • Like Like x 2
  19. Nogtail

    Artist

    I don't care too much about data loss from servers crashing, like has been said I would have bigger things to worry about if my servers were crashing regularly. I'm more worried about a sequence of events such as:
    Player joins 'Server1'
    Player data is loaded
    Player joins 'Server2'
    Player data is loaded
    Player data is saved from 'Server1'
    Player quits
    Player data is saved from 'Server2' overwriting 'Server1' data​

    The only thing I can think of to ensure data is saved before a player leaves is to handle all server changes on Bukkit instead of Bungee and save the data before telling Bungee to change servers which I would rather not do as it complicates my Bukkit plugin a heap.
     
  20.