LoadBalancedTransport.php 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * Redudantly and rotationally uses several Transports when sending.
  11. *
  12. * @package Swift
  13. * @subpackage Transport
  14. * @author Chris Corbyn
  15. */
  16. class Swift_Transport_LoadBalancedTransport implements Swift_Transport
  17. {
  18. /** Transports which are deemed useless */
  19. private $_deadTransports = array();
  20. /**
  21. * The Transports which are used in rotation.
  22. *
  23. * @var array Swift_Transport
  24. * @access protected
  25. */
  26. protected $_transports = array();
  27. /**
  28. * Creates a new LoadBalancedTransport.
  29. */
  30. public function __construct()
  31. {
  32. }
  33. /**
  34. * Set $transports to delegate to.
  35. *
  36. * @param array $transports Swift_Transport
  37. */
  38. public function setTransports(array $transports)
  39. {
  40. $this->_transports = $transports;
  41. $this->_deadTransports = array();
  42. }
  43. /**
  44. * Get $transports to delegate to.
  45. *
  46. * @return array Swift_Transport
  47. */
  48. public function getTransports()
  49. {
  50. return array_merge($this->_transports, $this->_deadTransports);
  51. }
  52. /**
  53. * Test if this Transport mechanism has started.
  54. *
  55. * @return boolean
  56. */
  57. public function isStarted()
  58. {
  59. return count($this->_transports) > 0;
  60. }
  61. /**
  62. * Start this Transport mechanism.
  63. */
  64. public function start()
  65. {
  66. $this->_transports = array_merge($this->_transports, $this->_deadTransports);
  67. }
  68. /**
  69. * Stop this Transport mechanism.
  70. */
  71. public function stop()
  72. {
  73. foreach ($this->_transports as $transport)
  74. {
  75. $transport->stop();
  76. }
  77. }
  78. /**
  79. * Send the given Message.
  80. *
  81. * Recipient/sender data will be retrieved from the Message API.
  82. * The return value is the number of recipients who were accepted for delivery.
  83. *
  84. * @param Swift_Mime_Message $message
  85. * @param string[] &$failedRecipients to collect failures by-reference
  86. * @return int
  87. */
  88. public function send(Swift_Mime_Message $message, &$failedRecipients = null)
  89. {
  90. $maxTransports = count($this->_transports);
  91. $sent = 0;
  92. for ($i = 0; $i < $maxTransports
  93. && $transport = $this->_getNextTransport(); ++$i)
  94. {
  95. try
  96. {
  97. if (!$transport->isStarted())
  98. {
  99. $transport->start();
  100. }
  101. if ($sent = $transport->send($message, $failedRecipients))
  102. {
  103. break;
  104. }
  105. }
  106. catch (Swift_TransportException $e)
  107. {
  108. $this->_killCurrentTransport();
  109. }
  110. }
  111. if (count($this->_transports) == 0)
  112. {
  113. throw new Swift_TransportException(
  114. 'All Transports in LoadBalancedTransport failed, or no Transports available'
  115. );
  116. }
  117. return $sent;
  118. }
  119. /**
  120. * Register a plugin.
  121. *
  122. * @param Swift_Events_EventListener $plugin
  123. */
  124. public function registerPlugin(Swift_Events_EventListener $plugin)
  125. {
  126. foreach ($this->_transports as $transport)
  127. {
  128. $transport->registerPlugin($plugin);
  129. }
  130. }
  131. // -- Protected methods
  132. /**
  133. * Rotates the transport list around and returns the first instance.
  134. *
  135. * @return Swift_Transport
  136. * @access protected
  137. */
  138. protected function _getNextTransport()
  139. {
  140. if ($next = array_shift($this->_transports))
  141. {
  142. $this->_transports[] = $next;
  143. }
  144. return $next;
  145. }
  146. /**
  147. * Tag the currently used (top of stack) transport as dead/useless.
  148. *
  149. * @access protected
  150. */
  151. protected function _killCurrentTransport()
  152. {
  153. if ($transport = array_pop($this->_transports))
  154. {
  155. try
  156. {
  157. $transport->stop();
  158. }
  159. catch (Exception $e)
  160. {
  161. }
  162. $this->_deadTransports[] = $transport;
  163. }
  164. }
  165. }