Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. RoundRobinTransport.php

class RoundRobinTransport

Uses several Transports using a round robin algorithm.

@author Fabien Potencier <fabien@symfony.com>

Hierarchy

  • class \Symfony\Component\Mailer\Transport\RoundRobinTransport implements \Symfony\Component\Mailer\Transport\TransportInterface

Expanded class hierarchy of RoundRobinTransport

1 file declares its use of RoundRobinTransport
Transport.php in vendor/symfony/mailer/Transport.php

File

vendor/symfony/mailer/Transport/RoundRobinTransport.php, line 25

Namespace

Symfony\Component\Mailer\Transport
View source
class RoundRobinTransport implements TransportInterface {
    
    /**
     * @var \SplObjectStorage<TransportInterface, float>
     */
    private \SplObjectStorage $deadTransports;
    private int $cursor = -1;
    
    /**
     * @param TransportInterface[] $transports
     */
    public function __construct(array $transports, int $retryPeriod = 60) {
        if (!$transports) {
            throw new TransportException(\sprintf('"%s" must have at least one transport configured.', static::class));
        }
        $this->deadTransports = new \SplObjectStorage();
    }
    public function send(RawMessage $message, ?Envelope $envelope = null) : ?SentMessage {
        $exception = null;
        while ($transport = $this->getNextTransport()) {
            try {
                return $transport->send($message, $envelope);
            } catch (TransportExceptionInterface $e) {
                $exception ??= new TransportException('All transports failed.');
                $exception->appendDebug(\sprintf("Transport \"%s\": %s\n", $transport, $e->getDebug()));
                $this->deadTransports[$transport] = microtime(true);
            }
        }
        throw $exception ?? new TransportException('No transports found.');
    }
    public function __toString() : string {
        return $this->getNameSymbol() . '(' . implode(' ', array_map('strval', $this->transports)) . ')';
    }
    
    /**
     * Rotates the transport list around and returns the first instance.
     */
    protected function getNextTransport() : ?TransportInterface {
        if (-1 === $this->cursor) {
            $this->cursor = $this->getInitialCursor();
        }
        $cursor = $this->cursor;
        while (true) {
            $transport = $this->transports[$cursor];
            if (!$this->isTransportDead($transport)) {
                break;
            }
            if (microtime(true) - $this->deadTransports[$transport] > $this->retryPeriod) {
                $this->deadTransports
                    ->detach($transport);
                break;
            }
            if ($this->cursor === ($cursor = $this->moveCursor($cursor))) {
                return null;
            }
        }
        $this->cursor = $this->moveCursor($cursor);
        return $transport;
    }
    protected function isTransportDead(TransportInterface $transport) : bool {
        return $this->deadTransports
            ->contains($transport);
    }
    protected function getInitialCursor() : int {
        // the cursor initial value is randomized so that
        // when are not in a daemon, we are still rotating the transports
        return mt_rand(0, \count($this->transports) - 1);
    }
    protected function getNameSymbol() : string {
        return 'roundrobin';
    }
    private function moveCursor(int $cursor) : int {
        return ++$cursor >= \count($this->transports) ? 0 : $cursor;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
RoundRobinTransport::$cursor private property
RoundRobinTransport::$deadTransports private property
RoundRobinTransport::getInitialCursor protected function 1
RoundRobinTransport::getNameSymbol protected function 1
RoundRobinTransport::getNextTransport protected function Rotates the transport list around and returns the first instance. 1
RoundRobinTransport::isTransportDead protected function
RoundRobinTransport::moveCursor private function
RoundRobinTransport::send public function Overrides TransportInterface::send
RoundRobinTransport::__construct public function
RoundRobinTransport::__toString public function
RSS feed
Powered by Drupal