Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 65 additions & 23 deletions HUD.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Use `Minigun::HUD.run_with_hud` to automatically run your task with HUD monitori
Minigun::HUD.run_with_hud(MyPipelineTask)
```

**Note**: When the pipeline finishes, the HUD stays open to display final statistics. Press `q` to exit. This allows you to review the final state, throughput metrics, and latency percentiles before closing.

### Option 3: Manual Control

For more control, manually create and manage the HUD controller:
Expand All @@ -101,36 +103,76 @@ hud_thread.join

| Key | Action |
|-----|--------|
| `q` / `Q` | Quit HUD |
| `Space` | Pause/Resume updates |
| `h` / `H` / `?` | Toggle help overlay |
| `r` / `R` | Force refresh / recalculate layout |
| `q` / `Q` | Quit HUD (works anytime, including when pipeline finished) |
| `Space` | Pause/Resume updates (disabled when finished) |
| `h` / `H` / `?` | Toggle help overlay (disabled when finished) |
| `r` / `R` | Force refresh / recalculate layout (disabled when finished) |
| `↑` / `↓` | Scroll process list |
| `d` / `D` | Toggle detailed view (future) |
| `w` / `s` | Pan flow diagram up/down |
| `a` / `d` | Pan flow diagram left/right |
| `c` / `C` | Compact view (future) |

## Display Elements

### Flow Diagram (Left Panel)

The left panel shows your pipeline stages as an animated flow diagram:

- **Stage icons**:
- `▶` Producer (generates data)
- `◆` Processor (transforms data)
- `◀` Consumer (consumes data)
- `⊞` Accumulator (batches items)
- `◇` Router (distributes to multiple stages)
- `⑂` Fork (IPC/COW process)
The left panel shows your pipeline stages as boxes with animated connections. Use `w`/`a`/`s`/`d` keys to pan the diagram for large pipelines.

- **Status indicators**:
- `⚡` Active (currently processing)
- `⏸` Idle (waiting for work)
- `⚠` Bottleneck (slowest stage)
- `✖` Error (failures detected)
- `✓` Done (completed)
```
┌─────────────────┐
│ ▶ generator ⚡ │
└──── 23.5/s ─────┘
⣿ ← flowing animation
┌─────────────────┐
│ ◆ processor ⚡ │
└──── 23.5/s ─────┘
┌─────────────────┐
│ ◀ consumer ⏸ │
└─────────────────┘
```

- **Animations**: Flowing characters indicate active data movement
**Box Components:**
- **Header Line**: Top border with stage name
- **Content**: Icon + Stage Name + Status Indicator
- **Footer**: Bottom border with throughput rate (when active)
- **Colors**: Status-based (green=active, yellow=bottleneck, red=error, gray=idle)

**Stage Icons:**
- `▶` Producer (generates data)
- `◆` Processor (transforms data)
- `◀` Consumer (consumes data)
- `⊞` Accumulator (batches items)
- `◇` Router (distributes to multiple stages)
- `⑂` Fork (IPC/COW process)

**Status Indicators:**
- `⚡` Active (currently processing)
- `⏸` Idle (waiting for work)
- `⚠` Bottleneck (slowest stage)
- `✖` Error (failures detected)
- `✓` Done (completed)

**Connection Animations:**
- Active connections show flowing Braille characters: `⠀⠁⠃⠇⠏⠟⠿⡿⣿`
- Horizontal lines pulse with dashed patterns: `─╌┄┈`
- Inactive connections shown as static gray lines
- Flow direction top-to-bottom through pipeline stages
- Fan-out patterns use proper split/fork characters: `┬ ┼` for tree-like visualization

**Example Fan-Out Pattern:**
```
┌──────────┐
│ producer │
└──────────┘
┬───┴───┬
│ │ │
┌───┘ │ └───┐
┌──────┐┌──────┐┌──────┐
│cons1 ││cons2 ││cons3 │
└──────┘└──────┘└──────┘
```

### Process Statistics (Right Panel)

Expand All @@ -155,9 +197,9 @@ The right panel displays a performance table:
### Status Bar (Bottom)

Shows:
- **Pipeline status**: RUNNING or PAUSED
- **Pipeline status**: RUNNING, PAUSED, or FINISHED
- **Pipeline name**: Current pipeline being monitored
- **Keyboard hints**: Available controls
- **Keyboard hints**: Available controls (changes to "Press [q] to exit..." when finished)

## Example

Expand Down
29 changes: 20 additions & 9 deletions TODO-CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ Minigun is a high-performance data processing pipeline framework for Ruby with s
### Phase 1.01: HUD

- [X] Initial HUD work:
- make a HUD inspired by htop to run as part of CLI
- two columns:
- LHS: flow diagram (ascii) on the other side, with ascii flow animations. make it inspired by cyberpunk (blade-runner/matrix/hackers)
- RHS: list of processes on one side
- use keys to navigate the hud.
- use ascii colors
- Before doing anything, plan it all out.
- [X] make a HUD inspired by htop to run as part of CLI
- [X] two columns:
- [X] LHS: flow diagram (ascii) on the other side, with ascii flow animations. make it inspired by cyberpunk (blade-runner/matrix/hackers)
- [X] RHS: list of processes on one side
- [X] use keys to navigate the hud.
- [X] use ascii colors
- [X] Before doing anything, plan it all out.

- [X] Running hud
- [X] task.hud to run in IRB/Rails console
Expand All @@ -57,11 +57,22 @@ Minigun is a high-performance data processing pipeline framework for Ruby with s
- [ ] Add hud to all examples when running
- [ ] Add idiomatic representation for each example

- [ ] HUD IPC support
- [ ] Process tree, forked routing
- [ ] HUD UI improvement
- [ ] Introduce Hud::DiagramStage and DiagramPipeline/Executor
- [ ] Re-add throughput and bottleneck icons to stages
- [ ] Improve animations, use 24-frame counter (or just int counter which rolls over?)
- [ ] Arrows on lines?
- [ ] fix up/down of stages (not clearing lines)
- [ ] auto-size width of stage columns
- [ ] p95 rather than p99?
- [ ] HUD IPC support
- [ ] Process tree, forked routing
- [ ] process wrappers

- [ ] HUD QoL
- [ ] % completion metrics
- [ ] CPU / MEM / disk / processes / queues
- [ ] tab menu?
- [ ] Error/log stream at bottom


Expand Down
32 changes: 26 additions & 6 deletions examples/03_fan_out_pattern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,38 @@ def initialize
users = [
{ id: 1, name: 'Alice', message: 'Hello Alice' },
{ id: 2, name: 'Bob', message: 'Hello Bob' },
{ id: 3, name: 'Charlie', message: 'Hello Charlie' }
{ id: 3, name: 'Charlie', message: 'Hello Charlie' },
{ id: 4, name: 'Diana', message: 'Hello Diana' },
{ id: 5, name: 'Eve', message: 'Hello Eve' },
{ id: 6, name: 'Frank', message: 'Hello Frank' },
{ id: 7, name: 'Grace', message: 'Hello Grace' },
{ id: 8, name: 'Hank', message: 'Hello Hank' }
]
users.each { |user| output << user }
users.each do |user|
output << user
sleep 0.05 if ENV['MINIGUN_HUD'] == '1' # Slow down for HUD visualization
end
end

# Email consumer
consumer :email_sender do |user|
consumer :email_sender, threads: 2 do |user|
sleep rand(0.02..0.05) if ENV['MINIGUN_HUD'] == '1' # Simulate work
@mutex.synchronize do
emails << "Email to #{user[:name]}: #{user[:message]}"
end
end

# SMS consumer
consumer :sms_sender do |user|
consumer :sms_sender, threads: 2 do |user|
sleep rand(0.03..0.06) if ENV['MINIGUN_HUD'] == '1' # Simulate work
@mutex.synchronize do
sms_messages << "SMS to #{user[:name]}: #{user[:message]}"
end
end

# Push notification consumer
consumer :push_sender do |user|
consumer :push_sender, threads: 2 do |user|
sleep rand(0.01..0.04) if ENV['MINIGUN_HUD'] == '1' # Simulate work
@mutex.synchronize do
push_notifications << "Push to #{user[:name]}: #{user[:message]}"
end
Expand All @@ -55,7 +66,16 @@ def initialize

if __FILE__ == $PROGRAM_NAME
pipeline = FanOutPipeline.new
pipeline.run

if ENV['MINIGUN_HUD'] == '1'
require_relative '../lib/minigun/hud'
puts 'Starting fan-out pipeline with HUD...'
puts 'Press [q] to quit the HUD when done'
sleep 1
Minigun::HUD.run_with_hud(pipeline)
else
pipeline.run
end

puts 'Fan-Out Pipeline Results:'
puts "\nEmails sent: #{pipeline.emails.size}"
Expand Down
4 changes: 2 additions & 2 deletions examples/hud_demo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# Demo script showing Minigun HUD in action
# Run with: ruby examples/hud_demo.rb

require_relative 'lib/minigun'
require_relative 'lib/minigun/hud'
require_relative '../lib/minigun'
require_relative '../lib/minigun/hud'

# Define a demo pipeline with various stages
class HudDemoTask
Expand Down
17 changes: 15 additions & 2 deletions lib/minigun/hud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative 'hud/theme'
require_relative 'hud/keyboard'
require_relative 'hud/flow_diagram'
require_relative 'hud/flow_diagram_frame'
require_relative 'hud/process_list'
require_relative 'hud/stats_aggregator'
require_relative 'hud/controller'
Expand Down Expand Up @@ -85,15 +86,27 @@ def self.run_with_hud(task)
end
end

# Monitor for user quit
# Monitor for user quit or task completion
loop do
if user_quit
# User pressed 'q' in HUD - exit immediately
task_thread.kill if task_thread.alive?
break
end

break unless task_thread.alive?
# Check if task finished
unless task_thread.alive?
# Task finished - notify HUD and wait for user to press key
hud.pipeline_finished = true

# Wait for user to quit via HUD
loop do
break if user_quit
sleep 0.1
end
break
end

sleep 0.1
end

Expand Down
Loading
Loading