Как запустить REST-вызов одновременно или с более низким приоритетом

Я загружаю данные через вызов REST и рендеринг его. После этого я вызываю другой REST API, который занимает около 10 секунд. В это время я не могу сделать еще один вызов REST, пока этот не закончится. У меня вопрос, как я могу это сделать?

Я пытался с потоком, но это не работает, возможно, я делаю что-то не так, или, возможно, потоки не правильный выбор?

Это названный маршрут:

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

Как я могу запустить код в строке 8-22 в "фоне", чтобы другие вызовы имели приоритет?

1 ответ

Команда t.join ждет окончания потока. Если вы хотите, чтобы ваш поток работал в фоновом режиме, просто запустите и забудьте:

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

Конечно, проблема в том, что вы получаете кучу мертвых потоков, которые накапливаются во время работы вашего сервера. И если вы работаете в REST API (разработанном так, чтобы он не имел состояния), это может быть не так просто, как перебрасывать ваши потоки в массив и периодически очищать их.

В конечном счете, я думаю, вы должны изучить асинхронные обработчики заданий. Я работал с sidekiq и хорошо провел время, но у меня недостаточно опыта, чтобы дать вам искреннюю рекомендацию.

Другие вопросы по тегам