feat: implement Redis caching with locking and optimized product search in SalesService and update compression dependency
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 2m52s
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 2m52s
This commit is contained in:
45
package-lock.json
generated
45
package-lock.json
generated
@@ -20,7 +20,7 @@
|
|||||||
"@types/cache-manager": "^3.4.3",
|
"@types/cache-manager": "^3.4.3",
|
||||||
"cache-manager": "^3.6.3",
|
"cache-manager": "^3.6.3",
|
||||||
"cache-manager-redis-store": "^3.0.1",
|
"cache-manager-redis-store": "^3.0.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.8.1",
|
||||||
"crc": "^4.3.2",
|
"crc": "^4.3.2",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"guid-typescript": "^1.0.9",
|
"guid-typescript": "^1.0.9",
|
||||||
@@ -4181,16 +4181,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/compression": {
|
"node_modules/compression": {
|
||||||
"version": "1.7.4",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
|
||||||
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
|
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.5",
|
"bytes": "3.1.2",
|
||||||
"bytes": "3.0.0",
|
"compressible": "~2.0.18",
|
||||||
"compressible": "~2.0.16",
|
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"on-headers": "~1.0.2",
|
"negotiator": "~0.6.4",
|
||||||
"safe-buffer": "5.1.2",
|
"on-headers": "~1.1.0",
|
||||||
|
"safe-buffer": "5.2.1",
|
||||||
"vary": "~1.1.2"
|
"vary": "~1.1.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4198,17 +4199,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/compression/node_modules/bytes": {
|
"node_modules/compression/node_modules/bytes": {
|
||||||
"version": "3.0.0",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/compression/node_modules/safe-buffer": {
|
"node_modules/compression/node_modules/negotiator": {
|
||||||
"version": "5.1.2",
|
"version": "0.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
@@ -9810,9 +9816,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/on-headers": {
|
"node_modules/on-headers": {
|
||||||
"version": "1.0.2",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
|
||||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
|
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
"@types/cache-manager": "^3.4.3",
|
"@types/cache-manager": "^3.4.3",
|
||||||
"cache-manager": "^3.6.3",
|
"cache-manager": "^3.6.3",
|
||||||
"cache-manager-redis-store": "^3.0.1",
|
"cache-manager-redis-store": "^3.0.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.8.1",
|
||||||
"crc": "^4.3.2",
|
"crc": "^4.3.2",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"guid-typescript": "^1.0.9",
|
"guid-typescript": "^1.0.9",
|
||||||
|
|||||||
@@ -27,8 +27,39 @@ export class SalesService {
|
|||||||
|
|
||||||
|
|
||||||
async GetProducts2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct = null,) {
|
async GetProducts2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct = null,) {
|
||||||
const connectionDb = new Connection(connectionOptions);
|
const cacheKey = `GetProducts2:${store}:${pageSize}:${pageNumber}:${JSON.stringify(filter)}`;
|
||||||
await connectionDb.connect();
|
const lockKey = `lock:${cacheKey}`;
|
||||||
|
const lockTimeout = 30;
|
||||||
|
|
||||||
|
// Fase 1: Verificar cache Redis
|
||||||
|
try {
|
||||||
|
const cachedResult = await this.redisClient.get(cacheKey);
|
||||||
|
if (cachedResult) {
|
||||||
|
console.log('GetProducts2 - Retornando resultado do cache');
|
||||||
|
return JSON.parse(cachedResult);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Erro ao acessar o Redis no GetProducts2:', err?.message || err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock para evitar thundering herd
|
||||||
|
const lockValue = Date.now() + lockTimeout * 1000 + 1;
|
||||||
|
let acquiredLock: string | null = null;
|
||||||
|
try {
|
||||||
|
acquiredLock = await this.redisClient.set(lockKey, lockValue, 'NX', 'EX', lockTimeout);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Erro ao adquirir lock no Redis (GetProducts2):', err?.message || err);
|
||||||
|
acquiredLock = 'OK'; // Em caso de erro no Redis, prosseguir sem lock
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acquiredLock !== 'OK') {
|
||||||
|
console.log('Lock não adquirido (GetProducts2), aguardando...');
|
||||||
|
await this.sleep(1000);
|
||||||
|
return this.GetProducts2(store, pageSize, pageNumber, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fase 2: Reutilizar conexão via pool
|
||||||
|
const connectionDb = getConnection();
|
||||||
const queryRunner = connectionDb.createQueryRunner();
|
const queryRunner = connectionDb.createQueryRunner();
|
||||||
await queryRunner.connect();
|
await queryRunner.connect();
|
||||||
try {
|
try {
|
||||||
@@ -38,55 +69,11 @@ export class SalesService {
|
|||||||
pageNumber = 1;
|
pageNumber = 1;
|
||||||
const offSet = (pageNumber - 1) * pageSize;
|
const offSet = (pageNumber - 1) * pageSize;
|
||||||
|
|
||||||
const sqlProduto = `SELECT
|
|
||||||
esvlistaprodutos.CODPROD as "idProduct",
|
|
||||||
esvlistaprodutos.SEQ as "seq",
|
|
||||||
esvlistaprodutos.DESCRICAO as "smallDescription",
|
|
||||||
esvlistaprodutos.NOMEECOMMERCE as "title",
|
|
||||||
esvlistaprodutos.CODFAB as "idProvider",
|
|
||||||
esvlistaprodutos.CODAUXILIAR as "ean",
|
|
||||||
esvlistaprodutos.TIPOPRODUTO as "productType",
|
|
||||||
esvlistaprodutos.DADOSTECNICOS as "technicalData",
|
|
||||||
esvlistaprodutos.INFORMACOESTECNICAS as "description",
|
|
||||||
esvlistaprodutos.URLIMAGEM as "urlImage",
|
|
||||||
esvlistaprodutos.NOMEMARCA as "brand",
|
|
||||||
esvlistaprodutos.NOMEDEPARTAMENTO as "department",
|
|
||||||
esvlistaprodutos.NOMESECAO as "section",
|
|
||||||
esvlistaprodutos.NOMECATEGORIA as "category",
|
|
||||||
esvlistaprodutos.NOMEFORNECEDOR as "supplier",
|
|
||||||
esvlistaprodutos.CODIGOFILIAL as "store",
|
|
||||||
esvlistaprodutos.CLASSEVENDA as "saleAbc",
|
|
||||||
esvlistaprodutos.CLASSEESTOQUE as "stockAbc",
|
|
||||||
esvlistaprodutos.FORALINHA as "outLine",
|
|
||||||
esvlistaprodutos.PRECOVENDA as "listPrice",
|
|
||||||
esvlistaprodutos.PRECOPROMOCIONAL as "salePrice",
|
|
||||||
esvlistaprodutos.PRECOPROMOCIONAL as "salePromotion",
|
|
||||||
esvlistaprodutos.PRECOPROMOCIONAL_AVISTA as "salePromotion_cash",
|
|
||||||
esvlistaprodutos.PERCENTUALDESCONTO as "offPercent",
|
|
||||||
esvlistaprodutos.QTESTOQUE_DISPONIVEL as "stock",
|
|
||||||
esvlistaprodutos.QTCAIXAS as "boxStock",
|
|
||||||
esvlistaprodutos.ESTOQUE_DISP_LOJA as "store_stock",
|
|
||||||
esvlistaprodutos.ESTOQUE_DISP_CAIXA_LOJA as "store_boxStock",
|
|
||||||
esvlistaprodutos.MULTIPLO as "mutiple",
|
|
||||||
esvlistaprodutos.UNIDADE as "unity",
|
|
||||||
esvlistaprodutos.URLDEPARTAMENTO as "urlDepartment",
|
|
||||||
esvlistaprodutos.URLSECAO as "urlSection",
|
|
||||||
esvlistaprodutos.PRODUTO_COM_REDUCAO_PRECO as "downPrice",
|
|
||||||
esvlistaprodutos.PRODUTO_EM_CAMPANHA as "compaing",
|
|
||||||
esvlistaprodutos.BASETINTOMETRICO as "base",
|
|
||||||
esvlistaprodutos.LETRABASETINTOMETRICO as "letter",
|
|
||||||
esvlistaprodutos.LINHATINTOMETRICO as "line",
|
|
||||||
esvlistaprodutos.LITRAGEM as "can",
|
|
||||||
esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL as "full_stock",
|
|
||||||
esvlistaprodutos.TEM_PRODUTO_SIMILAR as "similar",
|
|
||||||
NVL(esvlistaprodutos.TIPO, 'SEM') as "type_campaing"
|
|
||||||
FROM ESVLISTAPRODUTOS
|
|
||||||
WHERE 1 = 1 `;
|
|
||||||
|
|
||||||
if (filter && filter.text.length > 0) {
|
if (filter && filter.text.length > 0) {
|
||||||
const description = filter.text.toUpperCase();
|
const description = filter.text.toUpperCase();
|
||||||
console.log('consultando por codigo de fabrica');
|
console.log('consultando por texto: ' + description);
|
||||||
|
|
||||||
|
// Fase 3: Query unificada - busca por CODFAB OU DESCRICAO em uma única query
|
||||||
let products = await queryRunner.manager
|
let products = await queryRunner.manager
|
||||||
.getRepository(SalesProduct)
|
.getRepository(SalesProduct)
|
||||||
.createQueryBuilder('esvlistaprodutos')
|
.createQueryBuilder('esvlistaprodutos')
|
||||||
@@ -97,8 +84,6 @@ export class SalesService {
|
|||||||
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
||||||
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
||||||
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
||||||
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
|
|
||||||
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
||||||
@@ -131,13 +116,13 @@ export class SalesService {
|
|||||||
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
|
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
|
||||||
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
|
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
|
||||||
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
|
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
|
||||||
.where("UPPER(\"esvlistaprodutos\".CODFAB) LIKE '%'||REPLACE(:description, '@', '%')||'%'", { description })
|
.where("(UPPER(\"esvlistaprodutos\".CODFAB) LIKE '%'||REPLACE(:description, '@', '%')||'%' OR UPPER(\"esvlistaprodutos\".descricao) LIKE '%'||REPLACE(:description, '@', '%')||'%')", { description })
|
||||||
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
|
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')",
|
.andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')",
|
||||||
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
|
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')",
|
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')",
|
||||||
{ campaign: (filter.campaign) ? 'I' : 'N' })
|
{ campaign: (filter.campaign) ? 'I' : 'N' })
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :oportunity OR :oportunity = 'N')",
|
.andWhere("(\"esvlistaprodutos\".produto_oportunidade = :oportunity OR :oportunity = 'N')",
|
||||||
{ oportunity: (filter.oportunity) ? 'O' : 'N' })
|
{ oportunity: (filter.oportunity) ? 'O' : 'N' })
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')",
|
.andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')",
|
||||||
{ produtoEmPromocao: (filter.promotion) ? 'S' : 'N' })
|
{ produtoEmPromocao: (filter.promotion) ? 'S' : 'N' })
|
||||||
@@ -145,69 +130,9 @@ export class SalesService {
|
|||||||
.offset(offSet)
|
.offset(offSet)
|
||||||
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
|
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
|
||||||
.getRawMany();
|
.getRawMany();
|
||||||
if (products.length == 0) {
|
|
||||||
products = await queryRunner.manager
|
|
||||||
.getRepository(SalesProduct)
|
|
||||||
.createQueryBuilder('esvlistaprodutos')
|
|
||||||
.select("\"esvlistaprodutos\".CODPROD", "idProduct")
|
|
||||||
.addSelect("\"esvlistaprodutos\".SEQ", "seq")
|
|
||||||
.addSelect("\"esvlistaprodutos\".DESCRICAO", "smallDescription")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEECOMMERCE", "title")
|
|
||||||
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
|
||||||
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
|
||||||
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
|
||||||
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
|
|
||||||
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMESECAO", "section")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMECATEGORIA", "category")
|
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEFORNECEDOR", "supplier")
|
|
||||||
.addSelect("\"esvlistaprodutos\".CODIGOFILIAL", "store")
|
|
||||||
.addSelect("\"esvlistaprodutos\".CLASSEVENDA", "saleAbc")
|
|
||||||
.addSelect("\"esvlistaprodutos\".CLASSEESTOQUE", "stockAbc")
|
|
||||||
.addSelect("\"esvlistaprodutos\".FORALINHA", "outLine")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRECOVENDA", "listPrice")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL", "salePrice")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL", "salePromotion")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL_AVISTA", "salePromotion_cash")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PERCENTUALDESCONTO", "offPercent")
|
|
||||||
.addSelect("\"esvlistaprodutos\".QTESTOQUE_DISPONIVEL", "stock")
|
|
||||||
.addSelect("\"esvlistaprodutos\".QTCAIXAS", "boxStock")
|
|
||||||
.addSelect("\"esvlistaprodutos\".ESTOQUE_DISP_LOJA", "store_stock")
|
|
||||||
.addSelect("\"esvlistaprodutos\".ESTOQUE_DISP_CAIXA_LOJA", "store_boxStock")
|
|
||||||
.addSelect("\"esvlistaprodutos\".MULTIPLO", "mutiple")
|
|
||||||
.addSelect("\"esvlistaprodutos\".UNIDADE", "unity")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLDEPARTAMENTO", "urlDepartment")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLSECAO", "urlSection")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice")
|
|
||||||
.addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing")
|
|
||||||
.addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base")
|
|
||||||
.addSelect("\"esvlistaprodutos\".LETRABASETINTOMETRICO", "letter")
|
|
||||||
.addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line")
|
|
||||||
.addSelect("\"esvlistaprodutos\".LITRAGEM", "can")
|
|
||||||
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
|
|
||||||
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
|
|
||||||
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
|
|
||||||
.where("UPPER(\"esvlistaprodutos\".descricao) LIKE '%'||REPLACE(:description, '@', '%')||'%'", { description })
|
|
||||||
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
|
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')",
|
|
||||||
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
|
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')",
|
|
||||||
{ campaign: (filter.campaign) ? 'I' : 'N' })
|
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_oportunidade = :oportunity OR :oportunity = 'N')",
|
|
||||||
{ oportunity: (filter.oportunity) ? 'O' : 'N' })
|
|
||||||
.andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')",
|
|
||||||
{ produtoEmPromocao: (filter.promotion) ? 'S' : 'N' })
|
|
||||||
.orderBy("\"esvlistaprodutos\".CLASSEVENDA")
|
|
||||||
.limit(pageSize)
|
|
||||||
.offset(offSet)
|
|
||||||
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
|
|
||||||
.getRawMany();
|
|
||||||
}
|
|
||||||
products = this.createListImages(products);
|
products = this.createListImages(products);
|
||||||
console.log(products.length + ' produtos');
|
console.log(products.length + ' produtos');
|
||||||
|
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
|
||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,8 +159,6 @@ export class SalesService {
|
|||||||
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
||||||
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
||||||
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
||||||
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
|
|
||||||
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
||||||
@@ -285,6 +208,7 @@ export class SalesService {
|
|||||||
.getRawMany();
|
.getRawMany();
|
||||||
products = this.createListImages(products);
|
products = this.createListImages(products);
|
||||||
console.log(products.length + ' produtos');
|
console.log(products.length + ' produtos');
|
||||||
|
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
|
||||||
return products;
|
return products;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -300,8 +224,6 @@ export class SalesService {
|
|||||||
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
|
||||||
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
|
||||||
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
|
||||||
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
|
|
||||||
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
|
|
||||||
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
|
||||||
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
|
||||||
@@ -349,6 +271,7 @@ export class SalesService {
|
|||||||
.getRawMany();
|
.getRawMany();
|
||||||
products = this.createListImages(products);
|
products = this.createListImages(products);
|
||||||
console.log(products.length + ' produtos');
|
console.log(products.length + ' produtos');
|
||||||
|
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
|
||||||
return products;
|
return products;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -357,7 +280,15 @@ export class SalesService {
|
|||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await connectionDb.close();
|
// Não fecha a conexão - reutilizada pelo pool
|
||||||
|
try {
|
||||||
|
const currentLockValue = await this.redisClient.get(lockKey);
|
||||||
|
if (currentLockValue === lockValue.toString()) {
|
||||||
|
await this.redisClient.del(lockKey);
|
||||||
|
}
|
||||||
|
} catch (lockErr) {
|
||||||
|
console.error('Erro ao liberar lock Redis (GetProducts2):', lockErr?.message || lockErr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1114,17 +1045,18 @@ export class SalesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createListImages(products: SalesProduct[]): SalesProduct[] {
|
createListImages(products: SalesProduct[]): SalesProduct[] {
|
||||||
products.forEach(product => {
|
for (let i = 0; i < products.length; i++) {
|
||||||
|
const product = products[i];
|
||||||
product.images = [];
|
product.images = [];
|
||||||
if (product.urlImage != null) {
|
if (product.urlImage != null && product.urlImage.length > 0) {
|
||||||
let urlImage = product.urlImage;
|
product.images = product.urlImage
|
||||||
if (urlImage.indexOf(";") == -1) {
|
.split(';')
|
||||||
urlImage += ";";
|
.map(img => img.trim())
|
||||||
}
|
.filter(img => img.length > 0);
|
||||||
const images = product.urlImage.split(";");
|
|
||||||
product.images = images.map(i => i.trim());
|
|
||||||
}
|
}
|
||||||
});
|
// Adiciona thumbnail para acesso rápido no frontend
|
||||||
|
(product as any).thumbnail = product.images.length > 0 ? product.images[0] : null;
|
||||||
|
}
|
||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1415,8 +1347,7 @@ export class SalesService {
|
|||||||
const skipReg = ((pageNumber - 1) * pageSize);
|
const skipReg = ((pageNumber - 1) * pageSize);
|
||||||
const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`;
|
const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`;
|
||||||
|
|
||||||
const connectionDb = new Connection(connectionOptions);
|
const connectionDb = getConnection();
|
||||||
await connectionDb.connect();
|
|
||||||
const queryRunner = connectionDb.createQueryRunner();
|
const queryRunner = connectionDb.createQueryRunner();
|
||||||
await queryRunner.connect();
|
await queryRunner.connect();
|
||||||
|
|
||||||
@@ -1425,7 +1356,7 @@ export class SalesService {
|
|||||||
products = this.createListImages(products);
|
products = this.createListImages(products);
|
||||||
console.log("Total de produtos: " + products.length);
|
console.log("Total de produtos: " + products.length);
|
||||||
|
|
||||||
await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 3600);
|
await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900);
|
||||||
|
|
||||||
return products;
|
return products;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1433,7 +1364,7 @@ export class SalesService {
|
|||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await connectionDb.close();
|
// Não fecha a conexão - reutilizada pelo pool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user