Отменить действие Wordpress (или любую другую функцию PHP)

У меня есть плагин Wordpress, который отправляет данные поста после изменения пост / постмета.

Проблема заключается в том, что на занятом сайте Wordpress может быть очень много изменений postmeta, поэтому я бы хотел отменить / ограничить / агрегировать мета-обновления для одного вызова POST, заключенного в 1 секунду.

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

add_action( 'updated_post_meta', 'a3_updated_post_meta', 10, 4 );

function a3_updated_post_meta($meta_id, $post_id, $meta_key, $meta_value){
    global $wpdb;
    global $a3_types_to_send;

    a3_write_log('---> u p d a t e d  post  m e t a');

    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

    $mongo_dest_address = 'http://localhost:8080/admin/dirty';
    $reason = 'edit_meta';

    $dirty_post_ids = get_option('a3_dirty_post_ids');

    if(! is_array($dirty_post_ids) ){
        $dirty_post_ids = array();
    }    

    $dirty_post_ids[] = (int) $post_id;

    update_option('a3_dirty_post_ids', array_unique($dirty_post_ids));    

    $object_type = $wpdb->get_var( $wpdb->prepare("select post_type from $wpdb->posts where ID = %d", $post_id) );

    if(in_array($object_type, $a3_types_to_send)){
        a3_send_post_trans($post_id, $reason);  
    }            
}

1 ответ

Решение

В PHP нет простого способа сделать это. Я хотел бы предложить вам изучить другие идеи, такие как:

A) прекратить запускать эти действия и запускать скрипт cron каждые x секунд (простой php-скрипт, который запускается сервером через определенный интервал, который будет обрабатывать сообщения) B) запускать действия аналогично тому, как вы это делаете сейчас, и помещать сообщения в определенный очередь (она может иметь любые формы в зависимости от вашего опыта, от самых простых до, например, RabbitMQ). После этого вам нужно будет создать скрипт queueHandler (аналогично первому пункту), который будет обрабатывать ваши сообщения из очереди.

Вот как я решил это на save_post крючок

    function debounce_send() {
        $send_time = get_transient('send_time');

        if($send_time) {
            wp_clear_scheduled_hook('run_send')
            wp_schedule_single_event($send_time, 'run_send');
            
        } else {
            run_send();
            set_transient('send_time', time() + 60, 60);
        }
    }
    add_action('save_post', 'debounce_send');

Затем я делаю это:

    function run_send() {
        // Send an email here
    }
    add_action( 'run_send', 'run_send' );

В результате он будет отправлять 1 электронное письмо МАКСИМУМ каждые 60 секунд.

Другие вопросы по тегам