2014-10-09 4 views
2

Привет, я пытаюсь выполнить запрос (действие) в фоновом режиме.Yii Php Выполнение асинхронного запроса фона

function actionRequest($id){ 

//execute very long process here in background but continue redirect 

Yii::app()->user->setFlash('success', "Currently processing your request you may check it from time to time."); 
$this->redirect(array('index', 'id'=>$id)); 
} 

Что я пытаюсь добиться, чтобы НЕТ пользователя ожидающего за запрос будет обработан, так как он обычно занимает 5-10мин, и запрос обычно идет к тайм-аут, и даже если я установил тайм-аут дольше, ожидая 5-10 мин. не является хорошим пользовательским интерфейсом.

Таким образом, я хочу, чтобы сразу же вернулся на страницу, уведомляя пользователя о том, что его/ее запрос обрабатывается, пока он все еще может просматривать и делать другие вещи в приложении, после чего он может вернуться к и убедитесь, что его/ее запрос обработан.

Я изучал расширения Yii backjob. Он работает, перенаправление выполняется немедленно (как-то фоновый запрос), но при выполнении других действий, например, навигации по сайту, он не загружается, и кажется, что запрос все еще существует, и я не могу продолжать использовать приложение до тех пор, пока запрос не будет завершен.

Аналогичное расширение runactions обещает то же самое, но я даже не мог заставить его работать, он говорит, что он «касается url», как огонь, и забывает работу, но не работает.

Я также попытался разобраться в организации очередей сообщений услуги, такие как Gearman, RabbitMQ, но на самом деле сугубо технический, я даже не мог установить Gearman в моем окна машины так «сельское хозяйство» услуги не будет работать для меня. Некоторые ответы на фоновую обработку включают CRON и AJAX, но это звучит не слишком хорошо, плюс множество проблем.

Есть ли другой способ обхода асинхронной обработки? Я действительно искал этого, и я действительно не ищу продвинутых/сложных решений, таких как «работа над несколькими машинами» и т. Д. Спасибо Большое!

ответ

1

Если вы хотите иметь возможность запускать асинхронные задания через Yii, у вас может не быть выбора, кроме как с помощью AJAX, чтобы получить статус задания асинхронно. Вот рекомендации высокого уровня, которые работали для меня. Надеюсь, это поможет вам каким-то образом!


Настройка консоли действия

Для выполнения фоновых заданий, вам нужно будет использовать компонент консоли Yii в. В разделе/​​protected/commands создайте копию своего веб-контроллера, у которого есть actionRequest() (например, /protected/commands/BulkCommand.php).

Это должно позволить вам войти в вашу/защищенную папку и запустить yiic bulk request.

Имейте в виду, что если вы еще не создали консольное приложение, вам необходимо настроить его конфигурацию, аналогичную тому, как вы это сделали для веб-приложения. Прямая копия /protected/config/main.php в /protected/config/console.php должна выполнять 90% задания.


Настройка расширения для запуска асинхронных заданий консоли

Что работает для меня использует комбинацию из двух расширений: CConsole и TConsoleRunner. TConsoleRunner использует popen для запуска сценариев оболочки, которые работали для меня в Windows и Ubuntu. Я просто сливался своим кодом запуска() в CConsole следующим образом:

public function popen($shell, $redirectOutput = '') 
{ 
    $shell = $this->resolveCommandLine($shell, false, $redirectOutput); 
    $ret = self::RETURN_CODE_SUCCESS; 
    if (!$this->displayCommands) { 
     ob_start(); 
    } 

    if ($this->isWindows()) { 
     pclose(popen('start /b '.$shell, 'r')); 
    } 
    else { 
     pclose(popen($shell.' > /dev/null &', 'r')); 
    } 

    if (!$this->displayCommands) { 
     ob_end_clean(); 
    } 
    return $ret; 
} 

protected function isWindows() 
{ 
    if(PHP_OS == 'WINNT' || PHP_OS == 'WIN32') 
     return true; 
    else 
     return false; 
} 

Затем я изменил RunCommand CConsole в() к следующему:

public function runCommand($command, $args, $async = false, &$outputLines = null, $executor = 'popen') 
    { 
     ... 
     switch ($executor) { 
      ... 
      case 'popen': 
       return $this->popen($shell); 
      ... 
     } 
    } 


Запуска асинхронной работы

С приведенной выше настройкой вы можете использовать следующий фрагмент кода для вызова yiic bulk request, который мы создали ранее.

$console = new CConsole(); 
$console->runCommand('bulk request', array(
    '--arg1="argument"', 
    '--arg2="argument"', 
    '--arg3="argument"', 
)); 

Вы должны вставить это в свое оригинальное actionRequest().


Проверка на статус

К сожалению, я не уверен, что такая работа делает ваш запрос навалом. Для себя я собирал целую кучу файлов и помещал их в папку. Я знал, сколько файлов я ожидал, поэтому я мог бы легко создать действие контроллера, которое проверяет, сколько файлов было создано до сих пор, и дать% статуса как простого деления.

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