src/Core/Framework/DataAbstractionLayer/Doctrine/RetryableQuery.php line 32

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\DataAbstractionLayer\Doctrine;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\Exception\RetryableException;
  5. use Doctrine\DBAL\Statement;
  6. use Shopware\Core\Framework\Log\Package;
  7. #[Package('core')]
  8. class RetryableQuery
  9. {
  10.     public function __construct(private readonly ?Connection $connection, private readonly Statement $query)
  11.     {
  12.     }
  13.     public function execute(array $params = []): int
  14.     {
  15.         return self::retry($this->connection, fn () => $this->query->executeStatement($params), 0);
  16.     }
  17.     public static function retryable(Connection $connection\Closure $closure)
  18.     {
  19.         return self::retry($connection$closure0);
  20.     }
  21.     public function getQuery(): Statement
  22.     {
  23.         return $this->query;
  24.     }
  25.     private static function retry(?Connection $connection\Closure $closureint $counter)
  26.     {
  27.         ++$counter;
  28.         try {
  29.             return $closure();
  30.         } catch (RetryableException $e) {
  31.             if ($connection && $connection->getTransactionNestingLevel() > 0) {
  32.                 // If this closure was executed inside a transaction, do not retry. Remember that the whole (outermost)
  33.                 // transaction was already rolled back by the database when any RetryableException is thrown. Rethrow
  34.                 // the exception here so only the outermost transaction is retried which in turn includes this closure.
  35.                 throw $e;
  36.             }
  37.             if ($counter 10) {
  38.                 throw $e;
  39.             }
  40.             // randomize sleep to prevent same execution delay for multiple statements
  41.             usleep(20 $counter);
  42.             return self::retry($connection$closure$counter);
  43.         }
  44.     }
  45. }