116 lines
3.3 KiB
PHP
116 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Console\Command\Sync;
|
|
|
|
use App\Entity\Repository\SettingsRepository;
|
|
use App\Environment;
|
|
use App\LockFactory;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
|
|
use function random_int;
|
|
|
|
#[AsCommand(
|
|
name: 'azuracast:sync:nowplaying',
|
|
description: 'Task to run the Now Playing worker task.'
|
|
)]
|
|
class NowPlayingCommand extends AbstractSyncCommand
|
|
{
|
|
public function __construct(
|
|
LoggerInterface $logger,
|
|
LockFactory $lockFactory,
|
|
Environment $environment,
|
|
protected EntityManagerInterface $em,
|
|
protected SettingsRepository $settingsRepo,
|
|
) {
|
|
parent::__construct($logger, $lockFactory, $environment);
|
|
}
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this->addOption(
|
|
'timeout',
|
|
't',
|
|
InputOption::VALUE_OPTIONAL,
|
|
'Amount of time (in seconds) to run the worker process.',
|
|
600
|
|
);
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$settings = $this->settingsRepo->readSettings();
|
|
if ($settings->getSyncDisabled()) {
|
|
$this->logger->error('Automated synchronization is temporarily disabled.');
|
|
return 1;
|
|
}
|
|
|
|
$timeout = (int)$input->getOption('timeout');
|
|
$this->loop($io, $timeout);
|
|
|
|
return 0;
|
|
}
|
|
|
|
protected function loop(SymfonyStyle $io, int $timeout): void
|
|
{
|
|
$threshold = time() + $timeout;
|
|
|
|
while (time() < $threshold || !empty($this->processes)) {
|
|
// Check existing processes.
|
|
$this->checkRunningProcesses();
|
|
|
|
// Ensure a process is running for every active station.
|
|
if (time() < $threshold - 5) {
|
|
$activeStations = $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT s.id, s.short_name, s.nowplaying_timestamp
|
|
FROM App\Entity\Station s
|
|
WHERE s.is_enabled = 1
|
|
DQL
|
|
)->getArrayResult();
|
|
|
|
foreach ($activeStations as $activeStation) {
|
|
$shortName = $activeStation['short_name'];
|
|
|
|
if (!isset($this->processes[$shortName])) {
|
|
$npTimestamp = (int)$activeStation['nowplaying_timestamp'];
|
|
if (time() > $npTimestamp + random_int(5, 15)) {
|
|
$this->start($io, $shortName);
|
|
|
|
usleep(250000);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->em->clear();
|
|
gc_collect_cycles();
|
|
usleep(1000000);
|
|
}
|
|
}
|
|
|
|
protected function start(
|
|
SymfonyStyle $io,
|
|
string $shortName
|
|
): void {
|
|
$this->lockAndRunConsoleCommand(
|
|
$io,
|
|
$shortName,
|
|
'nowplaying',
|
|
[
|
|
'azuracast:sync:nowplaying:station',
|
|
$shortName,
|
|
]
|
|
);
|
|
}
|
|
}
|