left4me/docs/superpowers/specs/2026-05-06-l4d2-install-logging-design.md

2.1 KiB

SteamCMD Install Logging & Buffering Fix Design

Goal

Improve live feedback during the install operation by adding step markers to SteamInstaller and fixing Python subprocess buffering so output streams immediately instead of blocking until process exit or large chunks accumulate.

Root Cause

When the user triggers an install, two things cause significant UI delays:

  1. Double Buffering: l4d2web executes l4d2ctl via a subprocess pipe, and l4d2ctl executes steamcmd via another pipe. Python defaults to block-buffering sys.stdout when writing to a pipe. In run_command (both host and web versions), print(line, file=sys.stdout) uses flush=False by default. This causes Python to hold up to 8KB of log lines before sending them to the UI, causing massive "all at once" delays.
  2. Missing Markers: SteamInstaller was not updated to use the new _emit_step helper, so it provides no high-level contextual steps about what steamcmd is currently attempting (e.g. windows vs linux payloads).

Approach

1. Fix Python Subprocess Buffering

We will add flush=True to the pass-through print calls in our command runners. This forces Python to immediately push each line down the pipe to the UI.

  • Modify l4d2host/process.py:
    • Update print(line, file=sys.stderr) to print(line, file=sys.stderr, flush=True) in emit_stderr_message.
    • Update print(line, file=output_stream) to print(line, file=output_stream, flush=True) in pump.
  • Modify l4d2web/services/host_commands.py:
    • Apply the exact same flush=True fixes.

2. Add Step Markers to SteamInstaller

We will import _emit_step into l4d2host/steam_install.py and emit progress markers before executing the respective SteamCMD downloads.

  • Before the linux download: Step: downloading linux platform payload...
  • Before the windows download: Step: downloading windows platform payload...
  • After the loop: Step: installation complete.

Safety

These changes do not alter steamcmd's execution arguments or paths. The flush=True change only affects how quickly Python pushes strings through standard standard IO pipes, strictly improving SSE user experience.