Skip to content

Commit cdb0d54

Browse files
Copilotneph1
andcommitted
Final code quality improvements
- Add error handling for WebSocket send failures with fallback to AJAX - Extract sendViaAjax helper function to reduce code duplication - Improve WebSocket exception handling with proper logging and traceback - Add specific handling for asyncio.CancelledError - Extract _process_command method to eliminate duplicate command processing logic - Add player context to error messages for better debugging Co-authored-by: neph1 <[email protected]>
1 parent 8467de9 commit cdb0d54

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

tale/tio/if_browser_io.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -787,9 +787,18 @@ async def websocket_endpoint(websocket: WebSocket):
787787
await asyncio.sleep(0.1)
788788

789789
except WebSocketDisconnect:
790+
print(f"WebSocket disconnected for player {player.player.name if player and player.player else 'unknown'}")
790791
self._cleanup_player(player)
792+
except asyncio.CancelledError:
793+
# Task was cancelled, clean shutdown
794+
print(f"WebSocket task cancelled for player {player.player.name if player and player.player else 'unknown'}")
795+
self._cleanup_player(player)
796+
raise
791797
except Exception as e:
792-
print(f"WebSocket error: {e}")
798+
# Log the error with context
799+
import traceback
800+
print(f"WebSocket error for player {player.player.name if player and player.player else 'unknown'}: {e}")
801+
print(traceback.format_exc())
793802
self._cleanup_player(player)
794803

795804
def _get_player_from_headers(self, headers) -> Optional[PlayerConnection]:
@@ -814,22 +823,20 @@ def _handle_player_input(self, conn: PlayerConnection, data: str) -> None:
814823
conn.io.append_html_to_browser("<p>No matching commands.</p>")
815824
else:
816825
# Normal command processing
817-
cmd = html_escape(cmd, False)
818-
if cmd:
819-
if conn.io.dont_echo_next_cmd:
820-
conn.io.dont_echo_next_cmd = False
821-
elif conn.io.echo_input:
822-
conn.io.append_html_to_browser("<span class='txt-userinput'>%s</span>" % cmd)
823-
conn.player.store_input_line(cmd)
826+
self._process_command(conn, cmd)
824827
except json.JSONDecodeError:
825828
# Handle plain text input for backward compatibility
826-
cmd = html_escape(data, False)
827-
if cmd:
828-
if conn.io.dont_echo_next_cmd:
829-
conn.io.dont_echo_next_cmd = False
830-
elif conn.io.echo_input:
831-
conn.io.append_html_to_browser("<span class='txt-userinput'>%s</span>" % cmd)
832-
conn.player.store_input_line(cmd)
829+
self._process_command(conn, data)
830+
831+
def _process_command(self, conn: PlayerConnection, cmd: str) -> None:
832+
"""Process a command from the player"""
833+
cmd = html_escape(cmd, False)
834+
if cmd:
835+
if conn.io.dont_echo_next_cmd:
836+
conn.io.dont_echo_next_cmd = False
837+
elif conn.io.echo_input:
838+
conn.io.append_html_to_browser("<span class='txt-userinput'>%s</span>" % cmd)
839+
conn.player.store_input_line(cmd)
833840

834841
def _cleanup_player(self, conn: PlayerConnection) -> None:
835842
"""Cleanup when player disconnects"""

tale/web/script.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -231,21 +231,31 @@ function send_cmd(command, npcAddress) {
231231

232232
if (useWebSocket && websocket && websocket.readyState === WebSocket.OPEN) {
233233
// Use WebSocket
234-
var message = JSON.stringify({ cmd: fullCommand });
235-
console.log("Sending command via WebSocket: " + fullCommand);
236-
websocket.send(message);
234+
try {
235+
var message = JSON.stringify({ cmd: fullCommand });
236+
console.log("Sending command via WebSocket: " + fullCommand);
237+
websocket.send(message);
238+
} catch (e) {
239+
console.error("WebSocket send failed, falling back to AJAX:", e);
240+
// Fallback to AJAX if WebSocket send fails
241+
sendViaAjax(fullCommand);
242+
}
237243
} else {
238244
// Fallback to AJAX POST
239-
var ajax = new XMLHttpRequest();
240-
ajax.open("POST", "input", true);
241-
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
242-
243-
var encoded_cmd = encodeURIComponent(fullCommand);
244-
console.log("Sending command via AJAX: " + encoded_cmd);
245-
ajax.send("cmd=" + encoded_cmd);
245+
sendViaAjax(fullCommand);
246246
}
247247
}
248248

249+
function sendViaAjax(command) {
250+
var ajax = new XMLHttpRequest();
251+
ajax.open("POST", "input", true);
252+
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
253+
254+
var encoded_cmd = encodeURIComponent(command);
255+
console.log("Sending command via AJAX: " + encoded_cmd);
256+
ajax.send("cmd=" + encoded_cmd);
257+
}
258+
249259
function autocomplete_cmd()
250260
{
251261
var cmd_input = document.getElementById("input-cmd");

0 commit comments

Comments
 (0)