2015-11-17 6 views
0

В моей Синатра веб-приложения, у меня есть маршрут:Run, когда вы можете

get "/" do 
    temp = MyClass.new("hello",1) 
    redirect "/home" 
end 

Где MyClass является:

class MyClass 
    @instancesArray = [] 
    def initialize(string,id) 
     @string = string 
     @id = id 
     @instancesArray[id] = this 
    end 
    def run(id) 
     puts @instancesArray[id].string 
    end 
end 

В какой-то момент я хочу, чтобы запустить MyClass.run(1), но я Wouldn» t хочет, чтобы он выполнялся немедленно, потому что это замедлит реакцию серверов на некоторых клиентов. Я бы хотел, чтобы сервер подождал, чтобы запустить MyClass.run(temp), пока не было времени с более легкой нагрузкой. Как я могу сказать, чтобы он подождал, пока будет пустая/легкая нагрузка, а затем запустите MyClass.run(temp)? Я могу это сделать?

Добавление

Вот некоторые примеры кода для того, что я хотел бы сделать:

$var = 0 

get "/" do 
    $var = $var+1 # each time a request is recieved, it incriments 
end 

После того, что я бы цикл, который будет рассчитывать запросов/мин (так через минуту он сбросит $var на 0, и если $var был меньше некоторого числа, тогда он будет запускать задачи, используя увеличенную нагрузку.

ответ

0

MyClass.run(temp) никогда не выполняется. наш текущий запрос к / пути вы создаете экземпляр нового экземпляра MyClass, после чего он немедленно сделает запрос get к /home. Я не совсем уверен, в чем вопрос. Если вы хотите что-то выполнить после перенаправления, эта функциональность должна существовать в пределах маршрута /home.

get '/home' do 
    # some code like MyClass.run(some_arg) 
end 
+0

Opps извините! Опечатка! Это могло бы быть лучше как комментарий. Сейчас я задал вопрос. – thesecretmaster

2

Как Эндрю упоминалось (правильно-не знаю, почему он был отвергнут), Синатра stops обработки маршрута, когда он видит redirect, поэтому любые последующие заявления никогда не будет выполняться. Как вы заявили, вы не хотите ставить эти заявления доredirect, потому что это заблокирует запрос до его завершения. Вы могли бы отправить статус переадресации и заголовок клиенту без использования метода redirect и затем позвонить MyClass#run. Это будет иметь желаемый эффект (с точки зрения клиента), но процесс сервера (или поток) будет блокироваться до его завершения. Это нежелательно, потому что этот процесс (или поток) не сможет обслуживать какие-либо новые запросы, пока он не разблокируется.

Вы можете развернуть новый процесс (или создать новый поток) для асинхронной обработки этой фоновой задачи из основного процесса, связанного с запросом. К сожалению, этот подход может стать беспорядочным. Вам придется кодировать в разных ситуациях, например, при неудачной фоновой задаче, или в случае отказа fork/spawn, или процесс основного запроса не заканчивается, если ему принадлежит текущий поток или другой процесс. (Отказ от ответственности: я не знаю достаточно о IPC в Ruby и Rack под разными серверами приложений, чтобы понять все различные сценарии, но я уверен, что здесь есть драконы.)

Наиболее распространенный шаблон решения для этот тип проблемы заключается в том, чтобы подтолкнуть задачу к какой-то рабочей очереди, которая будет обслуживаться позже другим процессом. Нажатие задачи на очередь в идеале - очень быстрая операция и не будет блокировать основной процесс более чем на несколько миллисекунд. Это вводит несколько новых задач (где очередь? Как описывается задача, чтобы ее можно было облегчить в более позднее время без какого-либо контекста? Как мы поддерживаем рабочие процессы?), но, к счастью, многие работы ног уже были сделаны другими людьми. :-)

Существует драгоценный камень delayed_job, который, как представляется, обеспечивает хорошее решение «все-в-одном». К сожалению, он в основном ориентирован на Rails и ActiveRecord, и усилия, предпринимаемые людьми в прошлом, чтобы заставить его работать с Sinatra, выглядят невосприимчивыми. Современные каркасно-агностические решения: Resque и Sidekiq. Может потребоваться некоторое усилие, чтобы встать и работать с любым вариантом, но было бы неплохо, если бы у вас было несколько функций «запускать, когда вы», в своем приложении.

+0

Я уже видел решение рабочей очереди и смотрел, было ли что-то лучше, потому что решение рабочей очереди все равно замедляет следующий запрос, потому что сервер будет занят и будет иметь меньше ресурсов. Но +1 за большой подробный ответ! Я обязательно посмотрю на этот драгоценный камень, поскольку это кажется самым перспективным решением для меня. – thesecretmaster

+0

Но то, что я также ищу, - это способ запускать вещи, когда трафик сервера уменьшается. Поэтому мне понадобится что-то, что просто отслеживает трафик, и когда загрузка на сервере будет легкой, он выполнит задачи. – thesecretmaster

+0

Самый простой способ сделать это - запустить фоновый процесс (ы) с помощью «nice», который «намекает» на ядро ​​для запуска команды с более низким приоритетом. – mwp

Смежные вопросы