? simplenews-361071-11.patch Index: simplenews.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/simplenews/simplenews.install,v retrieving revision 1.8.2.33 diff -u -p -r1.8.2.33 simplenews.install --- simplenews.install 21 May 2010 15:37:41 -0000 1.8.2.33 +++ simplenews.install 8 Aug 2010 19:49:36 -0000 @@ -180,6 +180,20 @@ function simplenews_schema() { 'not null' => TRUE, 'default' => 0, ), + 'pid' => array( + 'description' => 'ID of the PHP process handling the batch', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'begin_send_timestamp' => array( + 'description' => 'Time the batch began processing', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), ), 'primary key' => array('msid'), 'indexes' => array('tid' => array('tid'), 'status' => array('status')), @@ -635,3 +649,15 @@ function simplenews_update_6011() { )); return $ret; } + +/** + * Add some fields to track which PHP process is handling a batch of messages + */ +function simplenews_update_6201() { + $ret = array(); + db_add_field($ret, 'simplenews_mail_spool', 'pid', + array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'ID of the PHP process handling the batch')); + db_add_field($ret, 'simplenews_mail_spool', 'begin_send_timestamp', + array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Time the batch began processing')); + return $ret; +} Index: simplenews.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/simplenews/simplenews.module,v retrieving revision 1.76.2.156 diff -u -p -r1.76.2.156 simplenews.module --- simplenews.module 19 May 2010 14:01:22 -0000 1.76.2.156 +++ simplenews.module 8 Aug 2010 19:49:36 -0000 @@ -1867,7 +1867,23 @@ function simplenews_save_spool($message) function simplenews_get_spool($status, $nid = NULL, $vid = NULL, $limit = 999999) { $messages = array(); - $result = db_query_range("SELECT * FROM {simplenews_mail_spool} s WHERE s.status = %d ORDER BY s.timestamp ASC", $status, 0, $limit); + /** + * Choose the messages that will be sent by this process + * This query will mark pending messages as belonging to this PHP process ID, and includes the current timestamp + * as the begin time. This way, no other processes will try to send the same messages, which could result in + * duplicates messages sent (this was a problem with poormanscron). + * The query will also claim any messages that had already been claimed by another process, but were started over + * an hour ago. This way, if a process fails before completing its batch, another process will take care of it later. + */ + $pid = getmypid(); + $now = time(); + $an_hour_ago = $now - (60 * 60); + $sql = "UPDATE {simplenews_mail_spool} SET pid=%d, begin_send_timestamp=%d + WHERE status = %d AND (pid = 0 OR begin_send_timestamp < %d) LIMIT %d"; + $ret = db_query($sql, array($pid, $now, $status, $an_hour_ago, $limit)); + + // Get the messages that were claimed for this process + $result = db_query("SELECT * FROM {simplenews_mail_spool} s WHERE s.pid = %d ORDER BY s.timestamp ASC", array($pid)); while ($data = db_fetch_array($result)) { $message = array(); foreach ($data as $key => $value) {