0

I am loading data via a REST call and rendering it. After that, I am calling another REST API which takes about 10 seconds. In this time, I can't make another REST call until this one is finished. My question is, how can I do this?

I tried with a thread, but it is not working, maybe I am doing something wrong, or maybe threads are not the correct choice?

This is the called route:

get '/api/dashboard/:dbnum/block/:blnum/inbackground/:inbackground' do
  user = get_current_userobject
  return assemble_error('LOGIN', 'NOTLOGGEDIN', {}, []).rest_fail if !user

  dbnum,blnum = params[:dbnum].to_i, params[:blnum].to_i
  return { rows: [] }.rest_success if !user.dashboardinfo || !user.dashboardinfo[dbnum] || !user.dashboardinfo[dbnum]['blocks'] || !(block = user.dashboardinfo[dbnum]['blocks'][blnum]) || !respond_to?("dashboard_type_#{block['type']}", true)

  if params[:inbackground] == 'true'

    t = Thread.new do

      t.priority= -1

      ret = method("dashboard_type_#{block['type']}").call(block['filters'], false, true)

      ret.rest_success
    end

    t.join

    t.exit

  else
    ret = method("dashboard_type_#{block['type']}").call(block['filters'], false, false)
    ret.rest_success
  end

end

How can I run the code inside line 8 to 22 in the 'background' so other calls have, like, priority?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303

1 Answers1

0

The command t.join waits for a thread to finish. If you want your thread to run in the background, just fire and forget:

get '/api/dashboard/:dbnum/block/:blnum/inbackground/:inbackground' do
  user = get_current_userobject
  return assemble_error('LOGIN', 'NOTLOGGEDIN', {}, []).rest_fail if !user

  dbnum,blnum = params[:dbnum].to_i, params[:blnum].to_i
  return { rows: [] }.rest_success if !user.dashboardinfo || !user.dashboardinfo[dbnum] || !user.dashboardinfo[dbnum]['blocks'] || !(block = user.dashboardinfo[dbnum]['blocks'][blnum]) || !respond_to?("dashboard_type_#{block['type']}", true)

  if params[:inbackground] == 'true'

    t = Thread.new do

      t.priority= -1

      ret = method("dashboard_type_#{block['type']}").call(block['filters'], false, true)

      ret.rest_success
    end

  else
    ret = method("dashboard_type_#{block['type']}").call(block['filters'], false, false)
    ret.rest_success
  end

end

Of course the problem with this is that you get a bunch of dead threads building up as your server runs. And if you're working in a REST API (designed to be stateless), it might not be as simple as throwing your threads into an array and periodically cleaning them up.

Ultimately, I think, you should look into asynchronous job handlers. I've worked with sidekiq and had a decent time, but I don't have enough experience to give you a whole-hearted recommendation.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
eiko
  • 5,110
  • 6
  • 17
  • 35