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
11 changes: 10 additions & 1 deletion openc3-cosmos-cmd-tlm-api/app/controllers/queues_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,18 @@ def exec_command
index = params[:index]&.to_f
command_data = model.remove_command(index)
if command_data
hazardous = false
begin
token = get_token(command_data['username'], scope: params[:scope])
cmd_no_hazardous_check(command_data['value'], queue: false, scope: params[:scope], token: token)
if hazardous
cmd_no_hazardous_check(command_data['value'], queue: false, scope: params[:scope], token: token)
else
cmd(command_data['value'], queue: false, scope: params[:scope], token: token)
end
rescue HazardousError => e
# Rescue hazardous error and retry with cmd_no_hazardous_check
hazardous = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever!

retry
rescue StandardError => e
log_error(e)
render json: { status: 'error', message: "Failed to execute command: #{e.message}", type: e.class.to_s, backtrace: e.backtrace }, status: 500
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ def generate_queue_hash
}
allow(OpenC3::QueueModel).to receive(:get_model).and_return(queue_model)
allow(queue_model).to receive(:remove_command).and_return(command_data)
allow(controller).to receive(:cmd_no_hazardous_check).with("TEST COMMAND", {queue: false, scope: "DEFAULT", token: anything})
allow(controller).to receive(:cmd).with("TEST COMMAND", {queue: false, scope: "DEFAULT", token: anything})

post :exec_command, params: {name: "QUEUE1", scope: "DEFAULT"}
expect(response).to have_http_status(:ok)
Expand All @@ -563,7 +563,7 @@ def generate_queue_hash
}
allow(OpenC3::QueueModel).to receive(:get_model).and_return(queue_model)
allow(queue_model).to receive(:remove_command).and_return(command_data)
allow(controller).to receive(:cmd_no_hazardous_check).with("INDEXED COMMAND", {queue: false, scope: "DEFAULT", token: anything})
allow(controller).to receive(:cmd).with("INDEXED COMMAND", {queue: false, scope: "DEFAULT", token: anything})
index = "3.5"

post :exec_command, params: {name: "QUEUE1", index: index, scope: "DEFAULT"}
Expand Down Expand Up @@ -620,7 +620,7 @@ def generate_queue_hash
}
allow(OpenC3::QueueModel).to receive(:get_model).and_return(queue_model)
allow(queue_model).to receive(:remove_command).and_return(command_data)
allow(controller).to receive(:cmd_no_hazardous_check).with("INTEGER INDEX COMMAND", {queue: false, scope: "DEFAULT", token: anything})
allow(controller).to receive(:cmd).with("INTEGER INDEX COMMAND", {queue: false, scope: "DEFAULT", token: anything})
index = 5

post :exec_command, params: {name: "QUEUE1", index: index, scope: "DEFAULT"}
Expand All @@ -639,7 +639,7 @@ def generate_queue_hash
}
allow(OpenC3::QueueModel).to receive(:get_model).and_return(queue_model)
allow(queue_model).to receive(:remove_command).and_return(command_data)
allow(controller).to receive(:cmd_no_hazardous_check).with("FRACTIONAL INDEX COMMAND", {queue: false, scope: "DEFAULT", token: anything})
allow(controller).to receive(:cmd).with("FRACTIONAL INDEX COMMAND", {queue: false, scope: "DEFAULT", token: anything})
index = "2.7"

post :exec_command, params: {name: "QUEUE1", index: index, scope: "DEFAULT"}
Expand Down
12 changes: 11 additions & 1 deletion openc3/lib/openc3/microservices/queue_microservice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
require 'openc3/script'

module OpenC3
module Script
private
# Override the prompt_for_hazardous method to always return true since there is no user to prompt
def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
return true
end
end

# The queue processor runs in a single thread and processes commands via cmd_api.
class QueueProcessor
attr_accessor :state
Expand Down Expand Up @@ -73,7 +81,9 @@ def process_queued_commands
token = get_token(username)
# It's important to set queue: false here to avoid infinite recursion when
# OPENC3_DEFAULT_QUEUE is set because commands would be re-queued to the default queue
cmd_no_hazardous_check(command['value'], queue: false, scope: @scope, token: token)
# NOTE: cmd() via script rescues hazardous errors and calls prompt_for_hazardous()
# but we've overridden it to always return true and go straight to cmd_no_hazardous_check()
cmd(command['value'], queue: false, scope: @scope, token: token)
end
rescue StandardError => e
@logger.error "QueueProcessor failed to process command from queue #{@name}\n#{e.message}"
Expand Down
12 changes: 6 additions & 6 deletions openc3/spec/microservices/queue_microservice_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ module OpenC3

before do
allow(processor).to receive(:get_token).with('test_user').and_return('test_token')
allow(processor).to receive(:cmd_no_hazardous_check)
allow(processor).to receive(:cmd)
processor.state = 'RELEASE'
end

Expand All @@ -184,9 +184,9 @@ module OpenC3
processor.process_queued_commands

expect(Store).to have_received(:bzpopmin).exactly(3).times
expect(processor).to have_received(:cmd_no_hazardous_check)
expect(processor).to have_received(:cmd)
.with(command1['value'], queue: false, scope: scope, token: 'test_token')
expect(processor).to have_received(:cmd_no_hazardous_check)
expect(processor).to have_received(:cmd)
.with(command2['value'], queue: false, scope: scope, token: 'test_token')
end

Expand All @@ -199,16 +199,16 @@ module OpenC3
processor.process_queued_commands

expect(Store).to have_received(:bzpopmin).once
expect(processor).not_to have_received(:cmd_no_hazardous_check)
expect(processor).not_to have_received(:cmd)
end

it 'handles errors and continues processing when cmd_no_hazardous_check fails' do
it 'handles errors and continues processing when cmd fails' do
allow(Store).to receive(:bzpopmin) do
processor.state = 'HOLD' if processor.state == 'RELEASE'
["#{scope}:QUEUE", command1.to_json, 0]
end
allow(processor).to receive(:get_token).with('test_user').and_return('test_token')
allow(processor).to receive(:cmd_no_hazardous_check).and_raise(StandardError.new('Command failed'))
allow(processor).to receive(:cmd).and_raise(StandardError.new('Command failed'))
expect(logger).to receive(:error).with(/QueueProcessor failed to process command from queue/)

processor.process_queued_commands
Expand Down
1 change: 1 addition & 0 deletions openc3/spec/script/commands_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
require 'spec_helper'
require 'openc3'
require 'openc3/script'
load 'openc3/script/script.rb' # load to prevent prompt_for_hazardous overrides
require 'openc3/api/api'
require 'openc3/models/target_model'
require 'openc3/microservices/interface_microservice'
Expand Down
2 changes: 0 additions & 2 deletions openc3/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ module OpenC3
end

require 'openc3/top_level'
require 'openc3/script'
# require 'openc3/utilities/logger'
# Create a easy alias to the base of the spec directory
SPEC_DIR = File.dirname(__FILE__)
$openc3_scope = ENV['OPENC3_SCOPE']
Expand Down
Loading