fix(join): increase join_world timeout, log dedicated server stdout/stderr, null check multiplayer
checkpoint / checkpoint (push) Successful in 5m49s

This commit is contained in:
2026-09-15 21:23:45 +00:00
parent e6e22ac5f2
commit 42520b33d5
3 changed files with 25 additions and 6 deletions
+19 -2
View File
@@ -50,6 +50,7 @@ class _WorldServer:
proc: subprocess.Popen
status_path: Path
token: str
log_path: Path | None = None
started_at: float = field(default_factory=time.time)
last_join: float = field(default_factory=time.time)
@@ -150,6 +151,7 @@ class GameServerSupervisor:
token = secrets.token_urlsafe(32)
status_path = self._runtime_dir / f"world_{world_id}_{port}.json"
status_path.unlink(missing_ok=True)
log_path = self._runtime_dir / f"world_{world_id}_{port}.log"
cmd = [
settings.GODOT_BIN, "--headless",
"--path", settings.GAME_PROJECT_DIR,
@@ -160,9 +162,10 @@ class GameServerSupervisor:
"--api-url", settings.GAME_SERVER_INTERNAL_API_URL,
"--server-token", token,
]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
log_file = open(log_path, "w")
proc = subprocess.Popen(cmd, stdout=log_file, stderr=subprocess.STDOUT)
return _WorldServer(
world_id=world_id, port=port, proc=proc, status_path=status_path, token=token
world_id=world_id, port=port, proc=proc, status_path=status_path, token=token, log_path=log_path
)
def _free_port(self) -> int:
@@ -199,13 +202,27 @@ class GameServerSupervisor:
if srv.is_ready():
return
if not srv.alive():
log_snippet = ""
if srv.log_path and srv.log_path.exists():
try:
log_snippet = srv.log_path.read_text()[-500:]
except OSError:
pass
raise TimeoutError(
f"server process for world {srv.world_id} exited before becoming ready"
+ (f": {log_snippet}" if log_snippet else "")
)
await asyncio.sleep(0.25)
log_snippet = ""
if srv.log_path and srv.log_path.exists():
try:
log_snippet = srv.log_path.read_text()[-500:]
except OSError:
pass
raise TimeoutError(
f"server for world {srv.world_id} did not report ready within "
f"{settings.GAME_SERVER_READY_TIMEOUT_SECONDS}s"
+ (f": {log_snippet}" if log_snippet else "")
)
async def _reap_loop(self) -> None: