src/Console/Sales/RotateProfileAdBoardPlacementsCommand.php line 43

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-05-06
  5.  * Time: 17:50
  6.  */
  7. namespace App\Console\Sales;
  8. use App\Entity\Sales\Profile\AdBoardPlacement;
  9. use App\Repository\CityRepository;
  10. use App\Repository\ProfileAdBoardPlacementRepository;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use Doctrine\Persistence\ManagerRegistry;
  13. use Symfony\Component\Console\Command\Command;
  14. use Symfony\Component\Console\Input\InputInterface;
  15. use Symfony\Component\Console\Output\OutputInterface;
  16. use Symfony\Component\Console\Style\SymfonyStyle;
  17. class RotateProfileAdBoardPlacementsCommand extends Command
  18. {
  19.     const ROTATIONS_PER_HOUR = 30;
  20.     private const AD_BOARD_PIPELINE_LOCK = 'sales:adboard:pipeline';
  21.     private const AD_BOARD_PIPELINE_LOCK_WAIT_SECONDS = 120;
  22.     private EntityManagerInterface $entityManager;
  23.     public function __construct(
  24.         ManagerRegistry $managerRegistry,
  25.         protected CityRepository $cityRepository,
  26.         protected ProfileAdBoardPlacementRepository $placementRepository
  27.     )
  28.     {
  29.         parent::__construct();
  30.         $this->entityManager = $managerRegistry->getManagerForClass(AdBoardPlacement::class);
  31.     }
  32.     protected function configure()
  33.     {
  34.         $this->setName('sales:profile:adboard:rotate');
  35.         $this->setAliases(['sales:placements:rotate']);
  36.     }
  37.     protected function execute(InputInterface $input, OutputInterface $output): int
  38.     {
  39.         $io = new SymfonyStyle($input, $output);
  40.         $connection = $this->entityManager->getConnection();
  41.         $hasLock = (int)$connection->fetchOne(
  42.             'SELECT GET_LOCK(:lock_name, :lock_wait)',
  43.             [
  44.                 'lock_name' => self::AD_BOARD_PIPELINE_LOCK,
  45.                 'lock_wait' => self::AD_BOARD_PIPELINE_LOCK_WAIT_SECONDS,
  46.             ]
  47.         ) === 1;
  48.         if (!$hasLock) {
  49.             $io->warning('Skipped: adboard pipeline lock is already acquired by another process.');
  50.             return Command::SUCCESS;
  51.         }
  52.         try {
  53.             $io->title('Rotating profile adboard placements');
  54.             $io->progressStart();
  55.             foreach ($this->cityRepository->iterateAll() as $city) {
  56.                 $this->placementRepository->rotateAdBoardStandardPositions($city, self::ROTATIONS_PER_HOUR);
  57.                 $this->placementRepository->rotateAdBoardVipPositions($city, self::ROTATIONS_PER_HOUR);
  58.                 $this->placementRepository->rotateAdBoardUltraVipPositions($city, self::ROTATIONS_PER_HOUR);
  59.                 $io->progressAdvance();
  60.             }
  61.             $io->progressFinish();
  62.             $io->success('Success rotating profile placements');
  63.         } finally {
  64.             $connection->executeStatement(
  65.                 'DO RELEASE_LOCK(:lock_name)',
  66.                 ['lock_name' => self::AD_BOARD_PIPELINE_LOCK]
  67.             );
  68.         }
  69.         return Command::SUCCESS;
  70.     }
  71. }