impl redis cloud

This commit is contained in:
JurTI-BR
2025-04-01 16:42:05 -03:00
parent f8bea4114f
commit 28a1cee876
14 changed files with 819 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ import { Controller, Get, Param,UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth } from '@nestjs/swagger';
import { DataConsultService } from './data-consult.service';
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'
import { ProductDto } from './dto/product.dto';
@ApiTags('DataConsult')
@Controller('api/v1/data-consult')
@@ -48,4 +49,11 @@ export class DataConsultController {
async products(@Param('filter') filter: string) {
return this.dataConsultService.products(filter);
}
@Get('Buscar 500 produtos')
@ApiOperation({ summary: 'VIEW DE 500 PRODUTOS' })
async getAllProducts(): Promise<ProductDto[]> {
return this.dataConsultService.getAllProducts();
}
}

View File

@@ -129,7 +129,7 @@ export class DataConsultRepository {
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO ||
' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description"
FROM PCPRODUT
WHERE PCPRODUT.CODPROD = ?
WHERE PCPRODUT.CODPROD = :1
ORDER BY PCPRODUT.DESCRICAO
`,
params: [cleanedFilter],
@@ -140,7 +140,7 @@ export class DataConsultRepository {
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO ||
' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description"
FROM PCPRODUT
WHERE PCPRODUT.CODAUXILIAR = ?
WHERE PCPRODUT.CODAUXILIAR = :1
ORDER BY PCPRODUT.DESCRICAO
`,
params: [cleanedFilter],
@@ -151,7 +151,7 @@ export class DataConsultRepository {
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO ||
' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description"
FROM PCPRODUT
WHERE PCPRODUT.DESCRICAO LIKE ?
WHERE PCPRODUT.DESCRICAO LIKE :1
ORDER BY PCPRODUT.DESCRICAO
`,
params: [likeFilter],
@@ -167,4 +167,16 @@ export class DataConsultRepository {
return [];
}
async findAllProducts(): Promise<ProductDto[]> {
const sql = `
SELECT PCPRODUT.CODPROD as "id",
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO ||
' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description"
FROM PCPRODUT
WHERE ROWNUM <= 1000
ORDER BY PCPRODUT.DESCRICAO
`;
return this.executeQuery<ProductDto[]>(sql);
}
}

View File

@@ -17,6 +17,10 @@ export class DataConsultService {
private readonly SELLERS_CACHE_KEY = 'data-consult:sellers';
private readonly SELLERS_TTL = 3600; // 1 hora
private readonly STORES_TTL = 3600;
private readonly BILLINGS_TTL = 3600;
private readonly ALL_PRODUCTS_CACHE_KEY = 'data-consult:products:all';
private readonly ALL_PRODUCTS_TTL = 600; // 10 minutos (ajustável)
constructor(
@@ -59,8 +63,11 @@ export class DataConsultService {
async billings(): Promise<BillingDto[]> {
this.logger.log('Buscando todos os faturamentos');
return this.repository.findBillings();
}
/**
* Obter clientes filtrados por termo de pesquisa
* @param filter - Termo de pesquisa para filtrar clientes
@@ -95,4 +102,17 @@ export class DataConsultService {
);
}
}
async getAllProducts(): Promise<ProductDto[]> {
this.logger.log('Buscando produtos com cache Redis...');
return getOrSetCache<ProductDto[]>(
this.redisClient,
this.ALL_PRODUCTS_CACHE_KEY,
this.ALL_PRODUCTS_TTL,
async () => {
this.logger.log('Cache de produtos vazio. Buscando no banco...');
return this.repository.findAllProducts();
}
);
}
}

View File

@@ -0,0 +1,140 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
exports.DataConsultController = void 0;
var common_1 = require("@nestjs/common");
var swagger_1 = require("@nestjs/swagger");
var jwt_auth_guard_1 = require("src/auth/guards/jwt-auth.guard");
var DataConsultController = /** @class */ (function () {
function DataConsultController(dataConsultService) {
this.dataConsultService = dataConsultService;
}
DataConsultController.prototype.stores = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.stores()];
});
});
};
DataConsultController.prototype.sellers = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.sellers()];
});
});
};
DataConsultController.prototype.billings = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.billings()];
});
});
};
DataConsultController.prototype.customer = function (filter) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.customers(filter)];
});
});
};
DataConsultController.prototype.products = function (filter) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.products(filter)];
});
});
};
DataConsultController.prototype.getAllProducts = function () {
return __awaiter(this, void 0, Promise, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.dataConsultService.getAllProducts()];
});
});
};
__decorate([
common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard),
swagger_1.ApiBearerAuth(),
common_1.Get('stores'),
swagger_1.ApiOperation({ summary: 'Lista todas as lojas' })
], DataConsultController.prototype, "stores");
__decorate([
common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard),
swagger_1.ApiBearerAuth(),
common_1.Get('sellers'),
swagger_1.ApiOperation({ summary: 'Lista todos os vendedores' })
], DataConsultController.prototype, "sellers");
__decorate([
common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard),
swagger_1.ApiBearerAuth(),
common_1.Get('billings'),
swagger_1.ApiOperation({ summary: 'Retorna informações de faturamento' })
], DataConsultController.prototype, "billings");
__decorate([
common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard),
swagger_1.ApiBearerAuth(),
common_1.Get('customers/:filter'),
swagger_1.ApiOperation({ summary: 'Filtra clientes pelo parâmetro fornecido' }),
swagger_1.ApiParam({ name: 'filter', description: 'Filtro de busca para clientes' }),
__param(0, common_1.Param('filter'))
], DataConsultController.prototype, "customer");
__decorate([
common_1.Get('products/:filter'),
swagger_1.ApiOperation({ summary: 'Busca produtos filtrados' }),
swagger_1.ApiParam({ name: 'filter', description: 'Filtro de busca' }),
__param(0, common_1.Param('filter'))
], DataConsultController.prototype, "products");
__decorate([
common_1.Get('Buscar 500 produtos'),
swagger_1.ApiOperation({ summary: 'VIEW DE 500 PRODUTOS' })
], DataConsultController.prototype, "getAllProducts");
DataConsultController = __decorate([
swagger_1.ApiTags('DataConsult'),
common_1.Controller('api/v1/data-consult')
], DataConsultController);
return DataConsultController;
}());
exports.DataConsultController = DataConsultController;