Index: simplenews.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/simplenews/simplenews.install,v retrieving revision 1.8.2.34 diff -u -p -r1.8.2.34 simplenews.install --- simplenews.install 20 Aug 2010 14:44:37 -0000 1.8.2.34 +++ simplenews.install 8 Sep 2010 20:41:00 -0000 @@ -180,6 +180,20 @@ function simplenews_schema() { 'not null' => TRUE, 'default' => 0, ), + 'sid' => array( + 'description' => 'ID from the PHP process handling the batch', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + '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')), @@ -628,3 +642,15 @@ function simplenews_update_6201() { )); return $ret; } + +/** + * Add some fields to track which PHP process is handling a batch of messages + */ +function simplenews_update_6202() { + $ret = array(); + db_add_field($ret, 'simplenews_mail_spool', 'sid', + array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', 'description' => 'ID from 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.157 diff -u -p -r1.76.2.157 simplenews.module --- simplenews.module 7 Sep 2010 02:10:14 -0000 1.76.2.157 +++ simplenews.module 8 Sep 2010 20:41:05 -0000 @@ -1868,7 +1868,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 process, 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. + */ + $sid = rand(); /* Random number to identify this process */ + $now = time(); + $an_hour_ago = $now - (60 * 60); + $sql = "UPDATE {simplenews_mail_spool} SET sid='%s', begin_send_timestamp=%d + WHERE status = %d AND ((sid IS NULL OR sid = '') OR begin_send_timestamp < %d) LIMIT %d"; + $ret = db_query($sql, array($sid, $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.sid = '%s' ORDER BY s.timestamp ASC", array($sid)); while ($data = db_fetch_array($result)) { $message = array(); foreach ($data as $key => $value) { @@ -1913,6 +1929,18 @@ function simplenews_count_spool($nid, $v } /** + * Count all data in mail spool table that has not been claimed by a send process + * + * @param string $status email sent status + * + * @return array Mail message array + */ +function simplenews_count_unclaimed_spool($status = SIMPLENEWS_SPOOL_PENDING) { + $an_hour_ago = time() - (60 * 60); + return db_result(db_query("SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE status = %d AND ((sid IS NULL OR sid = '') OR begin_send_timestamp < %d)", $status, $an_hour_ago)); +} + +/** * Remove records from mail spool table. * * All records with status 'send' and time stamp before the expiration date