Длительный опрос: Застрял в цикле while


Я пытаюсь написать длинную функцию опроса, которая возвращает данные клиенту только после обновления какой-либо пользовательской post_meta. Эта пользовательская метка post_meta является меткой времени unix, которая затем сравнивается с меткой времени unix, отправленной в функцию клиентом через AJAX. Если значение post_meta превышает значение клиента, значение post_meta отправляется обратно клиенту. Но по какой-то причине функция застревает в цикле while, который сравнивает две временные метки. временные метки unix, похоже, правильно отформатированы и могут быть сопоставлены без проблем, я пробовал это вне цикла while. Но в то время как внутри цикла while и post_meta тем временем обновляется, цикл while не останавливается. Похоже, что условие для цикла while, похоже, никогда не меняется, независимо от обновленного (и, конечно, более высокого) значения в базе данных. Чего мне не хватает?

function my_sync_function () { 

$post_id = intval(wp_strip_all_tags($_GET['post_id'])); // make post ID integer

$lastRequest = wp_strip_all_tags($_GET['timestamp']); // unix timestamp

$lastModified = get_post_meta( $post_id, 'last_modified', true ); // unix timestamp

// do nothing until the lastModified timestamp is greater than the lastRequest timestamp
while ($lastModified <= $lastRequest) {
    usleep(2000000);           
    clearstatcache();    
    $lastModified = get_post_meta( $post_id, 'last_modified', true ); // check for updated timestamp       
}

$result['type'] = 'success';
$result['timestamp'] = $lastModified;
$result = json_encode($result);
echo $result;

die();
}
    add_action('wp_ajax_my_sync_function', 'my_sync_function');
Author: JimQ, 2014-10-26

1 answers

PHP не является многозадачным языком, вы не должны пытаться использовать его как таковой. Другими словами, длительный опрос - это не то, что вам следует даже пытаться делать, если вы не используете языковую конструкцию, предназначенную для его поддержки.

Конкретно к вашему вопросу, вы, вероятно, потерпите неудачу, потому что wordpress имеет привычку кэшировать в памяти как можно больше информации, которая извлекается из БД (это основная функция, никаких плагинов не задействовано). Насколько я помню, как только метаданные post будут извлечены, это кэшируется и поэтому get_post_meta( $post_id, 'last_modified', true ) всегда возвращает одно и то же значение. Вам нужно аннулировать кэш, чтобы иметь возможность делать то, что вы пытаетесь, или отправить запрос в БД в обход API WP.

Кроме того, ваш код очень плохо влияет на производительность сервера, так как вы загружаете один процесс apache, не делая ничего полезного, что, если у вас есть apache для запуска 10 процессов, означает, что вы можете обслуживать на 10% меньше запросов во время работы вашего кода.

Еще одним фактором является php ограничение по времени выполнения, которое обычно устанавливается равным 30 секундам, поэтому ваш длительный процесс опроса просто умрет через 30 секунд без какого-либо уведомления об этом.

 1
Author: Mark Kaplun, 2014-10-26 14:54:46