Rust Chat Server with TUI Client: An Async Adventure and Request for Feedback
Introduction
Hello Rust community! About a month ago, I started building a chat server and a TUI client to dive into Rust's async and concurrency features. Although it's not a monumental open-source contribution, I hope it serves as a non-trivial, full-stack example in Rust. I'm really looking to improve my skills and would greatly appreciate any insights or feedback from Rustaceans at all levels. Your perspectives are the most valuable part of this project for me.
Project Overview
Yengas/rust-chat-server is an anonymous chat server that organizes conversations into a global list of rooms. Similar to Discord but with a twist: it's anonymous, operates on a single server instance, and is ephemeral.
Chat Server Components
- Comms Library: This component defines events and commands for the server. It takes advantage of Cargo "features" to optionally compile TCP logic, and employs Tokio Streams for robust, cancel-safe event and command streams.
- Server Binary: Inspired by the Actor model, this server handles multi-room chats and orchestrates both room and user session management through distinct modules.
- TUI Client: This terminal-based UI cleanly separates state management from rendering. Utilizing Flux Architecture principles and ratatui-org/ratatui for rendering.
I tried to maintain a strict architecture matching my use-case, instead of aiming for something generic. This approach allowed for a meaningful separation of concerns without additional complexity. I did not worry about scaling the server horizontally nor implementing the actor model / flux architecture perfectly.
Experience and Performance
- Rust met my expectations by offering a syntax reminiscent of Typescript and Scala, along with asynchronous capabilities like green threads and channels similar to Golang. Meanwhile, it provided memory usage and binary footprint better than most of the languages I've worked with.
- The notion of cancel safety in asynchronous programming was new and surprising, though it didn't make things overly complicated.
- TUI development proved more time-consuming than anticipated. Being accustomed to web and React programming, structuring the TUI was a different ball game.
- On the performance front, I ran stress tests locally on my M2 Pro. Despite running stress test binary, server and TUI on the same machine; Rust and Tokio handled over 10k users. On a 4$ DigitalOcean VPS, I achieved 500k writes and 1M reads (per minute) at 100% CPU utilization, running the stress test from another VPS.
Conclusion
Due to my focus on immutability and message-passing, coding in Rust felt quite similar to my experiences with Typescript, Scala, and Golang. I'm really curious how those more experienced in Rust would tackle a similar project. I'm definitely looking forward to your insights on architecture, code structure, and quality!
Cheers!