FastCGI
This commit is contained in:
@ -1,9 +1,15 @@
|
|||||||
#ENVIRONMENT=
|
#ENVIRONMENT=
|
||||||
|
|
||||||
TZ=
|
TZ=America/Santiago
|
||||||
|
#ENVIRONMENT=
|
||||||
APP_NAME=incoviba_cli
|
APP_NAME=incoviba_cli
|
||||||
API_URL=http://proxy/api
|
API_URL=http://proxy/api
|
||||||
|
#API_USERNAME=
|
||||||
|
#API_PASSWORD=
|
||||||
|
|
||||||
API_USERNAME=
|
#REDIS_HOST=redis
|
||||||
API_PASSWORD=
|
#REDIS_PORT=6379
|
||||||
|
|
||||||
|
#SOCKET_HOST=web
|
||||||
|
#SOCKET_PORT=9000
|
||||||
|
#SOCKET_ROOT=/code/public/index.php
|
||||||
|
@ -10,6 +10,7 @@ class Application extends Console\Application
|
|||||||
{
|
{
|
||||||
public function __construct(protected ContainerInterface $container, string $name = 'UNKNOWN', string $version = 'UNKNOWN')
|
public function __construct(protected ContainerInterface $container, string $name = 'UNKNOWN', string $version = 'UNKNOWN')
|
||||||
{
|
{
|
||||||
|
$name = 'incoviba_cli';
|
||||||
if ($this->container->has('APP_NAME')) {
|
if ($this->container->has('APP_NAME')) {
|
||||||
$name = $this->container->get('APP_NAME');
|
$name = $this->container->get('APP_NAME');
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"dragonmantank/cron-expression": "^3.4",
|
"dragonmantank/cron-expression": "^3.4",
|
||||||
"guzzlehttp/guzzle": "^7.8",
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
|
"hollodotme/fast-cgi-client": "^3.1",
|
||||||
"monolog/monolog": "^3.5",
|
"monolog/monolog": "^3.5",
|
||||||
"php-di/php-di": "^7.0",
|
"php-di/php-di": "^7.0",
|
||||||
"predis/predis": "^3.0",
|
"predis/predis": "^3.0",
|
||||||
|
@ -4,7 +4,7 @@ use Psr\Container\ContainerInterface;
|
|||||||
return [
|
return [
|
||||||
Incoviba\Service\Login::class => function(ContainerInterface $container) {
|
Incoviba\Service\Login::class => function(ContainerInterface $container) {
|
||||||
$client = new GuzzleHttp\Client([
|
$client = new GuzzleHttp\Client([
|
||||||
'base_uri' => $container->get('API_URL'),
|
'base_uri' => $container->has('API_URL') ? $container->get('API_URL') : 'http://proxy/api',
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'Authorization' => [
|
'Authorization' => [
|
||||||
'Bearer ' . md5($container->get('API_KEY'))
|
'Bearer ' . md5($container->get('API_KEY'))
|
||||||
@ -36,8 +36,15 @@ return [
|
|||||||
},
|
},
|
||||||
Psr\Http\Client\ClientInterface::class => function(ContainerInterface $container) {
|
Psr\Http\Client\ClientInterface::class => function(ContainerInterface $container) {
|
||||||
return new GuzzleHttp\Client([
|
return new GuzzleHttp\Client([
|
||||||
'base_uri' => $container->get('API_URL'),
|
'base_uri' => $container->has('API_URL') ? $container->get('API_URL') : 'http://proxy/api',
|
||||||
'handler' => $container->get(GuzzleHttp\HandlerStack::class),
|
'handler' => $container->get(GuzzleHttp\HandlerStack::class),
|
||||||
]);
|
]);
|
||||||
}
|
},
|
||||||
|
Incoviba\Service\FastCGI::class => function(ContainerInterface $container) {
|
||||||
|
return new Incoviba\Service\FastCGI(
|
||||||
|
$container->has('SOCKET_HOST') ? $container->get('SOCKET_HOST') : 'web',
|
||||||
|
$container->has('SOCKET_PORT') ? $container->get('SOCKET_PORT') : 9000,
|
||||||
|
$container->has('SOCKET_ROOT') ? $container->get('SOCKET_ROOT') : '/code/public/index.php'
|
||||||
|
);
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -5,8 +5,8 @@ return [
|
|||||||
Predis\ClientInterface::class => function(ContainerInterface $container) {
|
Predis\ClientInterface::class => function(ContainerInterface $container) {
|
||||||
$options = [
|
$options = [
|
||||||
'scheme' => 'tcp',
|
'scheme' => 'tcp',
|
||||||
'host' => $container->get('REDIS_HOST'),
|
'host' => $container->has('REDIS_HOST') ? $container->get('REDIS_HOST') : 'redis',
|
||||||
'port' => $container->get('REDIS_PORT')
|
'port' => $container->has('REDIS_PORT') ? $container->get('REDIS_PORT') : 6379
|
||||||
];
|
];
|
||||||
if ($container->has('REDIS_USER')) {
|
if ($container->has('REDIS_USER')) {
|
||||||
$options['username'] = $container->get('REDIS_USER');
|
$options['username'] = $container->get('REDIS_USER');
|
||||||
|
@ -7,8 +7,10 @@ use Psr\Http\Client\ClientExceptionInterface;
|
|||||||
use Psr\Http\Client\ClientInterface;
|
use Psr\Http\Client\ClientInterface;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Console;
|
use Symfony\Component\Console;
|
||||||
|
use Incoviba\Service\FastCGI;
|
||||||
use Incoviba\Service\Job;
|
use Incoviba\Service\Job;
|
||||||
use Incoviba\Common\Alias\Command;
|
use Incoviba\Common\Alias\Command;
|
||||||
|
use Incoviba\Exception\Client\FastCGI as FastCGIException;
|
||||||
|
|
||||||
#[Console\Attribute\AsCommand(
|
#[Console\Attribute\AsCommand(
|
||||||
name: 'queue',
|
name: 'queue',
|
||||||
@ -16,10 +18,11 @@ use Incoviba\Common\Alias\Command;
|
|||||||
)]
|
)]
|
||||||
class Queue extends Command
|
class Queue extends Command
|
||||||
{
|
{
|
||||||
public function __construct(ClientInterface $client, LoggerInterface $logger,
|
public function __construct(ClientInterface $client, LoggerInterface $logger,
|
||||||
protected Job $jobService,
|
protected Job $jobService,
|
||||||
protected DateTimeZone $timezone,
|
protected DateTimeZone $timezone,
|
||||||
?string $name = null)
|
protected FastCGI $fastcgi,
|
||||||
|
?string $name = null)
|
||||||
{
|
{
|
||||||
parent::__construct($client, $logger, $name);
|
parent::__construct($client, $logger, $name);
|
||||||
}
|
}
|
||||||
@ -55,20 +58,30 @@ class Queue extends Command
|
|||||||
$errors ++;
|
$errors ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$responses = $this->fastcgi->awaitResponses();
|
||||||
|
foreach ($responses as $response) {
|
||||||
|
if ((int) floor($response->getStatusCode() / 100) !== 2) {
|
||||||
|
$this->logger->error("Error running job", [
|
||||||
|
'status' => $response->getStatusCode(),
|
||||||
|
'body' => $response->getBody()->getContents(),
|
||||||
|
'headers' => $response->getHeaders(),
|
||||||
|
]);
|
||||||
|
$errors ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
return $errors === 0 ? Console\Command\Command::SUCCESS : Console\Command\Command::FAILURE;
|
return $errors === 0 ? Console\Command\Command::SUCCESS : Console\Command\Command::FAILURE;
|
||||||
}
|
}
|
||||||
protected function runJob(Console\Output\OutputInterface $output, int $job_id): int
|
protected function runJob(Console\Output\OutputInterface $output, int $job_id): int
|
||||||
{
|
{
|
||||||
$uri = "/api/queue/run/{$job_id}";
|
$uri = "/api/queue/run/{$job_id}";
|
||||||
$output->writeln("GET {$uri}");
|
$output->writeln("GET {$uri}");
|
||||||
try {
|
|
||||||
$response = $this->client->get($uri);
|
|
||||||
} catch (ClientExceptionInterface $exception) {
|
|
||||||
$this->logger->error($exception);
|
|
||||||
return Console\Command\Command::FAILURE;
|
|
||||||
}
|
|
||||||
$output->writeln("Response Code: {$response->getStatusCode()}");
|
|
||||||
|
|
||||||
return ((int) floor($response->getStatusCode() / 100) === 2) ? Console\Command\Command::SUCCESS : Console\Command\Command::FAILURE;
|
try {
|
||||||
|
$this->fastcgi->get($uri);
|
||||||
|
return self::SUCCESS;
|
||||||
|
} catch (FastCGIException $exception) {
|
||||||
|
$this->logger->error($exception->getMessage(), ['uri' => $uri, 'exception' =>$exception]);
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
cli/src/Exception/Client/FastCGI.php
Normal file
55
cli/src/Exception/Client/FastCGI.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Exception\Client;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
use Psr\Http\Client\ClientExceptionInterface;
|
||||||
|
|
||||||
|
|
||||||
|
class FastCGI implements ClientExceptionInterface
|
||||||
|
{
|
||||||
|
public function __construct(protected ?Throwable $previous) {}
|
||||||
|
|
||||||
|
public function getMessage(): string
|
||||||
|
{
|
||||||
|
$message = "Could not send request";
|
||||||
|
if ($this->previous !== null) {
|
||||||
|
$message .= ": {$this->previous->getMessage()}";
|
||||||
|
}
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCode()
|
||||||
|
{
|
||||||
|
return $this->previous?->getCode() ?? 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFile(): string
|
||||||
|
{
|
||||||
|
return $this->previous?->getFile() ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLine(): int
|
||||||
|
{
|
||||||
|
return $this->previous?->getLine() ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTrace(): array
|
||||||
|
{
|
||||||
|
return $this->previous?->getTrace() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTraceAsString(): string
|
||||||
|
{
|
||||||
|
return $this->previous?->getTraceAsString() ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrevious(): ?Throwable
|
||||||
|
{
|
||||||
|
return $this->previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->getMessage();
|
||||||
|
}
|
||||||
|
}
|
99
cli/src/Service/FastCGI.php
Normal file
99
cli/src/Service/FastCGI.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerAwareInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use hollodotme\FastCGI as FCGI;
|
||||||
|
use Incoviba\Exception\Client\FastCGI as FastCGIException;
|
||||||
|
|
||||||
|
class FastCGI implements LoggerAwareInterface
|
||||||
|
{
|
||||||
|
public function __construct(protected string $hostname, protected int $port,
|
||||||
|
protected string $documentRoot,
|
||||||
|
protected int $connectionTimeout = 5000, protected int $readTimeout = 5000)
|
||||||
|
{
|
||||||
|
$this->client = new FCGI\Client();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoggerInterface $logger {
|
||||||
|
get {
|
||||||
|
return $this->logger;
|
||||||
|
}
|
||||||
|
set(LoggerInterface $logger) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FCGI\Client $client;
|
||||||
|
protected FCGI\Interfaces\ConfiguresSocketConnection $socket;
|
||||||
|
public function connect(): self
|
||||||
|
{
|
||||||
|
$this->socket = new FCGI\SocketConnections\NetworkSocket($this->hostname, $this->port, $this->connectionTimeout, $this->readTimeout);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected array $socketIds = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FastCGIException
|
||||||
|
*/
|
||||||
|
public function sendRequest(FCGI\Interfaces\ProvidesRequestData $request): self
|
||||||
|
{
|
||||||
|
if (!isset($this->socket)) {
|
||||||
|
$this->connect();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$this->socketIds []= $this->client->sendAsyncRequest($this->socket, $request);
|
||||||
|
} catch (FCGI\Exceptions\FastCGIClientException $exception) {
|
||||||
|
$this->logger->error($exception->getMessage());
|
||||||
|
throw new FastCGIException($exception);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function awaitResponses(): array
|
||||||
|
{
|
||||||
|
$responses = [];
|
||||||
|
while ($this->client->hasUnhandledResponses()) {
|
||||||
|
try {
|
||||||
|
$readyResponses = $this->client->readReadyResponses(3000);
|
||||||
|
} catch (FCGI\Exceptions\FastCGIClientException $exception) {
|
||||||
|
$this->logger->error($exception->getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($readyResponses as $response) {
|
||||||
|
$responses []= $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $responses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $uri
|
||||||
|
* @return FastCGI
|
||||||
|
* @throws FastCGIException
|
||||||
|
*/
|
||||||
|
public function get(string $uri): self
|
||||||
|
{
|
||||||
|
$request = new FCGI\Requests\GetRequest($this->documentRoot, '');
|
||||||
|
$request->setRequestUri($uri);
|
||||||
|
return $this->sendRequest($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $uri
|
||||||
|
* @param ?array $data
|
||||||
|
* @return FastCGI
|
||||||
|
* @throws FastCGIException
|
||||||
|
*/
|
||||||
|
public function post(string $uri, ?array $data): self
|
||||||
|
{
|
||||||
|
$content = new FCGI\RequestContents\JsonData($data ?? []);
|
||||||
|
$request = FCGI\Requests\PostRequest::newWithRequestContent($this->documentRoot, $content);
|
||||||
|
$request->setRequestUri($uri);
|
||||||
|
return $this->sendRequest($request);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user