Design feedback: tokio, tungstenite (websocket), server,

This is pseudocode, as I'm looking for ideas/feedback:

v: Vec<Tokio_Tungstenite_Websocket>;

loop { // want to run as close to 0.1s / tick as posssible
  let t = Instant::now();
  
  for ws in v.iter() {
    tokiio::spawn(without_blocking_read_at_most_3_msg(ws))
  }

  wait_until_above_finishes();

  process_msgs();

  sleep until t + 0.1s
}

So I have a few questions here:

  1. We are calling tokio::spawn (10 * v.len())` times per second; this could be a bit much; is there a benefit to "long living tasks" vs "spanning a task every time just to read 3 msgs" ?

  2. how do we implement wait_untilL_above_finishes() efficiently ?

  3. how do we implement without_blocking_read_at_most_3_msgs ? Recall our system happens in two stages: "grab all msgs" then "process", so we can not have any of "grab all msgs" stall/block; we need to read what is available then return, so we can go to processing

====

If I have the entire design wrong here, please let me know what is wrong and what good design should be

====

XY problem: multi player game server

at-most-3-msgs is to ensure some notion of fairness / defense vs clients that flood

Thanks!

spawning a tokio task costs about the same as an allocation, it's quite cheap.

wait_until_above_finishes() can be implemented by simply looping over the joinhandles returned by tokio::spawn.

2 Likes

I agree with the above suggestion to just await the join handles from the spawned tasks. But you may also want to do some defensive coding and wrap them in a timeout with something like tokio::select!.

How you handle timeouts is up to you, but assuming your 100 ms maximum duration per loop is a hard constraint, I don't think I would just await the tasks without considering timeouts.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.