vendor/shopware/core/Framework/DataAbstractionLayer/Doctrine/RetryableQuery.php line 21

  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(
  11.         private readonly ?Connection $connection,
  12.         private readonly Statement $query
  13.     ) {
  14.     }
  15.     public function execute(array $params = []): int
  16.     {
  17.         return self::retry($this->connection, fn () => $this->query->executeStatement($params), 0);
  18.     }
  19.     public static function retryable(Connection $connection\Closure $closure)
  20.     {
  21.         return self::retry($connection$closure0);
  22.     }
  23.     public function getQuery(): Statement
  24.     {
  25.         return $this->query;
  26.     }
  27.     private static function retry(?Connection $connection\Closure $closureint $counter)
  28.     {
  29.         ++$counter;
  30.         try {
  31.             return $closure();
  32.         } catch (RetryableException $e) {
  33.             if ($connection && $connection->getTransactionNestingLevel() > 0) {
  34.                 // If this closure was executed inside a transaction, do not retry. Remember that the whole (outermost)
  35.                 // transaction was already rolled back by the database when any RetryableException is thrown. Rethrow
  36.                 // the exception here so only the outermost transaction is retried which in turn includes this closure.
  37.                 throw $e;
  38.             }
  39.             if ($counter 10) {
  40.                 throw $e;
  41.             }
  42.             // randomize sleep to prevent same execution delay for multiple statements
  43.             usleep(20 $counter);
  44.             return self::retry($connection$closure$counter);
  45.         }
  46.     }
  47. }