99 lines
3.0 KiB
PHP
99 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Command;
|
|
|
|
use App\Entity\Client;
|
|
use App\Entity\Trace;
|
|
use App\Model\ClientStatus;
|
|
use App\Model\TraceStatus;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
use Symfony\Component\Mercure\HubInterface;
|
|
use Symfony\Component\Mercure\Update;
|
|
|
|
#[AsCommand(name: 'opengnsys:check-client-availability', description: 'Check client availability')]
|
|
class CheckClientAvailability extends Command
|
|
{
|
|
const int THRESHOLD_MINUTES = 3;
|
|
|
|
public function __construct(
|
|
private readonly HubInterface $hub,
|
|
private readonly EntityManagerInterface $entityManager
|
|
)
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
$threshold = (new \DateTime())->modify(' - '.self::THRESHOLD_MINUTES . ' minutes');
|
|
|
|
$startQueryTime = microtime(true);
|
|
|
|
$query = $this->entityManager->createQuery(
|
|
'UPDATE App\Entity\Client c
|
|
SET c.status = :status
|
|
WHERE c.status = :currentStatus AND c.updatedAt < :threshold'
|
|
);
|
|
$query->setParameter('status', ClientStatus::DISCONNECTED);
|
|
$query->setParameter('currentStatus', ClientStatus::OG_LIVE);
|
|
$query->setParameter('threshold', $threshold);
|
|
$updatedCount = $query->execute();
|
|
|
|
$queryTime = microtime(true) - $startQueryTime;
|
|
|
|
$startMercureTime = microtime(true);
|
|
|
|
$clients = $this->entityManager->createQueryBuilder()
|
|
->select('c')
|
|
->from(Client::class, 'c')
|
|
->where('c.status = :status')
|
|
->andWhere('c.updatedAt < :threshold')
|
|
->setParameter('status', ClientStatus::DISCONNECTED)
|
|
->setParameter('threshold', $threshold)
|
|
->getQuery()
|
|
->getResult();
|
|
|
|
$this->dispatchMercureEvent($clients);
|
|
|
|
$mercureTime = microtime(true) - $startMercureTime;
|
|
|
|
$io->success("Updated $updatedCount clients to DISCONNECTED status.");
|
|
$io->note("Query time: " . round($queryTime, 3) . "s");
|
|
$io->note("Mercure dispatch time: " . round($mercureTime, 3) . "s");
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
private function dispatchMercureEvent(array $clients, int $chunkSize = 10000): void
|
|
{
|
|
$chunks = array_chunk($clients, $chunkSize);
|
|
|
|
foreach ($chunks as $chunk) {
|
|
$data = [];
|
|
|
|
foreach ($chunk as $client) {
|
|
$data[] = [
|
|
'@id' => '/clients/' . $client->getUuid(),
|
|
'status' => $client->getStatus(),
|
|
];
|
|
}
|
|
|
|
$update = new Update(
|
|
'clients',
|
|
json_encode($data)
|
|
);
|
|
|
|
$this->hub->publish($update);
|
|
}
|
|
}
|
|
|
|
}
|