Skip to content

Refactor ws_service_stats.rs to reduce cognitive_complexity and add test coverage #217

@mukeshblackhat

Description

@mukeshblackhat

ws_service_stats.rs has two suppressions: run_service_collector (line 254) and handle_stats_socket (line 436), both #[allow(clippy::cognitive_complexity)].

What they do

  • run_service_collector (~90 lines) — resolves the inner container for a service, then polls docker stats --no-stream every 2 seconds in a loop, parses JSON, pushes to history ring, broadcasts to subscribers
  • handle_stats_socket (~55 lines) — replays history buffer to a newly connected WebSocket client, then runs a tokio::select! loop relaying broadcast receiver output to the socket (same pattern as ws_stats.rs and ws_host_service_stats.rs)

What to do

1. Extract single-poll execution in run_service_collector

Lines 290–323 build exec options, run create_exec + start_exec, accumulate stdout, and parse JSON. Extract:

async fn poll_service_stats(
    docker: &bollard::Docker,
    coast_container_id: &str,
    stats_cmd: &str,
) -> Option<serde_json::Value>

2. Extract history push + broadcast

Lines 325–335 push the new value into the history ring and send to the broadcast channel. Extract (could be shared with ws_host_service_stats.rs and ws_stats.rs):

async fn push_stats_to_history_and_broadcast(
    history: &Mutex<HashMap<String, VecDeque<serde_json::Value>>>,
    key: &str,
    val: serde_json::Value,
    tx: &broadcast::Sender<serde_json::Value>,
)

3. Extract history replay for handle_stats_socket

Lines 440+ replay the history ring to the socket. Extract (shared with ws_stats.rs and ws_host_service_stats.rs):

async fn replay_stats_history(
    socket: &mut WebSocket,
    history: &Mutex<HashMap<String, VecDeque<serde_json::Value>>>,
    key: &str,
) -> ControlFlow<()>

4. Extract broadcast forwarding loop

The tokio::select! loop in handle_stats_socket that forwards broadcast messages to the socket. Shared across all three stats handlers. Extract into a common module if possible:

async fn relay_broadcast_to_socket(
    socket: &mut WebSocket,
    rx: &mut broadcast::Receiver<serde_json::Value>,
    key: &str,
)

5. Add unit tests

poll_service_stats and broadcast/history helpers are hard to unit test without mocks. Focus on:

  • Any pure helpers that come out of extraction (JSON parsing, key construction, etc.)

Important

The workspace Cargo.toml sets cognitive_complexity, too_many_lines, too_many_arguments, and several other clippy lints to warn globally. Run make lint after every change and make sure the output is clean. Don't fix a suppression here only to create new warnings elsewhere.

Acceptance criteria

  • poll_service_stats extracted (from run_service_collector)
  • push_stats_to_history_and_broadcast extracted (shared if possible)
  • replay_stats_history extracted (shared with other stats handlers)
  • relay_broadcast_to_socket extracted (shared)
  • Both functions use the new helpers
  • All tests pass (make test)
  • make lint passes with zero new warnings
  • Remove both #[allow(clippy::cognitive_complexity)] suppressions if make lint passes without them, keep any still needed (note why)

Related

Tracking issue pattern from previous PRs: #122, #133, #157, #158, #171, #172, #173, #174, #175

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions