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 waits 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 :)