Just as a little fun, I decided to rewrite textadventurer in Rust, source).
The server was initially written in ~600 LOC of Java with a basic websocket library. The Java implementation worked fine–it was essentially just a tiny tech demo to demo a jobson feature–but I decided to rewrite it in Rust so I could understand where the pain-points are in an application like this.
This is an interesting standalone Rust project because:
-
It’s small and standalone. A minimal implementation would only really require a basic HTTP + websocket implementation.
-
It requires multithreading and appropriate IO handling, because each game that’s launched in a browser effectively launches a live process server-side. The live process can write to a client at arbitrary times and visa-versa for the client writing to a process.
-
It has several interesting edge-case conditions that need to be handled correctly in order for the server to not leak:
-
Clients can disconnect at arbitrary times. Subprocesses must be killed appropriately.
-
Processes can exit at arbitrary times. The server has to ensure it
wait
s on the process to prevent zombies. Clients need to be informed appropriately. -
Clients behave slightly differently in how they handle websocket connections. For example, Firefox seems to keep TCP and websocket connections open even when a user closes the browser tab, so the server can’t rely on sessions being closed appropriately.
-
The reimplementation used actix-web, an actor system. Actor-based architectures are really interesting for these types of servers because they greatly simplify the mental juggling required to understand concurrent processes.
The Rust rewrite was actually smaller (<600 LOC) than Java original version and had more features (command-line flags, configuration options, etc.) and used significantly less RAM and CPU than the Java version. The resource usage drop is especially nice because I like paying less for my cloud servers :)