My Sinatra-based ruby app works just fine locally, however, when I push it to CloudFoundry, the page times out before the app prints the results on the page (Says: "hc.run.company.com took too long to respond. HTTP ERROR 504
). This is my main.rb
:
require 'rest-client'
require 'sinatra'
require 'open-uri'
require 'net/http'
require 'dir'
require 'json'
# require 'sinatra/async'
# require 'socket'
class DevMonit < Sinatra::Base
# register Sinatra::Async
@@services = Array.new
def self.register(service)
@@services << service
end
get '/url/:url' do
url = params[:url].to_s # Store 'url' parameter
is_verbose = params[:v].to_s # Store 'v' parameter
# stream :keep_open do |out|
# print 'out = ' # DEBUG
# p out # DEBUG
# check_status(url, is_verbose) do |x|
# out << "x=#{x}"
# out.close
# end
# end
return check_status(url, is_verbose)
end
def verbose(is_verbose)
if !is_verbose.nil? && is_verbose == 'true'
return true
else
return false
end
end
def check_status(uri_str, is_verbose, limit = 10)
response = RestClient.get "#{uri_str}"
case response.code
when 200...300
@@services.each do |service|
if service.is_matched?("#{uri_str}")
tool_name = service.class.name.split('::').last.downcase # Fetch the name of the Class for the tool_name
@@result = service.check_tool_specific("#{tool_name}","#{uri_str}", "#{verbose(is_verbose)}")
end
end
if @@result.nil?
return 'No results, something went wrong!'
end
return "#{@@result.to_json}"
when Net::HTTPRedirection then
location = response['location']
check_status(location, limit - 1)
else
puts "It doesn't work!"
puts "#{response.code}"
end
rescue SocketError => e; #do something with e.message
return {
:url => uri_str,
:timestamp => Time.now.strftime('%Y-%m-%d %T'),
:results => 'Cannot resolve the hostname'
}
end
run! if app_file == $0
end
I am trying to have a thread that feeds the browser something to keep it alive (HTTP CODE 200?) while it's executing the return check_status(url, is_verbose)
or at if service.is_matched?("#{uri_str}")
. The reason why I am trying to do this is because the app triggers a Jenkins job and waits for it to finish which then the app takes the necessary information puts it in a json format (which is the output), then outputs it from return "#{@@result.to_json}"
.
I've been reading on how to do this but, I can't make it work, (I've tried doing something with sockets and that failed miserably, I also tried doing something like this and that didn't work either).
Any kind of guidance is appreciated.
UPDATE:
This is the code where it takes the longest time (waits for Jenkins job to finish to pull required information):
# require 'em-http-request'
class WaitForJob
def self.job(current_build_json, last_build_json, start_job)
job_result_hash = Hash.new{|hsh,key| hsh[key] = {} } # Initialize a Hash for storing the results
start_job.send_request # Start the Jenkins Job
get_current_build_number = CheckJSON.get_from_json("#{current_build_json.send_request}", 'nextBuildNumber') # Fetch the nextBuildNumber as soon as the job starts (as that doesn't increment while it's in queue); the nextBuildNumber is going to be the currentBuildNumber
current_build_number = get_current_build_number.to_i # Save that nextBuildNumber to a separate variable for comparison
get_last_build_number = CheckJSON.get_from_json("#{last_build_json.send_request}", 'number')
get_last_build_duration = CheckJSON.get_from_json("#{last_build_json.send_request}", 'duration')
get_last_build_result = nil
loop do
Timeout::timeout(120) do
# EM.run do
sleep(5) # DEBUG
get_last_build_number = CheckJSON.get_from_json("#{last_build_json.send_request}", 'number')
get_last_build_result = CheckJSON.get_from_json("#{last_build_json.send_request}", 'result')
get_last_build_duration = CheckJSON.get_from_json("#{last_build_json.send_request}", 'duration')
# conn = EM::HttpRequest.new('http://localhost:9000/')
# start = Time.now
# r1 = conn.get :query => {delay: 1.5}, :keepalive => true
# r2 = conn.get :query => {delay: 1.0}
# r2.callback do
# p Time.now - start # => 1.5 - keep-alive + pipelining
# EM.stop
# end
# end
end
break if !get_last_build_result.nil? && !get_last_build_duration.zero? && (current_build_number == get_last_build_number) # End the loop when job is done
end
job_name = "#{CheckJSON.get_from_json("#{last_build_json.send_request}", 'fullDisplayName')}" # Fetch job's name
job_name = job_name.split(/ |\./) # Splits the job_name using '.' and ' ' as delimiters
job_result_hash['job_type'] = "#{job_name[3]}" # This takes the last part of the jenkins job name (Ex: Dev.eng-paas.devtools.TESTING_INTEGRATION_JOB)
job_result_hash['build_number'] = "#{current_build_number}" # Return the build number also which can be used in different situations
job_result_hash['job_duration'] = "#{CheckJSON.get_from_json("#{last_build_json.send_request}", 'duration')}" # Fetches the duration of job
job_result_hash['job_result'] = "#{CheckJSON.get_from_json("#{last_build_json.send_request}", 'result').downcase}" # Fetches if the job was successful/unstable/failure
return job_result_hash
end
end