scheduleCheck(); } public function nextConnection(bool $force = false): ConnectionInterface { $skipped = []; $total = count($this->connections); while ($total--) { /** * @var Connection $connection */ $connection = $this->selector->select($this->connections); if ($connection->isAlive() === true) { return $connection; } if ($this->readyToRevive($connection) === true) { if ($connection->ping() === true) { return $connection; } } else { $skipped[] = $connection; } } // All "alive" nodes failed, force pings on "dead" nodes foreach ($skipped as $connection) { if ($connection->ping() === true) { return $connection; } } throw new NoNodesAvailableException("No alive nodes found in your cluster"); } public function scheduleCheck(): void { foreach ($this->connections as $connection) { $connection->markDead(); } } private function readyToRevive(Connection $connection): bool { $timeout = min( $this->pingTimeout * pow(2, $connection->getPingFailures()), $this->maxPingTimeout ); if ($connection->getLastPing() + $timeout < time()) { return true; } else { return false; } } }