Redis service

This commit is contained in:
2023-10-19 20:46:52 -03:00
parent 742c0327c2
commit dc217d876a
10 changed files with 228 additions and 97 deletions

View File

@ -0,0 +1,15 @@
<?php
namespace Incoviba\Common\Implement\Exception;
use Throwable;
use Exception;
class EmptyRedis extends Exception
{
public function __construct(string $key, ?Throwable $previous = null)
{
$message = "Redis key {$key} not found in database.";
$code = 750;
parent::__construct($message, $code, $previous);
}
}

View File

@ -9,6 +9,7 @@
"nyholm/psr7-server": "^1.0",
"php-di/php-di": "^7.0",
"php-di/slim-bridge": "^3.4",
"predis/predis": "^2.2",
"slim/slim": "^4.11"
},
"require-dev": {

View File

@ -19,4 +19,11 @@ return [
return (new Incoviba\Service\Money())->register('uf', $mindicador)
->register('ipc', $mindicador);
},
Predis\Client::class => function(ContainerInterface $container) {
return new Predis\Client([
'scheme' => 'tcp',
'host' => $container->get('REDIS_HOST'),
'port' => $container->get('REDIS_PORT')
]);
}
];

View File

@ -1,6 +1,8 @@
<?php
namespace Incoviba\Controller\API;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
@ -10,7 +12,7 @@ use Incoviba\Service;
class Ventas
{
use withJson;
use withJson, withRedis;
public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta $service): ResponseInterface
{
@ -46,29 +48,40 @@ class Ventas
}
return $this->withJson($response, $output);
}
public function porFirmar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService): ResponseInterface
public function porFirmar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "promesas_por_firmar-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'promesas' => 0
];
try {
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$ventas = $ventaService->getByProyecto($proyecto_id);
$promesas = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'vigente';
});
$output['promesas'] = count($promesas);
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function escrituras(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Venta\Pago $pagoService): ResponseInterface
public function escrituras(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Venta\Pago $pagoService, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "escrituras-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'escrituras' => [
@ -77,6 +90,9 @@ class Ventas
'abonar' => 0
]
];
try {
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$ventas = $ventaService->getEscriturasByProyecto($proyecto_id);
$porFirmar = array_filter($ventas, function(Model\Venta $venta) {
@ -106,7 +122,9 @@ class Ventas
});
$output['escrituras']['abonar'] = count($porAbonar);
unset($porAbonar);
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function comentarios(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $service, Repository\Venta\Comentario $comentarioRepository, int $venta_id): ResponseInterface

View File

@ -3,38 +3,59 @@ namespace Incoviba\Controller\API\Ventas;
use DateTimeImmutable;
use DateInterval;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Controller\API\withRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
use Incoviba\Service;
class Cuotas
{
use withJson;
public function hoy(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository): ResponseInterface
use withJson, withRedis;
public function hoy(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService): ResponseInterface
{
$today = new DateTimeImmutable();
$redisKey = "cuotas_hoy-{$today->format('Y-m-d')}";
$output = [
'cuotas' => 0
];
try {
$output['cuotas'] = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$output['cuotas'] = count($cuotaRepository->fetchHoy());
$this->saveRedis($redisService, $redisKey, $output['cuotas']);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function pendiente(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository): ResponseInterface
public function pendiente(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService): ResponseInterface
{
$today = new DateTimeImmutable();
$redisKey = "cuotas_pendientes-{$today->format('Y-m-d')}";
$output = [
'cuotas' => 0
];
try {
$output['cuotas'] = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$output['cuotas'] = count($cuotaRepository->fetchPendientes());
$this->saveRedis($redisService, $redisKey, $output['cuotas']);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function porVencer(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Format $formatService): ResponseInterface
public function porVencer(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService, Service\Format $formatService): ResponseInterface
{
$today = new DateTimeImmutable();
$redisKey = "cuotas_por_vencer-{$today->format('Y-m-d')}";
try {
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
$output = [];
try {
$benchmark = [
@ -67,7 +88,9 @@ class Cuotas
}
$benchmark['run'] = microtime(true) - $benchmark['start'];
error_log(var_export($benchmark,true));
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, ['cuotas' => $output]);
}
}

View File

@ -1,22 +1,29 @@
<?php
namespace Incoviba\Controller\API\Ventas;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Controller\API\withRedis;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
class Unidades
{
use withJson;
use withJson, withRedis;
public function disponibles(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Unidad $unidadRepository, Repository\Proyecto\TipoUnidad $tipoUnidadRepository): ResponseInterface
public function disponibles(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Unidad $unidadRepository, Repository\Proyecto\TipoUnidad $tipoUnidadRepository, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "unidades_disponibles-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'unidades' => [
@ -30,6 +37,9 @@ class Unidades
'bodegas' => 0,
]
];
try {
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$totalUnidades = $unidadRepository->fetchByProyecto($proyecto_id);
$unidades = $unidadRepository->fetchDisponiblesByProyecto($proyecto_id);
@ -50,7 +60,9 @@ class Unidades
}
$output['unidades']["{$tipoUnidad->descripcion}s"] = count($tempUnidades);
}
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
}

View File

@ -5,7 +5,7 @@ use Psr\Http\Message\ResponseInterface;
trait withJson
{
public function withJson(ResponseInterface $response, array $data = []): ResponseInterface
public function withJson(ResponseInterface $response, array|object $data = []): ResponseInterface
{
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');

View File

@ -0,0 +1,24 @@
<?php
namespace Incoviba\Controller\API;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Service;
trait withRedis
{
public function fetchRedis(Service\Redis $redisService, string $redisKey): mixed
{
$jsonString = $redisService->get($redisKey);
if ($jsonString === null) {
throw new EmptyRedis($redisKey);
}
return json_decode($jsonString);
}
public function saveRedis(Service\Redis $redisService, string $redisKey, mixed $value): void
{
if (is_array($value) or is_object($value)) {
$value = json_encode($value);
}
$redisService->set($redisKey, $value);
}
}

18
app/src/Service/Redis.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace Incoviba\Service;
use Predis\Client;
class Redis
{
public function __construct(protected Client $client) {}
public function get(string $name): mixed
{
return $this->client->get($name);
}
public function set(string $name, mixed $value): void
{
$this->client->set($name, $value);
}
}

View File

@ -47,6 +47,18 @@ services:
- default
- adminer_network
redis:
profiles:
- cache
image: redis
container_name: incoviba_redis
<<: *restart
env_file: ${APP_PATH:-.}/.redis.env
volumes:
- incoviba_redis:/data
ports:
- "63790:6379"
python:
profiles:
- python
@ -74,6 +86,7 @@ services:
volumes:
dbdata: {}
incoviba_redis: {}
networks:
adminer_network: {}