Ruby calls python functions over http, asynchronous communication causes the return result to lag, and the program error

ruby calls python functions through http, I need to request http multiple times, and the result I need to return changes the scene, but the http protocol is asynchronous communication, multiple requests will be sent quickly, the result is lagging back, and the result in the code block cannot be returned, can the above structure control the sending of the request?
Here’s a code block that calls http in a loop:


num_time.times do |t|
    model_properties = {}
    model_properties['times']=times
    model_properties['key']=key
    model_properties['bracket_vertex_all']=bracket_vertex_all
    model_properties['component_vertex_all']=component_vertex_all
    model_properties['sun_vector']=direction_towards_sun.to_a
    json_text = JSON.generate(model_properties) 
    @request = Sketchup::Http::Request.new("http://127.0.0.1/single_time", Sketchup::Http::POST)
    @response=nil
    @request.headers= { 'Content-Type' => 'application/json' }
    @request.body = json_text
    @request.start do |request, response|
      a=JSON.parse(response.body) 

     #return a  # Return will report an error

    end
end

Whether http has a way to communicate synchronously, or through a program-controlled loop, waiting for the request to return to the structure and then requesting again.

SketchUp’s HTTP classes are asynchronous by design, so that they will not halt SketchUp.

Your example is using the same @vars so the next time it will be overridden.

Try keeping arrays …

  @requests  = []
  @responses = []

  num_time.times do |t|
    model_properties = {}
    model_properties['times']=times
    model_properties['key']=key
    model_properties['bracket_vertex_all']=bracket_vertex_all
    model_properties['component_vertex_all']=component_vertex_all
    model_properties['sun_vector']=direction_towards_sun.to_a
    json_text = JSON.generate(model_properties) 
    @requests << request = Sketchup::Http::Request.new(
      "http://127.0.0.1/single_time", Sketchup::Http::POST
    )
    request.headers= { 'Content-Type' => 'application/json' }
    request.body = json_text
    request.start do |request, response|
      @responses << JSON.parse(response.body) 
    end
  end

You will have to use Ruby’s standard Net library for synchronous HTTP requests.

1 Like

@zuoyou

The below will work, but I’m not sure how much you’ve simplified the code example. If the server is local, it should work fine, but the code would need more error handling if the server was remote.

If the server is local, you could just use a tcp socket instead of a http connection…

require 'json'
require 'net/http'

HOST = '127.0.0.1'
PORT = 80
PATH = '/single_time'

Net::HTTP.start(HOST, PORT) do |http|
  model_properties = {}
  req = Net::HTTP::Post.new PATH
  req['Content-Type'] = 'application/json'

  num_time.times do |t|
    # added for testing
    model_properties['index'] = t
    model_properties['times'] = times
    model_properties['key'] = key
    model_properties['bracket_vertex_all'] = bracket_vertex_all
    model_properties['component_vertex_all'] = component_vertex_all
    model_properties['sun_vector'] = direction_towards_sun.to_a

    req.body = JSON.generate model_properties

    resp = http.request req

    case resp
    when Net::HTTPSuccess
      # Process JSON.parse(resp.body)
    when Net::HTTPRedirection
      # ? follow ?
    else
      raise "#{resp.class}"
    end
  end
end

Thanks for the method, I thought of a workaround in my attempt, changing the circular request to a recursive call, which avoids the hassle of asynchrony

def(times)
    model_properties = {}
    model_properties['times']=times
    model_properties['key']=key
    model_properties['bracket_vertex_all']=bracket_vertex_all
    model_properties['component_vertex_all']=component_vertex_all
    model_properties['sun_vector']=direction_towards_sun.to_a
    json_text = JSON.generate(model_properties) 
    @request = Sketchup::Http::Request.new("http://127.0.0.1/single_time", Sketchup::Http::POST)
    @response=nil
    @request.headers= { 'Content-Type' => 'application/json' }
    @request.body = json_text
    @request.start do |request, response|
      a=JSON.parse(response.body) 
      times=times+t
      def(times)
    end
end