mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Asynchronous emails: added a retry mechanism useful in case your SMTP server restricts the number of emails that can be sent over a period of time (usage: broadcasting a newsletter). The mechanism is not specific to sending email as it is implemented at the AsyncTask level.
SVN:trunk[3047]
This commit is contained in:
@@ -34,7 +34,8 @@ class ExecAsyncTask implements iBackgroundProcess
|
||||
|
||||
public function Process($iTimeLimit)
|
||||
{
|
||||
$sOQL = "SELECT AsyncTask WHERE ISNULL(started) AND (ISNULL(planned) OR (planned < NOW()))";
|
||||
$sNow = date('Y-m-d H:i:s');
|
||||
$sOQL = "SELECT AsyncTask WHERE ISNULL(started) AND (ISNULL(planned) OR (planned < '$sNow'))";
|
||||
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array());
|
||||
$iProcessed = 0;
|
||||
while ((time() < $iTimeLimit) && ($oTask = $oSet->Fetch()))
|
||||
@@ -42,10 +43,40 @@ class ExecAsyncTask implements iBackgroundProcess
|
||||
$oTask->Set('started', time());
|
||||
$oTask->DBUpdate();
|
||||
|
||||
$oTask->Process();
|
||||
$iProcessed++;
|
||||
try
|
||||
{
|
||||
$oTask->Process();
|
||||
$iProcessed++;
|
||||
|
||||
$oTask->DBDelete();
|
||||
$oTask->DBDelete();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$iRemaining = $oTask->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
if (is_array($aRetries) && array_key_exists(get_class($oTask), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($oTask)];
|
||||
$iRetryDelay = $aConfig['retry_delay'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$iRetryDelay = 600;
|
||||
}
|
||||
IssueLog::Info('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage().' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$oTask->Set('remaining_retries', $iRemaining - 1);
|
||||
$oTask->Set('started', null);
|
||||
$oTask->Set('planned', time() + $iRetryDelay);
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($iProcessed == $oSet->Count())
|
||||
{
|
||||
@@ -88,6 +119,8 @@ abstract class AsyncTask extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", array("targetclass"=>"Event", "jointype"=> "", "allowed_values"=>null, "sql"=>"event_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", array("allowed_values"=>null, "sql"=>"remaining_retries", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
// MetaModel::Init_SetZListItems('details', array()); // Attributes to be displayed for the complete details
|
||||
// MetaModel::Init_SetZListItems('list', array()); // Attributes to be displayed for a list
|
||||
@@ -99,6 +132,14 @@ abstract class AsyncTask extends DBObject
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->Set('created', time());
|
||||
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($this)];
|
||||
$iRetries = $aConfig['max_retries'];
|
||||
$this->Set('remaining_retries', $iRetries);
|
||||
}
|
||||
}
|
||||
|
||||
public function Process()
|
||||
|
||||
@@ -332,6 +332,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'async_task_retries' => array(
|
||||
'type' => 'array',
|
||||
'description' => 'Automatic retries of asynchronous tasks in case of failure (per class)',
|
||||
'default' => array('AsyncSendEmail' => array('max_retries' => 0, 'retry_delay' => 600)),
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'email_asynchronous' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'If set, the emails are sent off line, which requires cron.php to be activated. Exception: some features like the email test utility will force the serialized mode',
|
||||
@@ -712,6 +720,8 @@ class Config
|
||||
case 'float':
|
||||
$value = (float) $value;
|
||||
break;
|
||||
case 'array':
|
||||
break;
|
||||
default:
|
||||
throw new CoreException('Unknown type for setting', array('property' => $sPropCode, 'type' => $sType));
|
||||
}
|
||||
@@ -968,7 +978,14 @@ class Config
|
||||
{
|
||||
if ($this->IsProperty($sPropCode))
|
||||
{
|
||||
$value = trim($rawvalue);
|
||||
if (is_string($rawvalue))
|
||||
{
|
||||
$value = trim($rawvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $rawvalue;
|
||||
}
|
||||
$this->Set($sPropCode, $value, $sConfigFile);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user