Мне нужно вызвать метод 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 … и, похоже, моя последняя остановка.
Это не совсем так. Каждый процесс PHP запускается и сносится для каждого отдельного запроса. Вы не должны пытаться напрямую запускать что-либо непосредственно из PHP-скрипта, отвечающего на HTTP-запрос. Его единственная работа должна состоять в том, чтобы вернуть ответ HTTP как можно скорее, а затем положить трубку. Любые большие объемы работы должны быть поставлены в очередь для обработки более настойчивым бэкэндом позже.
Что напрямую подводит меня к очереди сообщений и рабочие. смотреть на Gearman для довольно простой такой системы, хотя существует множество других возможностей, включая ØMQ, Redis и другие. Вы просто помещаете несколько сообщений в эту очередь, которые затем обрабатываются одним или несколькими сценариями PHP, работающими как задание cron или постоянные рабочие демоны в фоновом режиме, полностью отделенные от внешних обработчиков HTTP.
Один из способов сделать это — создать скрипт 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 ('[email protected]', '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 не выполненных заданий) и отправляет его.
Тогда вам просто нужно поместить скрипт в хрон и пусть он отправит все письма.
Если произойдет сбой, его очень легко отправить снова, просто установите выполненное в ноль, и оно будет доставлено.