exec — php вызывает метод класса асинхронно

Мне нужно вызвать метод PHP в цикле асинхронно.

Вот что я попробовал:

foreach ($batch_ids as $batch_id) {
$this->launchBackgroundProcess( $this->sendBatchMail($batch_id) );
}

public function launchBackgroundProcess($call) {

// pclose( popen( $call.'/dev/null &', 'r'));
Proc_close( Proc_open( $call.' > /dev/null & ', 'r'));
return true;
}

Теперь ошибка в том, что моя функция sendBatchMail вызывается напрямую, а launchBackgroundProcess никогда не вызывается (используется для проверки echo / print / log).

Таким образом, если в идентификаторе пакета есть 10 тысяч писем, endBatchcMail для следующего идентификатора пакета никогда не запускается.

Я хочу вызывать sendBatchMail одновременно и асинхронно в фоновом режиме для всех полученных идентификаторов пакетов.

Я не очень хорошо разбираюсь в pthreads … и, похоже, моя последняя остановка.

0

Решение

Это не совсем так. Каждый процесс PHP запускается и сносится для каждого отдельного запроса. Вы не должны пытаться напрямую запускать что-либо непосредственно из PHP-скрипта, отвечающего на HTTP-запрос. Его единственная работа должна состоять в том, чтобы вернуть ответ HTTP как можно скорее, а затем положить трубку. Любые большие объемы работы должны быть поставлены в очередь для обработки более настойчивым бэкэндом позже.

Что напрямую подводит меня к очереди сообщений и рабочие. смотреть на Gearman для довольно простой такой системы, хотя существует множество других возможностей, включая ØMQ, Redis и другие. Вы просто помещаете несколько сообщений в эту очередь, которые затем обрабатываются одним или несколькими сценариями PHP, работающими как задание cron или постоянные рабочие демоны в фоновом режиме, полностью отделенные от внешних обработчиков HTTP.

1

Другие решения

Один из способов сделать это — создать скрипт php с кодом отправки и выполнить:

shell_exec("theBackgroundScript.php >/dev/null &");

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

Вместо этого рассмотрите возможность создания таблицы в вашей базе данных для хранения всех почтовых заданий. Это может быть как:

CREATE TABLE email_jobs (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
executed TINYINT DEFAULT 0,
destination VARCHAR(255) NOT NULL,
subject VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME DEFAULT NULL);

Затем вам просто нужно добавить детали каждой работы, когда вам это нужно:

$db->query("INSERT INTO email_jobs (destination, subject, content, created_at) VALUES ('someperson@example.com', 'some subject', 'some email content', NOW())");

Затем вам понадобится PHP-скрипт, который будет запрашивать базу данных о еще не выполненных заданиях:

$row = $db->query("SELECT * FORM email_jobs WHERE executed = 0 LIMIT 1");
// ... send email described in $row

Сценарий получает первое не выполненное задание (или первое N не выполненных заданий) и отправляет его.
Тогда вам просто нужно поместить скрипт в хрон и пусть он отправит все письма.

Если произойдет сбой, его очень легко отправить снова, просто установите выполненное в ноль, и оно будет доставлено.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector