<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-05-06
* Time: 17:50
*/
namespace App\Console\Sales;
use App\Entity\Sales\Profile\AdBoardPlacement;
use App\Repository\CityRepository;
use App\Repository\ProfileAdBoardPlacementRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class RotateProfileAdBoardPlacementsCommand extends Command
{
const ROTATIONS_PER_HOUR = 30;
private const AD_BOARD_PIPELINE_LOCK = 'sales:adboard:pipeline';
private const AD_BOARD_PIPELINE_LOCK_WAIT_SECONDS = 120;
private EntityManagerInterface $entityManager;
public function __construct(
ManagerRegistry $managerRegistry,
protected CityRepository $cityRepository,
protected ProfileAdBoardPlacementRepository $placementRepository
)
{
parent::__construct();
$this->entityManager = $managerRegistry->getManagerForClass(AdBoardPlacement::class);
}
protected function configure()
{
$this->setName('sales:profile:adboard:rotate');
$this->setAliases(['sales:placements:rotate']);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$connection = $this->entityManager->getConnection();
$hasLock = (int)$connection->fetchOne(
'SELECT GET_LOCK(:lock_name, :lock_wait)',
[
'lock_name' => self::AD_BOARD_PIPELINE_LOCK,
'lock_wait' => self::AD_BOARD_PIPELINE_LOCK_WAIT_SECONDS,
]
) === 1;
if (!$hasLock) {
$io->warning('Skipped: adboard pipeline lock is already acquired by another process.');
return Command::SUCCESS;
}
try {
$io->title('Rotating profile adboard placements');
$io->progressStart();
foreach ($this->cityRepository->iterateAll() as $city) {
$this->placementRepository->rotateAdBoardStandardPositions($city, self::ROTATIONS_PER_HOUR);
$this->placementRepository->rotateAdBoardVipPositions($city, self::ROTATIONS_PER_HOUR);
$this->placementRepository->rotateAdBoardUltraVipPositions($city, self::ROTATIONS_PER_HOUR);
$io->progressAdvance();
}
$io->progressFinish();
$io->success('Success rotating profile placements');
} finally {
$connection->executeStatement(
'DO RELEASE_LOCK(:lock_name)',
['lock_name' => self::AD_BOARD_PIPELINE_LOCK]
);
}
return Command::SUCCESS;
}
}