Class: Aidp::Harness::UI::JobMonitor

Inherits:
Base
  • Object
show all
Defined in:
lib/aidp/harness/ui/job_monitor.rb

Overview

Real-time job monitoring and status tracking

Defined Under Namespace

Classes: JobMonitorError, JobNotFoundError, MonitorError

Constant Summary collapse

JOB_STATUSES =
{
  pending: "Pending",
  running: "Running",
  completed: "Completed",
  failed: "Failed",
  cancelled: "Cancelled",
  retrying: "Retrying"
}.freeze
JOB_PRIORITIES =
{
  low: "Low",
  normal: "Normal",
  high: "High",
  urgent: "Urgent"
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(ui_components = {}, prompt: TTY::Prompt.new) ⇒ JobMonitor

Returns a new instance of JobMonitor.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/aidp/harness/ui/job_monitor.rb', line 36

def initialize(ui_components = {}, prompt: TTY::Prompt.new)
  super()
  @prompt = prompt
  @pastel = Pastel.new
  @status_manager = ui_components[:status_manager] || StatusManager.new
  @frame_manager = ui_components[:frame_manager] || FrameManager.new
  @formatter = ui_components[:formatter] || JobMonitorFormatter.new

  @jobs = {}
  @job_history = []
  @monitoring_active = false
  @monitor_thread = nil
  @monitor_mutex = Mutex.new
  @update_callbacks = []
end

Instance Method Details

#add_update_callback(callback) ⇒ Object



154
155
156
157
158
159
# File 'lib/aidp/harness/ui/job_monitor.rb', line 154

def add_update_callback(callback)
  validate_callback(callback)
  @update_callbacks << callback
rescue JobMonitorError => e
  raise MonitorError, "Failed to add update callback: #{e.message}"
end

#all_jobsObject



103
104
105
# File 'lib/aidp/harness/ui/job_monitor.rb', line 103

def all_jobs
  @monitor_mutex.synchronize { @jobs.dup }
end

#display_all_jobsObject



185
186
187
188
189
# File 'lib/aidp/harness/ui/job_monitor.rb', line 185

def display_all_jobs
  @frame_manager.section("All Jobs") do
    display_jobs_table(@jobs)
  end
end

#display_job_status(job_id) ⇒ Object



178
179
180
181
182
183
# File 'lib/aidp/harness/ui/job_monitor.rb', line 178

def display_job_status(job_id)
  job = job_status(job_id)
  @frame_manager.section("Job Status: #{job_id}") do
    display_job_details(job)
  end
end

#display_jobs_by_status(status) ⇒ Object



191
192
193
194
195
196
# File 'lib/aidp/harness/ui/job_monitor.rb', line 191

def display_jobs_by_status(status)
  jobs = jobs_by_status(status)
  @frame_manager.section("Jobs with Status: #{status}") do
    display_jobs_table(jobs)
  end
end

#has_job?(job_id) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
101
# File 'lib/aidp/harness/ui/job_monitor.rb', line 98

def has_job?(job_id)
  validate_job_id(job_id)
  @monitor_mutex.synchronize { @jobs.key?(job_id) }
end

#job_status(job_id) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/aidp/harness/ui/job_monitor.rb', line 88

def job_status(job_id)
  validate_job_id(job_id)

  @monitor_mutex.synchronize do
    job = @jobs[job_id]
    raise JobNotFoundError, "Job not found: #{job_id}" unless job
    job.dup
  end
end

#jobs_by_priority(priority) ⇒ Object



117
118
119
120
121
122
123
# File 'lib/aidp/harness/ui/job_monitor.rb', line 117

def jobs_by_priority(priority)
  validate_job_priority(priority)

  @monitor_mutex.synchronize do
    @jobs.select { |_, job| job[:priority] == priority }
  end
end

#jobs_by_status(status) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/aidp/harness/ui/job_monitor.rb', line 107

def jobs_by_status(status)
  validate_job_status(status)

  @monitor_mutex.synchronize do
    @jobs.select { |_, job| job[:status] == status }
  end
rescue JobMonitorError => e
  raise MonitorError, "Failed to get jobs by status: #{e.message}"
end

#monitoring_active?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/aidp/harness/ui/job_monitor.rb', line 150

def monitoring_active?
  @monitoring_active
end

#monitoring_summaryObject



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/aidp/harness/ui/job_monitor.rb', line 165

def monitoring_summary
  @monitor_mutex.synchronize do
    {
      total_jobs: @jobs.size,
      jobs_by_status: @jobs.values.map { |job| job[:status] }.tally,
      jobs_by_priority: @jobs.values.map { |job| job[:priority] }.tally,
      monitoring_active: @monitoring_active,
      total_events: @job_history.size,
      last_update: @job_history.last&.dig(:timestamp)
    }
  end
end

#register_job(job_id, job_data) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/aidp/harness/ui/job_monitor.rb', line 52

def register_job(job_id, job_data)
  validate_job_id(job_id)
  validate_job_data(job_data)

  @monitor_mutex.synchronize do
    job = create_job_entry(job_id, job_data)
    @jobs[job_id] = job
    record_job_event(job_id, :registered, job_data)
    notify_callbacks(:job_registered, job)
  end
rescue => e
  raise MonitorError, "Failed to register job: #{e.message}"
end

#remove_update_callback(callback) ⇒ Object



161
162
163
# File 'lib/aidp/harness/ui/job_monitor.rb', line 161

def remove_update_callback(callback)
  @update_callbacks.delete(callback)
end

#start_monitoring(interval_seconds = 1.0) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/aidp/harness/ui/job_monitor.rb', line 125

def start_monitoring(interval_seconds = 1.0)
  return if @monitoring_active

  @monitoring_active = true
  @monitor_thread = Thread.new do
    monitoring_loop(interval_seconds)
  end

  @prompt.say(@formatter.format_monitoring_started(interval_seconds))
rescue => e
  raise MonitorError, "Failed to start monitoring: #{e.message}"
end

#stop_monitoringObject



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/aidp/harness/ui/job_monitor.rb', line 138

def stop_monitoring
  return unless @monitoring_active

  @monitoring_active = false
  @monitor_thread&.join
  @monitor_thread = nil

  @prompt.say(@formatter.format_monitoring_stopped)
rescue => e
  raise MonitorError, "Failed to stop monitoring: #{e.message}"
end

#update_job_status(job_id, status, additional_data = {}) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/aidp/harness/ui/job_monitor.rb', line 66

def update_job_status(job_id, status, additional_data = {})
  validate_job_id(job_id)
  validate_job_status(status)

  @monitor_mutex.synchronize do
    job = @jobs[job_id]
    raise JobNotFoundError, "Job not found: #{job_id}" unless job

    old_status = job[:status]
    job[:status] = status
    job[:last_updated] = Time.now
    job.merge!(additional_data)

    record_job_event(job_id, :status_changed, {from: old_status, to: status})
    notify_callbacks(:job_status_changed, job, old_status)
  end
rescue JobNotFoundError => e
  raise e
rescue => e
  raise MonitorError, "Failed to update job status: #{e.message}"
end