From 5ec872a469b3656fe447ae50b53c673f4716a1d3 Mon Sep 17 00:00:00 2001
From: Peter Rotich <peter@osticket.com>
Date: Fri, 24 Jan 2014 17:44:41 +0000
Subject: [PATCH] Timeout after max timeout while fetching emails

Processing fetching in ASC order of the last fetch time
Remove LIMIT of 10 emails per fetch
Flush the buffer and terminate the request cleanly on autocron
---
 include/class.mailfetch.php | 23 +++++++++++++++--------
 scp/autocron.php            |  9 +++++++--
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index 3c4306d1e..7149d44d0 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -643,24 +643,31 @@ class MailFetcher {
             .' WHERE mail_active=1 '
             .'  AND (mail_errors<='.$MAXERRORS.' OR (TIME_TO_SEC(TIMEDIFF(NOW(), mail_lasterror))>'.($TIMEOUT*60).') )'
             .'  AND (mail_lastfetch IS NULL OR TIME_TO_SEC(TIMEDIFF(NOW(), mail_lastfetch))>mail_fetchfreq*60)'
-            .' ORDER BY mail_lastfetch DESC'
-            .' LIMIT 10'; //Processing up to 10 emails at a time.
+            .' ORDER BY mail_lastfetch ASC';
 
-       // echo $sql;
-        if(!($res=db_query($sql)) || !db_num_rows($res))
+        if (!($res=db_query($sql)) || !db_num_rows($res))
             return;  /* Failed query (get's logged) or nothing to do... */
 
-        //TODO: Lock the table here??
+        //Get max execution time so we can figure out how long we can fetch
+        // take fetching emails.
+        if (!($max_time = ini_get('max_execution_time')))
+            $max_time = 300;
+
+        //Start time
+        $start_time = Misc::micro_time();
+        while (list($emailId, $errors)=db_fetch_row($res)) {
+            //Break if we're 80% into max execution time
+            if ((Misc::micro_time()-$start_time) > ($max_time*0.80))
+                break;
 
-        while(list($emailId, $errors)=db_fetch_row($res)) {
             $fetcher = new MailFetcher($emailId);
-            if($fetcher->connect()) {
+            if ($fetcher->connect()) {
                 db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=0, mail_lastfetch=NOW() WHERE email_id='.db_input($emailId));
                 $fetcher->fetchEmails();
                 $fetcher->close();
             } else {
                 db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($emailId));
-                if(++$errors>=$MAXERRORS) {
+                if (++$errors>=$MAXERRORS) {
                     //We've reached the MAX consecutive errors...will attempt logins at delayed intervals
                     $msg="\nosTicket is having trouble fetching emails from the following mail account: \n".
                         "\nUser: ".$fetcher->getUsername().
diff --git a/scp/autocron.php b/scp/autocron.php
index 1e2460786..85e3cfbbb 100644
--- a/scp/autocron.php
+++ b/scp/autocron.php
@@ -26,6 +26,12 @@ header('Cache-Control: no-cache, must-revalidate');
 header('Content-Length: '.strlen($data));
 header('Connection: Close');
 print $data;
+// Flush the request buffer
+while(@ob_end_flush());
+flush();
+//Terminate the request
+if (function_exists('fastcgi_finish_request'))
+    fastcgi_finish_request();
 
 ob_start(); //Keep the image output clean. Hide our dirt.
 //TODO: Make cron DB based to allow for better time limits. Direct calls for now sucks big time.
@@ -37,7 +43,7 @@ if($sec>180 && $ost && !$ost->isUpgradePending()): //user can call cron once eve
 require_once(INCLUDE_DIR.'class.cron.php');
 
 $thisstaff = null; //Clear staff obj to avoid false credit internal notes & auto-assignment
-Cron::TicketMonitor(); //Age tickets: We're going to age tickets regardless of cron settings. 
+Cron::TicketMonitor(); //Age tickets: We're going to age tickets regardless of cron settings.
 if($cfg && $cfg->isAutoCronEnabled()) { //ONLY fetch tickets if autocron is enabled!
     Cron::MailFetcher();  //Fetch mail.
     $ost->logDebug('Auto Cron', 'Mail fetcher cron call ['.$caller.']');
@@ -45,6 +51,5 @@ if($cfg && $cfg->isAutoCronEnabled()) { //ONLY fetch tickets if autocron is enab
 
 $_SESSION['lastcroncall']=time();
 endif;
-$output = ob_get_contents();
 ob_end_clean();
 ?>
-- 
GitLab