Skip to content

ARCHITECTURE: Channel Spaghetti and Deadlock Risk #23

@devfire

Description

@devfire

Severity: MEDIUM

Location

src/processor.rs and src/app.rs

Issue

The application spawns 5 concurrent tasks connected by 3 different channel types, creating complex dependencies and potential deadlock scenarios.

Current Structure

stdin_input_task (blocking)
    |
    v
command_sender -> command_handler_task -> state_actor
                       |                      |
message_sender -> message_handler_task -------|  
                       |                      |
                       v                      v
                  network_manager      display_sender
                       ^
                       |
udp_input_task --------|-> display_sender

Problems

  1. Complex dependencies: Hard to reason about message flow
  2. Multiple channel types: mpsc, actor messages, blocking_send
  3. Deadlock potential: Tasks can block waiting on each other
  4. Error propagation: Hard to trace errors through channels
  5. Testing nightmare: Cannot test task interaction

Specific Issues

Blocking in async context:

if command_sender.blocking_send(c).is_err() { // In tokio::task::spawn_blocking

Channel capacity issues:

let (command_sender, command_receiver) = tokio::sync::mpsc::channel::<Command>(100);
// What happens when 101 commands arrive?

Unclear ownership:

  • Multiple tasks share display_sender
  • Network manager is Arc'd everywhere
  • State actor is cloned to multiple tasks

Proposed Solution

Option 1: Use actor model properly

CLI Actor -> Command Actor -> State Actor
                             -> Network Actor
Network Actor -> Message Actor -> State Actor

Option 2: Simplify with single event loop

enum Event {
    UserInput(String),
    NetworkMessage(Packet),
    Command(Command),
}

loop {
    select! {
        event = event_rx.recv() => handle_event(event),
    }
}

Benefits of Refactoring

  • Clear message flow
  • No deadlock risk
  • Easier testing
  • Better error handling
  • Simpler reasoning

Labels

architecture, concurrency, refactoring

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions