LoadBalancedTransport.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. * Redundantly and rotationally uses several Transports when sending.
  11. *
  12. * @author Chris Corbyn
  13. */
  14. class Swift_Transport_LoadBalancedTransport implements Swift_Transport
  15. {
  16. /**
  17. * Transports which are deemed useless.
  18. *
  19. * @var Swift_Transport[]
  20. */
  21. private $_deadTransports = array();
  22. /**
  23. * The Transports which are used in rotation.
  24. *
  25. * @var Swift_Transport[]
  26. */
  27. protected $_transports = array();
  28. /**
  29. * Creates a new LoadBalancedTransport.
  30. */
  31. public function __construct()
  32. {
  33. }
  34. /**
  35. * Set $transports to delegate to.
  36. *
  37. * @param Swift_Transport[] $transports
  38. */
  39. public function setTransports(array $transports)
  40. {
  41. $this->_transports = $transports;
  42. $this->_deadTransports = array();
  43. }
  44. /**
  45. * Get $transports to delegate to.
  46. *
  47. * @return Swift_Transport[]
  48. */
  49. public function getTransports()
  50. {
  51. return array_merge($this->_transports, $this->_deadTransports);
  52. }
  53. /**
  54. * Test if this Transport mechanism has started.
  55. *
  56. * @return bool
  57. */
  58. public function isStarted()
  59. {
  60. return count($this->_transports) > 0;
  61. }
  62. /**
  63. * Start this Transport mechanism.
  64. */
  65. public function start()
  66. {
  67. $this->_transports = array_merge($this->_transports, $this->_deadTransports);
  68. }
  69. /**
  70. * Stop this Transport mechanism.
  71. */
  72. public function stop()
  73. {
  74. foreach ($this->_transports as $transport) {
  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 An array of failures by-reference
  86. *
  87. * @return int
  88. */
  89. public function send(Swift_Mime_Message $message, &$failedRecipients = null)
  90. {
  91. $maxTransports = count($this->_transports);
  92. $sent = 0;
  93. for ($i = 0; $i < $maxTransports
  94. && $transport = $this->_getNextTransport(); ++$i)
  95. {
  96. try {
  97. if (!$transport->isStarted()) {
  98. $transport->start();
  99. }
  100. if ($sent = $transport->send($message, $failedRecipients)) {
  101. break;
  102. }
  103. } catch (Swift_TransportException $e) {
  104. $this->_killCurrentTransport();
  105. }
  106. }
  107. if (count($this->_transports) == 0) {
  108. throw new Swift_TransportException(
  109. 'All Transports in LoadBalancedTransport failed, or no Transports available'
  110. );
  111. }
  112. return $sent;
  113. }
  114. /**
  115. * Register a plugin.
  116. *
  117. * @param Swift_Events_EventListener $plugin
  118. */
  119. public function registerPlugin(Swift_Events_EventListener $plugin)
  120. {
  121. foreach ($this->_transports as $transport) {
  122. $transport->registerPlugin($plugin);
  123. }
  124. }
  125. /**
  126. * Rotates the transport list around and returns the first instance.
  127. *
  128. * @return Swift_Transport
  129. */
  130. protected function _getNextTransport()
  131. {
  132. if ($next = array_shift($this->_transports)) {
  133. $this->_transports[] = $next;
  134. }
  135. return $next;
  136. }
  137. /**
  138. * Tag the currently used (top of stack) transport as dead/useless.
  139. */
  140. protected function _killCurrentTransport()
  141. {
  142. if ($transport = array_pop($this->_transports)) {
  143. try {
  144. $transport->stop();
  145. } catch (Exception $e) {
  146. }
  147. $this->_deadTransports[] = $transport;
  148. }
  149. }
  150. }