Жалобы на почтовые рассылки подписанных материалов поступают уже часто, меня это слегка достало и я полез смотреть что там происходит. Очередное включение модуля subscriptions_mail привело к тому, что сайт начал развозить по всем адресам рассылки наверно с 1900 года Ещё раз мои извинения перед пользователями, которые обнаружили в почтовом ящике не очень свежие новости с drupal.ru.
Детальное изучение показало, что в таблице subscription_queue набралось уже 6.5 млн. записей - если правильно понял архитектуру модуля, это общий список, по которому регулярно идёт рассылка. Причём выборка записей для рассылки осуществляется имхо не очень удачно:
<?php
/**
* Implementation of hook_cron().
*
* Takes items from {subscriptions_queue} and generates notification emails.
*/
function subscriptions_mail_cron() {
// тут кусок пропущен
while (($mails_allowed <= 0 || $single_count + count($mails) < $mails_allowed)
&& $total_seconds - timer_read('page')/1000 > $available_seconds*variable_get('subscriptions_cron_percent', 50)/100) {
$result = db_query_range('SELECT * FROM {subscriptions_queue} WHERE last_sent + send_interval < %d ORDER BY sqid', time(), 0, 1);
if (!($s = db_fetch_array($result))) {
break; // No more subscriptions, terminate loop.
}
?>
Т.е. из этой огромной таблицы мы пробегаем число раз заданное в настройках модуля (переменная $mails_allowed) за каждый запуск крона. Один такой запрос исполняется на нашем vps ~30 сек. Т.е. минимум 30 с. получаем на отправку одного письма (3.6 млн. писем значит разошлются примерно за 3.5 года). В общем понятно тогда, почему кому-то приходят письма многомесячной давности, кому ничего.
Обновил таблицу, чтобы не было старых подписок - last_sent был везде проставлен в текущее время.
+------------------+
| unix_timestamp() |
+------------------+
| 1245145244 |
+------------------+
1 ROW IN SET (0.01 sec)
mysql> UPDATE dru_subscriptions_queue SET last_sent = 1245145244;
Query OK, 6519502 ROWS affected (2 MIN 37.17 sec)
ROWS matched: 6519502 Changed: 6519502 Warnings: 0
Но сразу после этого выборка даёт:
+----------+
| COUNT(*) |
+----------+
| 3639864 |
+----------+
1 ROW IN SET (31.13 sec)
Так что помогло не сильно, т.к. send_interval у половины записей стоит 1 - "рассылка сразу при обновлении материала". По 3.6 млн. записей оно будет ходить тоже не один год.
Как вариант - сбросить все настройки подписок drupal.ru и начать заново. Только нет гарантий, что за пару лет не наберётся тоже самое. Либо с этой гигантской очередью какой-то глюк и она не должна была получиться таких размеров? Модуль стоит давно и не раз уже обновлялся, мейби что-то покосячилось в один из апгрейдов? Собственно с учётом не такого уж большого количества нодов на drupal.ru и терминов выходит слишком подозрительно много, но на первый взгляд выборка таблицы выглядит ок. В общем, жду советов от тех кто ковырялся в модуле и разбирался детально с его работой. Пока отрубил его обратно, пока в спамеры не записали.
UPD Ага, кажется начинаю понимать. Если юзер подписался на чей-то блог, в queue прописываются записи для каждой ноды этого блога что-ли?