9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/supermicro/tasks.rb', line 9
def poll_task(task_location, timeout: 30, show_progress: true)
debug "Polling task: #{task_location}", 2
start_time = Time.now
last_percent = 0
task_name = task_location.split('/').last
if show_progress && (!respond_to?(:verbosity) || verbosity == 0)
spinner = Spinner.new("Processing task #{task_name}", type: :dots, color: :cyan)
spinner.start
else
spinner = nil
end
begin
while (Time.now - start_time) < timeout
task_response = authenticated_request(:get, task_location)
if task_response.status == 202
begin
if task_response.body && !task_response.body.empty?
monitor_data = JSON.parse(task_response.body)
if monitor_data['TaskState']
task_info = monitor_data
else
spinner&.update("Waiting for task to start...")
debug " Task pending (202 status)...", 3
sleep 1
next
end
else
spinner&.update("Task initializing...")
debug " Task still initializing...", 3
sleep 1
next
end
rescue JSON::ParserError
spinner&.update("Task running...")
debug " Task running (202)...", 3
sleep 1
next
end
elsif task_response.status == 200
begin
task_info = JSON.parse(task_response.body)
rescue JSON::ParserError => e
debug "Could not parse task response: #{e.message}", 2, :yellow
sleep 1
next
end
elsif task_response.status == 404
spinner&.stop("Task endpoint not found", success: false)
debug "Task endpoint returned 404 - cannot monitor task", 1, :red
return { success: false, error: 'task_endpoint_not_found' }
elsif task_response.status == 400
begin
if task_response.body && !task_response.body.empty?
task_info = JSON.parse(task_response.body)
if task_info['TaskState'] == 'Exception'
spinner&.stop("Task failed: #{task_info['Message']}", success: false)
debug "✗ Task failed: #{task_info['Message']}", 1, :red
return { success: false, task: task_info, error: task_info['Message'] }
elsif task_info['TaskState'] == 'Completed'
spinner&.stop("Task completed", success: true)
debug "✓ Task completed", 2, :green
return { success: true, task: task_info }
else
debug "Unexpected 400 response with TaskState: #{task_info['TaskState']}", 2, :yellow
sleep 1
next
end
end
rescue JSON::ParserError
debug "400 response but couldn't parse body: #{task_response.body}", 1, :red
return { success: false, error: 'bad_request' }
end
else
debug "Unexpected task response: #{task_response.status}", 2, :yellow
sleep 1
next
end
if defined?(task_info) && task_info && task_info['TaskState']
percent = task_info['PercentComplete'] || 0
if percent > 0 && percent != last_percent
spinner&.update("Task progress: #{percent}%")
debug " Task progress: #{percent}%", 2
last_percent = percent
end
case task_info['TaskState']
when 'Completed'
spinner&.stop("Task completed successfully", success: true)
debug "✓ Task completed successfully", 2, :green
return { success: true, task: task_info }
when 'Exception', 'Killed', 'Cancelled'
spinner&.stop("Task failed: #{task_info['TaskState']}", success: false)
debug "✗ Task failed: #{task_info['TaskState']}", 1, :red
if task_info['Messages']
task_info['Messages'].each do |msg|
debug " #{msg['Message']}", 1, :red
end
end
return { success: false, task: task_info }
when 'Running', 'Starting', 'Pending', 'New'
state_msg = task_info['TaskState'] == 'Running' ? "Running" : "Starting"
spinner&.update("Task #{state_msg.downcase}...")
debug " Task state: #{task_info['TaskState']}", 3
else
spinner&.update("Task state: #{task_info['TaskState']}")
debug " Unknown task state: #{task_info['TaskState']}", 2, :yellow
end
end
sleep 1
end
spinner&.stop("Task timed out after #{timeout} seconds", success: false)
debug "Task polling timed out after #{timeout} seconds", 1, :yellow
{ success: false, error: 'timeout' }
ensure
spinner&.stop if spinner
end
end
|