Files
watchstate/src/Commands/State/CacheCommand.php

178 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Commands\State;
use App\Command;
use App\Libs\Config;
use App\Libs\Data;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Yaml;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Throwable;
class CacheCommand extends Command
{
public const TASK_NAME = 'cache';
public function __construct(private LoggerInterface $logger)
{
set_time_limit(0);
ini_set('memory_limit', '-1');
parent::__construct();
}
protected function configure(): void
{
$this->setName('state:cache')
->setDescription('Cache the GUIDs > Server Internal ID relations.')
->addOption(
'proxy',
null,
InputOption::VALUE_REQUIRED,
'By default the HTTP client uses your ENV: HTTP_PROXY.'
)
->addOption(
'no-proxy',
null,
InputOption::VALUE_REQUIRED,
'Disables the proxy for a comma-separated list of hosts that do not require it to get reached.'
)
->addOption(
'timeout',
null,
InputOption::VALUE_REQUIRED,
'Set request timeout in seconds'
)
->addOption(
'servers-filter',
's',
InputOption::VALUE_OPTIONAL,
'Sync selected servers, comma seperated. \'s1,s2\'.',
''
)
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addOption('redirect-logger', 'r', InputOption::VALUE_NONE, 'Not used. will be removed in the future.')
->addOption('memory-usage', 'm', InputOption::VALUE_NONE, 'Not used. will be removed in the future.');
}
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
return $this->single(fn(): int => $this->process($input, $output), $output);
}
protected function process(InputInterface $input, OutputInterface $output): int
{
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
if (!is_string($config) || !is_file($config) || !is_readable($config)) {
throw new RuntimeException('Unable to read data given config.');
}
Config::save('servers', Yaml::parseFile($config));
}
$list = [];
$serversFilter = (string)$input->getOption('servers-filter');
$selected = explode(',', $serversFilter);
$isCustom = !empty($serversFilter) && count($selected) >= 1;
$supported = Config::get('supported', []);
foreach (Config::get('servers', []) as $serverName => $server) {
$type = strtolower(ag($server, 'type', 'unknown'));
if ($isCustom && !in_array($serverName, $selected, true)) {
$this->logger->info(sprintf('Ignoring \'%s\' as requested by --servers-filter.', $serverName));
continue;
}
if (!isset($supported[$type])) {
$this->logger->error(
sprintf(
'Unexpected type for server \'%s\'. Was Expecting one of [%s], but got \'%s\' instead.',
$serverName,
implode('|', array_keys($supported)),
$type
)
);
return self::FAILURE;
}
if (null === ag($server, 'url')) {
$this->logger->error(sprintf('Server \'%s\' has no URL.', $serverName));
return self::FAILURE;
}
$server['name'] = $serverName;
$list[$serverName] = $server;
}
if (empty($list)) {
$output->writeln(
sprintf(
'<error>%s</error>',
$isCustom ? '--servers-filter/-s did not return any servers.' : 'No servers were found.'
)
);
return self::FAILURE;
}
/** @var array<array-key,ResponseInterface> $queue */
$queue = [];
foreach ($list as $name => &$server) {
Data::addBucket($name);
$opts = ag($server, 'options', []);
if ($input->getOption('proxy')) {
$opts['client']['proxy'] = $input->getOption('proxy');
}
if ($input->getOption('no-proxy')) {
$opts['client']['no_proxy'] = $input->getOption('no-proxy');
}
if ($input->getOption('timeout')) {
$opts['client']['timeout'] = $input->getOption('timeout');
}
$server['options'] = $opts;
$server['class'] = makeServer($server, $name);
$this->logger->notice(sprintf('Caching \'%s\' server guids relation map.', $name));
array_push($queue, ...$server['class']->cache());
}
unset($server);
$this->logger->notice(sprintf('Waiting on (%d) HTTP Requests.', count($queue)));
foreach ($queue as $_key => $response) {
$requestData = $response->getInfo('user_data');
try {
$requestData['ok']($response);
} catch (Throwable $e) {
$requestData['error']($e);
}
$queue[$_key] = null;
gc_collect_cycles();
}
unset($queue);
$this->logger->notice('Finished Caching GUIDs relations.');
return self::SUCCESS;
}
}