asynctask.class.inc.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. // Copyright (C) 2010-2012 Combodo SARL
  3. //
  4. // This file is part of iTop.
  5. //
  6. // iTop is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // iTop is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with iTop. If not, see <http://www.gnu.org/licenses/>
  18. /**
  19. * Persistent classes (internal): user defined actions
  20. *
  21. * @copyright Copyright (C) 2010-2012 Combodo SARL
  22. * @license http://opensource.org/licenses/AGPL-3.0
  23. */
  24. class ExecAsyncTask implements iBackgroundProcess
  25. {
  26. public function GetPeriodicity()
  27. {
  28. return 2; // seconds
  29. }
  30. public function Process($iTimeLimit)
  31. {
  32. $sNow = date('Y-m-d H:i:s');
  33. $sOQL = "SELECT AsyncTask WHERE ISNULL(started) AND (ISNULL(planned) OR (planned < '$sNow'))";
  34. $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array());
  35. $iProcessed = 0;
  36. while ((time() < $iTimeLimit) && ($oTask = $oSet->Fetch()))
  37. {
  38. $oTask->Set('started', time());
  39. $oTask->DBUpdate();
  40. try
  41. {
  42. $oTask->Process();
  43. $iProcessed++;
  44. $oTask->DBDelete();
  45. }
  46. catch(Exception $e)
  47. {
  48. $iRemaining = $oTask->Get('remaining_retries');
  49. if ($iRemaining > 0)
  50. {
  51. $aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
  52. if (is_array($aRetries) && array_key_exists(get_class($oTask), $aRetries))
  53. {
  54. $aConfig = $aRetries[get_class($oTask)];
  55. $iRetryDelay = $aConfig['retry_delay'];
  56. }
  57. else
  58. {
  59. $iRetryDelay = 600;
  60. }
  61. IssueLog::Info('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage().' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
  62. $oTask->Set('remaining_retries', $iRemaining - 1);
  63. $oTask->Set('started', null);
  64. $oTask->Set('planned', time() + $iRetryDelay);
  65. $oTask->DBUpdate();
  66. }
  67. else
  68. {
  69. IssueLog::Error('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage());
  70. }
  71. }
  72. }
  73. if ($iProcessed == $oSet->Count())
  74. {
  75. return "processed $iProcessed tasks";
  76. }
  77. else
  78. {
  79. return "processed $iProcessed tasks (remaining: ".($oSet->Count() - $iProcessed).")";
  80. }
  81. }
  82. }
  83. /**
  84. * A
  85. *
  86. * @package iTopORM
  87. */
  88. abstract class AsyncTask extends DBObject
  89. {
  90. public static function Init()
  91. {
  92. $aParams = array
  93. (
  94. "category" => "core/cmdb",
  95. "key_type" => "autoincrement",
  96. "name_attcode" => array('created'),
  97. "state_attcode" => "",
  98. "reconc_keys" => array(),
  99. "db_table" => "priv_async_task",
  100. "db_key_field" => "id",
  101. "db_finalclass_field" => "realclass",
  102. "display_template" => "",
  103. );
  104. MetaModel::Init_Params($aParams);
  105. //MetaModel::Init_InheritAttributes();
  106. // MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  107. MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
  108. MetaModel::Init_AddAttribute(new AttributeDateTime("started", array("allowed_values"=>null, "sql"=>"started", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
  109. // planned... still not used - reserved for timer management
  110. MetaModel::Init_AddAttribute(new AttributeDateTime("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
  111. 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())));
  112. MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", array("allowed_values"=>null, "sql"=>"remaining_retries", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
  113. // Display lists
  114. // MetaModel::Init_SetZListItems('details', array()); // Attributes to be displayed for the complete details
  115. // MetaModel::Init_SetZListItems('list', array()); // Attributes to be displayed for a list
  116. // Search criteria
  117. // MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
  118. // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
  119. }
  120. protected function OnInsert()
  121. {
  122. $this->Set('created', time());
  123. $aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
  124. if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
  125. {
  126. $aConfig = $aRetries[get_class($this)];
  127. $iRetries = $aConfig['max_retries'];
  128. $this->Set('remaining_retries', $iRetries);
  129. }
  130. }
  131. public function Process()
  132. {
  133. $sStatus = $this->DoProcess();
  134. if ($this->Get('event_id') != 0)
  135. {
  136. $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
  137. $oEventLog->Set('message', $sStatus);
  138. $oEventLog->DBUpdate();
  139. }
  140. }
  141. abstract public function DoProcess();
  142. }
  143. /**
  144. * An email notification
  145. *
  146. * @package iTopORM
  147. */
  148. class AsyncSendEmail extends AsyncTask
  149. {
  150. public static function Init()
  151. {
  152. $aParams = array
  153. (
  154. "category" => "core/cmdb",
  155. "key_type" => "autoincrement",
  156. "name_attcode" => "created",
  157. "state_attcode" => "",
  158. "reconc_keys" => array(),
  159. "db_table" => "priv_async_send_email",
  160. "db_key_field" => "id",
  161. "db_finalclass_field" => "",
  162. "display_template" => "",
  163. );
  164. MetaModel::Init_Params($aParams);
  165. MetaModel::Init_InheritAttributes();
  166. MetaModel::Init_AddAttribute(new AttributeInteger("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>Email::ORIGINAL_FORMAT, "is_null_allowed"=>false, "depends_on"=>array())));
  167. MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
  168. MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  169. MetaModel::Init_AddAttribute(new AttributeLongText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
  170. // Display lists
  171. // MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list')); // Attributes to be displayed for the complete details
  172. // MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject')); // Attributes to be displayed for a list
  173. // Search criteria
  174. // MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
  175. // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
  176. }
  177. static public function AddToQueue(EMail $oEMail, $oLog)
  178. {
  179. $oNew = MetaModel::NewObject(__class__);
  180. if ($oLog)
  181. {
  182. $oNew->Set('event_id', $oLog->GetKey());
  183. }
  184. $oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
  185. $oNew->Set('subject', $oEMail->GetSubject());
  186. // $oNew->Set('version', 1);
  187. // $sMessage = serialize($oEMail);
  188. $oNew->Set('version', 2);
  189. $sMessage = $oEMail->SerializeV2();
  190. $oNew->Set('message', $sMessage);
  191. $oNew->DBInsert();
  192. }
  193. public function DoProcess()
  194. {
  195. $sMessage = $this->Get('message');
  196. $iVersion = (int) $this->Get('version');
  197. switch($iVersion)
  198. {
  199. case Email::FORMAT_V2:
  200. $oEMail = Email::UnSerializeV2($sMessage);
  201. break;
  202. case Email::ORIGINAL_FORMAT:
  203. $oEMail = unserialize($sMessage);
  204. break;
  205. default:
  206. return 'Unknown version of the serialization format: '.$iVersion;
  207. }
  208. $iRes = $oEMail->Send($aIssues, true /* force synchro !!!!! */);
  209. switch ($iRes)
  210. {
  211. case EMAIL_SEND_OK:
  212. return "Sent";
  213. case EMAIL_SEND_PENDING:
  214. return "Bug - the email should be sent in synchronous mode";
  215. case EMAIL_SEND_ERROR:
  216. return "Failed: ".implode(', ', $aIssues);
  217. }
  218. }
  219. }
  220. ?>