[PHP] Подскажите функцию

kruzer25

К скрипту приходит запрос. Надо сказать клиенту, что запрос обрабатывается, и продолжить обработку (которая может быть очень долгой чтобы клиент при этом больше не ждал ответа.
<?php
echo 'Your request has been accepted';
?
some_long_processing_that_can+take_up_to_several_hours_or_days;
?>

Что должно стоять на месте "?", чтобы клиент сразу решил, что не надо ждать ответа, что весь ответ уже получен?

pitrik2

то есть ты спрашиваешь как flush сделать?
или спрашиваешь как твою долгую процедуру в отдельном потоке запустить, чтобы дать изначальному потоку подохнуть?

kruzer25

то есть ты спрашиваешь как flush сделать?
Точнее, как сделать "окончательный" flush, чтобы клинет не ждал, не выведется ли там ещё чего-нибудь после этой длинной процедуры, и оборвал подключение к серверу.
или спрашиваешь как твою долгую процедуру в отдельном потоке запустить, чтобы дать изначальному потоку подохнуть
Например. Хотя, вроде бы, был какой-то способ просто сказать клиенту, что он должен отвалиться...

yolki

м.б. тут стоит ajax прикрутить?

kruzer25

и перед реализацией функционала ajax-а встанет такая же проблема.
Как запустить выполнение очень долгой процедуры, чтобы клиент отвалился, не дожидаясь её окончания? ajax - это те же яйца, только сбоку.
ЗЫ: На самом деле, клиентом будет другой php-скрипт

yolki

можно рефрешем поиграться.
но на аджаксе я бы сделал дёргалку функции типа "готов_ли_ответ_на_мой_запрос" и если там "готово", брал бы ответ..
на то он и аджакс - для асинхронности

kruzer25

но на аджаксе я бы сделал дёргалку функции типа "готов_ли_ответ_на_мой_запрос"
Замечательно. Сам-то запрос где начнёшь обрабатывать?

kruzer25

На всякий случай поясню - клиенту насрать, готов ли там ответ, ему вообще этот ответ не нужен. А эта ajax-овая примочка никак не поможет клиенту подать запрос так, чтобы он отвалился, не ожидая ответа.

yolki

чё-то я не понял вопроса.
пусть есть query.php, который формирует ответ на запрос.
при его запуске он генерит страницу типа (спасибо, ваш запрос обрабатывается).
при этом периодически чекается query_result_status.php. если там "ready", то запрашиваем get_query_result.php
связку хоть по PHPSESSID делай

kruzer25

пусть есть query.php, который формирует ответ на запрос.
при его запуске он генерит страницу типа (спасибо, ваш запрос обрабатывается).
при этом периодически чекается query_result_status.php
Повторю вопрос ещё раз. Где ты собрался на сервере запускать обработку самого запроса?
<?php
echo "спасибо, ваш запрос обрабатывается"
?>

И где тут обработка запроса?
при этом периодически чекается query_result_status.php
Да насрать на статус.

uncle17

ну-у-уу... если запрос гетом, то во фрейм (или ифрейм) размером 1х1 соседний его яваскриптом передаешь
Можно и не 1х1, в принципе пох
Проще всего так.

kruzer25

если запрос гетом, то во фрейм (или ифрейм) размером 1х1 соседний его яваскриптом передаешь
Те же яйца, только сбоку.
Клиент не отваливается, но пользователь этого не увидит (если не посмотрит в строку состояния).
А в данном случае, клиент - не человекк, который сидит в браузере, а сервер, которому надо пнуть другой сервер, чтобы тот начал обрабатывать запрос. При этом, скрипт на первом сервере должен сказать "всё, запрос выполняется" и сдохнуть. Варианты вида "переписать скрипт на первом сервере, чтобы он висел, но это не было заметно пользователю первого сервера" не подходят, вопрос в том, что надо написать на втором сервере, чтобы первый понял, что ждать нечего.
Да, первый сервер, конечно, не будет лезть на второй через какие-то там сокеты, всё цивильно, через curl в худшем случае.

mkrec

я так понял, ты хочешь, чтобы клиент стартовал задачу на сервере, а затем задача вела себя так, будто она независима? А ты не можешь экзекнуть стороннее приложение с этой задачей и спокойно завершить формирование страницы?

kruzer25

А ты не можешь экзекнуть стороннее приложение с этой задачей
Могу, конечно.
Но вроде был какой-то цивильный способ решения такой проблемы, что-то типа client_abort.

Andr163

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

kruzer25

можно сделать так: раз в минуту запускается скрипт, который проверяет наличие в каком-то файле единички, если она есть - запускается большая_и_толстая_функция
Молодец, изобрёл велосипед.
Крон - тоже не вариант (тем более, что второй сервер - не наш, и никто нас к крону не пустит хочется всё сделать наиболее красиво.

Andr163

ну если не страшно, что одновременно будут работать несколько больших_и_толстых_функций

kruzer25

ну если не страшно, что одновременно будут работать несколько больших_и_толстых_функций
Ну ты подумай ещё, может, и мьютексы изобретёшь

Andr163

ну ты тоже подумай тогда

kruzer25

Прочитай ещё раз мой первый пост. Там вопрос поставлен предельно точно

pitrik2

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

sinet

попробуй register_shutdown_function

kruzer25

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

kruzer25

В смысле, в register_shutdown_function повесить вызов большой и толстой функции?
Не катит:
<?php

function test {
echo 'test'.PHP_EOL;
}

register_shutdown_function('test');

?>

выдаёт "test", а не должно выдавать ничего.

psm-home

А если клиента редиректить куда еще, отдавая ему подходящий заголовок с помощью вызова header ? Клиент уйдет на страничку "ваша заявка принята", а скрипт продолжит выполнение. (Я PHP не знаю, поэтому возможно совет фиговый.)

kruzer25

А если клиента редиректить куда еще, отдавая ему подходящий заголовок с помощью вызова header ?
О, хороший вариант, кстати.
Вообще, по идее, header('Location: ...') где-то внутри делает как раз такую хрень, которая мне нужна... а можно ли это как-нибудь получить без использования header?

uncle17

О, хороший вариант, кстати
а при этом разве не прекращается выполнение скрипта?

kruzer25

Зависит от настроек php, можно сделать, чтобы не прекращалось.

Fragaria

Какой нахуй хедер? Он не пошлётся, если в браузер уже начат вывод. Максимум что можно сделать - редирект с помощью джаваскрипта.
А вообще мой труЪ-вариант таков:
<?php
echo 'Your request has been accepted';
echo 'Можете уже закрыть браузер нахрен';
some_long_processing_that_can+take_up_to_several_hours_or_days;
?>

pitrik2

Какой нахуй хедер? Он не пошлётся, если в браузер уже начат вывод
дык вывода и не будет
хедер сразу на статическую страницу с текстом "подождите"

psm-home

Какой нахуй хедер? Он не пошлётся, если в браузер уже начат вывод.
Ясный пень не пошлется, так не надо ничего выводить клиенту, послать редирект и все.

uncle17

Какой нахуй хедер? Он не пошлётся, если в браузер уже начат вывод
прекрасно он пошлется
Попробуй

1
<?php
header('Location:http://forum.b.gz.ru')
?>

Fragaria

А, так в этом случае браузер отконнектится от сервера, и скрипт ляжет.
Я бы предложил запускать скрипт с помощью system, открепляя его от родительского процесса.

Fragaria

1
header('Location//forum.b.gz.ru')
?>
X-Powered-By: PHP/5.2.0
Content-type: text/html
1
Warning: Cannot modify header information - headers already sent by (output started at PHPDocument1:2) in PHPDocument1 on line 3

kruzer25

echo 'Your request has been accepted';
echo 'Можете уже закрыть браузер нахрен';
Ага, а на первом сервере - мегаинтеллектуальный курл, который поймёт, что можно уже прибить коннект нахрен и передать управление тому, что дальше.

uncle17

гыг
а меня прекрасно перенаправил из браузера

kruzer25

Попробуй
У тебя просто кэширование включено.

uncle17

причем тут кеширование?

Fragaria

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

Fragaria

Он просто имеет в виду буферизацию вывода. С ней весь вывод хранится в буфере до момента окончания работы скрипта, или до ob_flush.

kruzer25

При том, что у тебя эта единичка в буфере лежит, и не отправляется клиенту.

kruzer25

Тебе сказано уже - нельзя прибивать коннект
Кем сказано?

Fragaria

Ради интереса поставь перед хедером слип в 5 секунд и посмотри, выведется ли твоя единичка. Спорю на пиво, что не выведется.

uncle17

да, точно. Добавил ob_flush - браузер сказал "already sent"

Fragaria

Ладно, пенартур, пожалею я тебя.
ignore_user_abort

pitrik2

А, так в этом случае браузер отконнектится от сервера, и скрипт ляжет.
дык пенартур говорит что есть настройка пхп что скрипт не ляжет

kruzer25

Я знаю про эту функцию. Она даёт продолжать обработку после того, как клиент перейдёт по header/отвалится по таймауту/просто порвёт соединение.
Вопрос в том, как заставить клиента отвалиться.

Fragaria

Вот тут миллион решений. Если клиентом будет другой PHP-скрипт, то он тупо может анализировать выходной поток и при получении строки "Идите нахуй, пожалуйста" закрывать соединение. Что сложного-то?

kruzer25

Если клиентом будет другой PHP-скрипт, то он тупо может анализировать выходной поток и при получении строки "Идите нахуй, пожалуйста" закрывать соединение
Ага, и при этом переписывать всё под сокеты?
curl_exec, он тебе по частям ответ выдавать не будет.

Fragaria

Кто тебе мешает заголовком ему отправить заранее определённый content_length?

kruzer25

О, спасибо - грязный хак, но работает.

kruzer25

Нет, хуй там.
<?php
header('Content-Length: 2');
echo 'abcdefg';
flush;
sleep(20);
file_put_contents('test.txt','test3.txt');
?>

Браузер двадцать секунд грузит, после чего выдаёт "ab"...

Fragaria

Ты не браузером проверяй, а curl'ом. Браузер в любом случае ждёт обрыва соединения, поэтому для него можно поиграться с content_type, в частности, попробовать указать ему, что он получает поток.

Fragaria

Да, кстати, проверь ещё оперой, потому что возможен такой вариант, что браузер тупо не начинает отрисовку страницы до тех пор, пока не получит разрыв соединения, поэтому рисует твои "ab" только по таймауту.

kruzer25

file_get_contents ждёт и выдаёт весь вывод.
curl ждёт и выдаёт первые два символа.

Fragaria

Значит делай как я сказал: запускай "system'ом" процесс и отвязывай его от родительского.

kruzer25

Ну и говно.
ЗЫ: curl с CURL_FOLLOWLOCATION при использовании header:location точно так же тупит, хотя совершенно непонятно, какого хрена - уже и заголовки ему все отдали, и flush текста сделали, а он всё равно завершения работы скрипта ждёт, прежде чем по header: location перейти

Fragaria

Окей, способ интересней: делаешь pcntl_fork, смотришь, какой результат возвратила функция, и если 0 - то запускаешь длинный процесс (значит ты форкнутый щаз если не ноль - то тупо заканчиваешь себя.

Fragaria

Бля. У тебя PHP модулем к апачу? Тогда не прокатит.

kruzer25

Бля. У тебя PHP модулем к апачу?
У меня на том сервере может быть абсолютно всё, что угодно. Известно только, что та мбудет php.
Похоже, придётся ждать завершения работы того скрипта, а это ещё некоторое количество геморроя - за транзакциями следить, таймаут корректно обрабатывать...

Fragaria

Тогда делай PHP CGI-приложением и форкайся. Форкнутый процесс отвязан от стандартного ввода апача, поэтому апач закроет коннект при завершении родительского приложения, а дочернее будет работать.

kruzer25

Тогда делай PHP CGI-приложением
Повторю ещё раз - там php может быть чем угодно. Требовать, чтобы там он был cgi-приложением - слишком геморройно, легче уж ответа ждать.

Fragaria

А-а-а, я просто тебя понял в том смысле, что ты на тот сервер что угодно можешь поставить.

kruzer25

На тот сервер я могу поставить какие угодно скрипты.
А на этом сервере хочется использовать уже существующие прослойки, а не лезть напрямую в сокеты.

sbs-66

А у меня вот такая идея возникла. Что если передать браузеру хедер с редиректом и сказать, что соединение keep alive, а не close. По идее он тогда должен начать отоброжение сразу, а не ждать закрытия соединения. И получив header должен сразу средиректиться. Хотя может я и ошибаюсь - пробовать в лом.

sbs-66

Хотя не, посмотрел щас - почти все сервера и так keep alive говорят

Vladislav177Rus

Кросспост:
А register_shutdown_function тебе не поможет?

kruzer25

А прочитать тред ты не можешь?
Оставить комментарий
Имя или ник:
Комментарий: