Sure -

Sure - The Durable Object handles websocket clients for a multiplayer game using a deterministic physics engine. The physics are executed on both the clients and the server. Serializing the physics world costs up to a few KB per player. To join games, I have a lobbies table in D1 with a game_state column: 'waiting' | 'playing' | 'finished'. I need to set the game to the finished state when it's abandoned, so if the player rejoins the websocket later, it won't re-initialize the DO. Because the transactional storage API is so expensive, I want to treat crashed games as permanently dead and show clients an error when they reconnect.
16 Replies
Erwin
Erwin13mo ago
Moving this to a thread btw.. keeps the channel cleaner for other people
Ottomated
OttomatedOP13mo ago
👍 Hmm. I do already have a tick_index that gets incremented, so if the client detects that it's decreased it knows it's broken? seems really hard to get right
Erwin
Erwin13mo ago
I mean when the DO is reinitialised, it wont have any state.. so that might be a clue? When the DO gets a regular gaming message when it doesn't have any state, it knows something is up I would imagine?
Ottomated
OttomatedOP13mo ago
that might work But then I am letting my clients dictate when I've crashed Also they don't send heartbeats But I guess they would auto-reconnect... or maybe not? because if I'm using the Hibernation API, when the DO crashes they would stay connected or is that wrong? I guess the foolproof solution is to store some "game_started" boolean in transactional storage, and then if that's set to true when the DO is constructed I know it's in a bad state However, the flaw with that solution is that I only detect the crash once the clients reconnect - it doesn't detect abandonment
Erwin
Erwin13mo ago
The clients would try to reconnect yes. So you would receive a message. Now I don't know your protocol obviously, but I can imagine that the messages you receive during a game are different than before a game?
Ottomated
OttomatedOP13mo ago
My only concern is a malicious client here.
Erwin
Erwin13mo ago
Just kill that client? And if all connections are killed clean up and let the DO die? I am not sure if you can set a timeout on the hibernation API? I haven't used it myself.. but otherwise you will want to use an alarm for that
Ottomated
OttomatedOP13mo ago
I mean if my metric for detecting a crash is if a client sends the wrong type of message, a malicious client could send that message intentionally and kill the DO
Erwin
Erwin13mo ago
Don't kill the DO.. kill the client connection.
Ottomated
OttomatedOP13mo ago
I need to write to D1 that the lobby is dead
Erwin
Erwin13mo ago
And if all connections are gone, the DO will die
Ottomated
OttomatedOP13mo ago
I guess that would work, but now we're back to needing a way to detect when the DO dies naturally
Erwin
Erwin13mo ago
You mean when all clients stop playing? Hmm.. so I just realised that in your case the DO can still be unloaded, even though gamers are connected right?
Ottomated
OttomatedOP13mo ago
There are 3 cases for the DO dying: 1. Game ends, I kick all clients and update D1 2. Game is abandoned, all clients are disconnected - I guess I do this on a close event + a timer? Still impractical 3. DO crashes, client almost certainly instantly auto-reconnects, I detect that the DO is being initialized in a bad state and update D1 I only want to hibernate in the waiting state - during the playing state I'm broadcasting 10 ticks per second
Erwin
Erwin13mo ago
ok.. that makes sense. So how long can the waiting state take?
Ottomated
OttomatedOP13mo ago
Until the lobby fills
Want results from more Discord servers?
Add your server