Well I'm happy to report that the long slog of porting Umpire to a networked architecture is coming along. And I've learned a lot along the way about Rust's async ecosystem, especially Tokio.
Nota bene: many unexpected issues can arise when porting synchronous to asynchronous code in Rust. Every async
function can implicitly place Send
or Sync
constraints on various fields involved. This can require special handling for types not naturally amenable to being shared across threads. Fortunately the Rust world is replete with alternative implementations that satisfy such constraints, such as sync_channel
in std::sync::mpsc
.
Because a significant transition can be required to make even a single method async
, it pays to make the shift piecemeal rather than all at once. I tried the former, and was drowning in compile errors. Now, one function at a time, I'm making much better progress.
That's the current phase of the project: switching important trait methods to async
, even before wiring in the RPC calls. This shakes out threading issues before they happen, so to speak, and paves the way for networking.
It's all getting very close, and I'm feeling optimistic for a successful switch. The initial network protocol is actually implemented, ready to be adopted when the moment is right. It's a horribly inefficient protocol, with all kinds of needless round-trips, but that's where we're going to start. We can add some caching or other optimizations later if need be.
The addition of networked multiplayer will merit a new release: Umpire 0.5. Soon!
Feels good to delve into this world of client-server code in a new way. The concerns are so different from a REST server implemented in Typescript, say. But not that different: we're appeasing the compiler gods through our offerings, one way or another.