/
githubmirror
/
ydb-php-sdk
Обзор
Документация
Войти
/
githubmirror
/
ydb-php-sdk
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v1.8.1
src/Retry/Retry.php
146 строк
5 KB
Илья
Fixed bug, when function Retry::backoffType always return SlowBackoff
17 июл 2023, 15:54
17 июл 2023, 15:54
d4ee6b9
Код
Авторство
О чём код?
<?php namespace YdbPlatform\Ydb\Retry; use Closure; use YdbPlatform\Ydb\Exception; use YdbPlatform\Ydb\Exceptions\RetryableException; use Psr\Log\LoggerInterface; class Retry { protected $timeoutMs; protected $slowBackOff; protected $fastBackOff; protected $noBackOff; /** * @var LoggerInterface */ protected $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; $this->timeoutMs = 2000; $this->fastBackOff = new Backoff(6, 5); $this->slowBackOff = new Backoff(6, 1000); $this->noBackOff = new Backoff(0, 0); } protected function retryDelay(int $retryCount, Backoff $backoff) { return $backoff->getBackoffSlotMillis() * (1 << min($retryCount, $backoff->getBackoffCeiling())); } /** * @param int $timeoutMs */ protected function setTimeoutMs(int $timeoutMs): void { $this->timeoutMs = $timeoutMs; } /** * @param Backoff $slowBackOff */ protected function setSlowBackOff(Backoff $slowBackOff): void { $this->slowBackOff = $slowBackOff; } /** * @param Backoff $fastBackOff */ protected function setFastBackOff(Backoff $fastBackOff): void { $this->fastBackOff = $fastBackOff; } public function withParams(?RetryParams $params): Retry { if (is_null($params)) return $this; $retry = clone $this; if ($params->getTimeoutMs()) $retry->setTimeoutMs($params->getTimeoutMs()); if ($params->getFastBackOff()) $retry->setFastBackOff($params->getFastBackOff()); if ($params->getSlowBackOff()) $retry->setSlowBackOff($params->getSlowBackOff()); return $retry; } /** * @throws Exception */ public function retry(Closure $closure, bool $idempotent) { $startTime = microtime(true); $retryCount = 0; $lastException = null; while (microtime(true) < $startTime + $this->timeoutMs / 1000) { $this->logger->debug("YDB: Run user function. Retry count: $retryCount. s: ".(microtime(true) - $startTime)); try { return $closure(); } catch (Exception $e) { $this->logger->warning("YDB: Received exception: ".$e->getMessage()); if (!$this->canRetry($e, $idempotent)){ $lastException = $e; break; } $retryCount++; $lastException = $e; $delay = $this->retryDelay($retryCount, $this->backoffType(get_class($e)))*1000; usleep($delay); } } throw $lastException; } /** * @param string $e * @return Backoff */ protected function backoffType(string $e): Backoff { return in_array($e, self::$immediatelyBackoff) ? $this->noBackOff : (in_array($e, self::$fastBackoff) ? $this->fastBackOff : $this->slowBackOff); } protected function alwaysRetry(string $exception) { return in_array($exception, self::$alwaysRetry); } protected function canRetry(Exception $e, bool $idempotent) { return is_a($e, RetryableException::class) && ($this->alwaysRetry(get_class($e)) || $idempotent); } private static $immediatelyBackoff = [ \YdbPlatform\Ydb\Exceptions\Grpc\AbortedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\BadSessionException::class, ]; private static $fastBackoff = [ \YdbPlatform\Ydb\Exceptions\Grpc\CanceledException::class, \YdbPlatform\Ydb\Exceptions\Grpc\DeadlineExceededException::class, \YdbPlatform\Ydb\Exceptions\Grpc\InternalException::class, \YdbPlatform\Ydb\Exceptions\Grpc\UnavailableException::class, \YdbPlatform\Ydb\Exceptions\Ydb\AbortedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\UnavailableException::class, \YdbPlatform\Ydb\Exceptions\Ydb\CancelledException::class, \YdbPlatform\Ydb\Exceptions\Ydb\UndeterminedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\SessionBusyException::class, ]; private static $alwaysRetry = [ \YdbPlatform\Ydb\Exceptions\Grpc\ResourceExhaustedException::class, \YdbPlatform\Ydb\Exceptions\Grpc\AbortedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\AbortedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\UnavailableException::class, \YdbPlatform\Ydb\Exceptions\Ydb\OverloadedException::class, \YdbPlatform\Ydb\Exceptions\Ydb\BadSessionException::class, \YdbPlatform\Ydb\Exceptions\Ydb\SessionBusyException::class, ]; }