Мне бы очень хотелось подумать об этом подходе, который я внедряю для обработки очень длинных процессов в веб-приложении.
Проблема
У меня есть сетьПриложение, все написано в javascript, который общается с сервером через API.В этом приложении есть несколько «массовых действий», выполнение которых занимает много времени.Я хочу выполнить их безопасным способом, убедившись, что время ожидания сервера не истекло, и с обширной обратной связью с пользователем, чтобы он / она знали, что происходит.
Обычныйподход
Как я могу видеть в своем исследовании, рекомендуемый метод выполнения - запуск фонового процесса на сервере и заставить его написать куда-нибудь, как он работает, чтобы вы могли делать запросы на проверку идать отзыв пользователю.Так как я использую php в бэк-энде, подход будет более или менее описан здесь: http://humblecontributions.blogspot.com.br/2012/12/how-to-run-php-process-in-background.html
Добавление нескольких реквизитов
Поскольку Im разрабатываетсяпроект с открытым исходным кодом (плагин WordPress) Я хочу, чтобы он работал в различных ситуациях и средах.Я не хотел добавлять требования на стороне сервера, и, насколько мне известно, подход с использованием фоновых процессов может не работать в нескольких решениях общего хостинга.
Я хочу, чтобы он работал "из коробки" на (почти) любом сервере с типичной поддержкой WordPress, даже если в конечном итоге решение оказалось немного медленнее.
Мой подход
Идея состоит в том, чтобы разбить этот процесс таким образом, чтобы он постепенно выполнялся посредством множества небольших запросов.
Поэтому, когда браузер в первый раз отправляет запрос на запуск процесса, он запускаетсятолько маленький шаг и верните полезную информацию, чтобы дать пользователю некоторую обратную связь.Затем браузер выполняет другой запрос и повторяет его до тех пор, пока сервер не сообщит, что процесс завершен.
Чтобы сделать это, я бы сохранил этот объект в сеансе, поэтому первый запрос даст мне идентификатори следующие запросы отправят этот идентификатор на сервер, чтобы он управлял одним и тем же объектом.
Вот концептуальный пример:
class LongProcess {
function __construct() {
$this->id = uniqid();
$_SESSION[$this->id] = $this;
$this->step = 1;
$this->total = 100;
}
function run() {
// do stuff based on the step you are in
$this->step = $this->step + 10;
if ($this->step >= $this->total)
return -1;
return $this->step;
}
}
function ajax_callback() {
session_start();
if (!isset($_POST['id']) || empty($_POST['id'])) {
$object = new LongProcess();
} else {
$object = $_SESSION[$_POST['id']];
}
$step = $object->run();
echo json_encode([
'id' => $object->id,
'step' => $return,
'total' => $object->total
]);
}
Теперь я могу отправить своего клиентазапрашивает рекурсивно и обновляет обратную связь с пользователем по мере получения ответов.
function recursively_ajax(session_id)
{
$.ajax({
type:"POST",
async:false, // set async false to wait for previous response
url: "xxx-ajax.php",
dataType:"json",
data:{
action: 'bulk_edit',
id: session_id
},
success: function(data)
{
updateFeedback(data);
if(data.step != -1){
recursively_ajax(data.id);
} else {
updateFeedback('finish');
}
}
});
}
$('#button').click(function() {
recursively_ajax();
});
Конечно, это всего лишь подтверждение концепции, я даже не использую jQuery в реальном коде.Это просто, чтобы выразить идею.
Обратите внимание, что этот объект, который хранится в сеансе, должен быть очень легким объектом.Любые обрабатываемые данные должны храниться в базе данных или файловой системе и ссылаться на них только в объекте, чтобы он знал, где искать вещи.
Одним типичным случаем является обработка большого файла CSV.Файл будет храниться в файловой системе, а объект будет хранить указатель на последнюю обработанную строку, чтобы он знал, с чего начать в следующем запросе.
Объект также может возвращать более подробный журнал, описывающий всеэто было сделано и сообщало об ошибках, так что пользователь полностью знал, что было сделано.
Интерфейс, который я думаю, был бы отличным, это индикатор выполнения с кнопкой «посмотреть детали», которая открыла бы текстовое поле с этимподробный журнал.
Имеет ли это смысл?
Так что теперь я спрашиваю.Как это выглядит?Это жизнеспособный подход?
Есть ли лучший способ сделать это и убедиться, что он будет работать на очень ограниченных серверах?