CW server: send out messages in parallel

We now send out messages to all participants at the same time (or more
or less, as asyncio permits). To not fail in case we can't send the
message to one player, we ignore send-exceptions in these occasions and
hope that the `for data in self.websocket` in _handle_client() will
throw an error and kick the client out of our game.
This commit is contained in:
Sebastian Lohff 2025-04-13 20:07:06 +02:00
parent f3732b09d5
commit 5dda7af184
1 changed files with 17 additions and 8 deletions

View File

@ -124,8 +124,7 @@ class Client:
print("FREQ", self.curr_freq, freq, self.freqs) print("FREQ", self.curr_freq, freq, self.freqs)
await self._send(type="join", freq=self.curr_freq, self_id=self.id, await self._send(type="join", freq=self.curr_freq, self_id=self.id,
other_players=[c.id for c in self._others(freq)]) other_players=[c.id for c in self._others(freq)])
for other in self._others(freq): await self._send_to_group(self._others(freq), type="player-joined", player=self.id)
await other._send(type="player-joined", player=self.id)
async def _handle_morse_state(self, data): async def _handle_morse_state(self, data):
if not self.curr_freq: if not self.curr_freq:
@ -136,16 +135,16 @@ class Client:
await self._send_error("No state key with type bool in data") await self._send_error("No state key with type bool in data")
return return
for other in self._others(self.curr_freq): await self._send_to_group(self._others(self.curr_freq),
await other._send(type="morse-state", state=data["state"], from_player=self.id) type="morse-state", state=data["state"], from_player=self.id)
async def _leave_room(self): async def _leave_room(self):
if not self.curr_freq: if not self.curr_freq:
self._send_error("You are not on a frequency") self._send_error("You are not on a frequency")
return return
for other in self._others(self.curr_freq): await self._send_to_group(self._others(self.curr_freq),
await other._send(type="player-left", player=self.id) type="player-left", player=self.id)
try: try:
self.freqs[self.curr_freq].remove(self) self.freqs[self.curr_freq].remove(self)
except ValueError: except ValueError:
@ -162,10 +161,20 @@ class Client:
def _others(self, freq): def _others(self, freq):
return [c for c in self.freqs[freq] if c.id != self.id] return [c for c in self.freqs[freq] if c.id != self.id]
async def _send(self, **kwargs): async def _send(self, ignore_exceptions=False, **kwargs):
data = json.dumps(kwargs).encode() data = json.dumps(kwargs).encode()
print(f" --> sending out to {self.client}: {data}") print(f" --> sending out to {self.client}: {data}")
await self.websocket.send(json.dumps(kwargs).encode() + b"\n") try:
await self.websocket.send(json.dumps(kwargs).encode() + b"\n")
except Exception as e:
print(f"Error sending data to {self.client}: {e}")
if not ignore_exceptions:
raise
async def _send_to_group(self, group, **kwargs):
async with asyncio.TaskGroup() as tg:
for member in group:
tg.create_task(member._send(ignore_exceptions=True, **kwargs))
async def _send_error(self, msg: str): async def _send_error(self, msg: str):
await self._send(type="error", message=msg) await self._send(type="error", message=msg)