Привет я пытаюсь выполнить ДЛИННЫЙ БЕГ запрос (действие) в фоновом режиме.
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 на свою машину с Windows, так что «фермерские» услуги мне не подойдут. Некоторые ответы на фоновую обработку включают CRON и AJAX, но это звучит не слишком хорошо, а также множество проблем.
Есть ли другой способ обойти асинхронную фоновую обработку? Я действительно стремился к этому, и я действительно не ищу продвинутых / сложных решений, таких как «отработка работы на нескольких машинах» и тому подобное. Спасибо Большое!
Если вы хотите иметь возможность запускать асинхронные задания через 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. Я просто слил код run () в 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 ().
К сожалению, я не уверен, какую работу выполняет ваш массовый запрос. Для себя я собирал целую кучу файлов и помещал их в папку. Я знал, сколько файлов я ожидал, так что я мог легко создать действие контроллера, которое проверяет, сколько файлов было создано до сих пор и дает% статуса в виде простого деления.
Других решений пока нет …