Refatora ProcessarMedicoesUseCase e ajusta dependências
Refatora o uso de HttpClient, removendo controle explícito de concorrência com SemaphoreSlim e RateLimiter, e adiciona suporte a certificados SSL com o método CreateHttpClient. Simplifica assinaturas de métodos e inicialização de dependências. Ajusta a lógica de comparação de medições para maior precisão com Math.Round. Atualiza consultas SQL em AccessRepository e PostgresRepository para melhorar legibilidade e remover filtros específicos. Altera o intervalo de datas no Program.cs e remove configurações de proxy e validação de certificado no HttpClient. Remove código legado e comentários desnecessários, melhorando a organização geral do código.
This commit is contained in:
parent
0db548b273
commit
9a91cc456f
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Domain;
|
using Domain;
|
||||||
@ -11,19 +12,13 @@ namespace Application
|
|||||||
{
|
{
|
||||||
private readonly IPostgresRepository _postgresRepository;
|
private readonly IPostgresRepository _postgresRepository;
|
||||||
private readonly IAccessRepository _accessRepository;
|
private readonly IAccessRepository _accessRepository;
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private readonly RateLimiter _rateLimiter;
|
|
||||||
|
|
||||||
public ProcessarMedicoesUseCase(
|
public ProcessarMedicoesUseCase(
|
||||||
IPostgresRepository postgresRepository,
|
IPostgresRepository postgresRepository,
|
||||||
IAccessRepository accessRepository,
|
IAccessRepository accessRepository)
|
||||||
HttpClient httpClient,
|
|
||||||
RateLimiter rateLimiter)
|
|
||||||
{
|
{
|
||||||
_postgresRepository = postgresRepository;
|
_postgresRepository = postgresRepository;
|
||||||
_accessRepository = accessRepository;
|
_accessRepository = accessRepository;
|
||||||
_httpClient = httpClient;
|
|
||||||
_rateLimiter = rateLimiter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ExecuteAsync(DateTime dataIni, DateTime dataFim, string caminhoLog, CancellationToken ct)
|
public async Task ExecuteAsync(DateTime dataIni, DateTime dataFim, string caminhoLog, CancellationToken ct)
|
||||||
@ -32,15 +27,9 @@ namespace Application
|
|||||||
var operacoesLog = new ConcurrentBag<string>();
|
var operacoesLog = new ConcurrentBag<string>();
|
||||||
var perfis = (await _accessRepository.ObterPerfisAsync(ct)).ToList();
|
var perfis = (await _accessRepository.ObterPerfisAsync(ct)).ToList();
|
||||||
|
|
||||||
_httpClient.DefaultRequestHeaders.Add("SOAPAction", "listarMedidaCincoMinutos");
|
|
||||||
var endpoint = new Uri("https://servicos.ccee.org.br/ws/v2/MedidaCincoMinutosBSv2");
|
var endpoint = new Uri("https://servicos.ccee.org.br/ws/v2/MedidaCincoMinutosBSv2");
|
||||||
var datas = Enumerable.Range(0, (dataFim - dataIni).Days).Select(i => dataIni.AddDays(i));
|
var datas = Enumerable.Range(0, (dataFim - dataIni).Days).Select(i => dataIni.AddDays(i));
|
||||||
|
|
||||||
// Controle explícito de concorrência HTTP (assíncrona)
|
|
||||||
// Ajuste conforme latência observada (ex.: 32, 48, 64).
|
|
||||||
var maxConcurrentRequests = 10;
|
|
||||||
using var httpSemaphore = new SemaphoreSlim(maxConcurrentRequests);
|
|
||||||
|
|
||||||
await Parallel.ForEachAsync(perfis, async (perfil, ctPerfil) =>
|
await Parallel.ForEachAsync(perfis, async (perfil, ctPerfil) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.Now}: Iniciado ponto {perfil.CodigoSCDE}");
|
Console.WriteLine($"{DateTime.Now}: Iniciado ponto {perfil.CodigoSCDE}");
|
||||||
@ -58,7 +47,7 @@ namespace Application
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ProcessarDiaAsync(perfil, dia, existentes, endpoint, errosPersistentes, operacoesLog, ctDia, httpSemaphore);
|
await ProcessarDiaAsync(perfil, dia, existentes, endpoint, errosPersistentes, operacoesLog, ctDia);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -110,8 +99,7 @@ namespace Application
|
|||||||
Uri endpoint,
|
Uri endpoint,
|
||||||
ConcurrentBag<string> errosPersistentes,
|
ConcurrentBag<string> errosPersistentes,
|
||||||
ConcurrentBag<string> operacoesLog,
|
ConcurrentBag<string> operacoesLog,
|
||||||
CancellationToken ct,
|
CancellationToken ct)
|
||||||
SemaphoreSlim httpSemaphore)
|
|
||||||
{
|
{
|
||||||
if (perfil.DataDeMigracao > dia)
|
if (perfil.DataDeMigracao > dia)
|
||||||
{
|
{
|
||||||
@ -129,21 +117,14 @@ namespace Application
|
|||||||
string payload = Xml_requisicao(dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, 1);
|
string payload = Xml_requisicao(dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, 1);
|
||||||
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
||||||
|
|
||||||
// SEGURAR O SEMÁFORO APENAS NA CHAMADA HTTP
|
|
||||||
await _rateLimiter.WaitAsync(ct);
|
|
||||||
|
|
||||||
HttpResponseMessage response;
|
HttpResponseMessage response;
|
||||||
string resposta;
|
string resposta;
|
||||||
await httpSemaphore.WaitAsync(ct);
|
|
||||||
try
|
using (var client = CreateHttpClient())
|
||||||
{
|
{
|
||||||
response = await _httpClient.PostAsync(endpoint, conteudo, ct);
|
response = await client.PostAsync(endpoint, conteudo, ct);
|
||||||
resposta = await response.Content.ReadAsStringAsync();
|
resposta = await response.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
httpSemaphore.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)response.StatusCode >= 400)
|
if ((int)response.StatusCode >= 400)
|
||||||
{
|
{
|
||||||
@ -171,7 +152,7 @@ namespace Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ProcessarXMLAsync(resposta, dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, existentes, ct, endpoint, httpSemaphore, 1, null, 1, operacoesLog);
|
await ProcessarXMLAsync(resposta, dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, existentes, ct, endpoint, 1, null, 1, operacoesLog);
|
||||||
sucesso = true;
|
sucesso = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -199,7 +180,6 @@ namespace Application
|
|||||||
IDictionary<(string, double, int), Medicao> existentes,
|
IDictionary<(string, double, int), Medicao> existentes,
|
||||||
CancellationToken ct,
|
CancellationToken ct,
|
||||||
Uri endpoint,
|
Uri endpoint,
|
||||||
SemaphoreSlim httpSemaphore,
|
|
||||||
int paginaAtual = 1,
|
int paginaAtual = 1,
|
||||||
List<XElement>? acumulador = null,
|
List<XElement>? acumulador = null,
|
||||||
int totalPaginas = 1,
|
int totalPaginas = 1,
|
||||||
@ -223,21 +203,15 @@ namespace Application
|
|||||||
string payload = Xml_requisicao(dia, perfil, ponto, paginaAtual + 1);
|
string payload = Xml_requisicao(dia, perfil, ponto, paginaAtual + 1);
|
||||||
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
||||||
|
|
||||||
await _rateLimiter.WaitAsync(ct);
|
|
||||||
|
|
||||||
string proxXml;
|
string proxXml;
|
||||||
await httpSemaphore.WaitAsync(ct);
|
|
||||||
try
|
using (var client = CreateHttpClient())
|
||||||
{
|
{
|
||||||
using var resp = await _httpClient.PostAsync(endpoint, conteudo, ct);
|
using var resp = await client.PostAsync(endpoint, conteudo, ct);
|
||||||
proxXml = await resp.Content.ReadAsStringAsync();
|
proxXml = await resp.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
httpSemaphore.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
await ProcessarXMLAsync(proxXml, dia, perfil, ponto, existentes, ct, endpoint, httpSemaphore, paginaAtual + 1, acumulador, totalPaginas, operacoesLog);
|
await ProcessarXMLAsync(proxXml, dia, perfil, ponto, existentes, ct, endpoint, paginaAtual + 1, acumulador, totalPaginas, operacoesLog);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,10 +338,10 @@ namespace Application
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (existente.Origem != m.Origem ||
|
if (existente.Origem != m.Origem ||
|
||||||
existente.AtivaConsumo != m.AtivaConsumo ||
|
Math.Round(existente.AtivaConsumo ?? 0, 10) != Math.Round(m.AtivaConsumo ?? 0, 10) ||
|
||||||
existente.AtivaGeracao != m.AtivaGeracao ||
|
Math.Round(existente.AtivaGeracao ?? 0, 10) != Math.Round(m.AtivaGeracao ?? 0, 10) ||
|
||||||
existente.ReativaConsumo != m.ReativaConsumo ||
|
Math.Round(existente.ReativaConsumo ?? 0, 10) != Math.Round(m.ReativaConsumo ?? 0, 10) ||
|
||||||
existente.ReativaGeracao != m.ReativaGeracao)
|
Math.Round(existente.ReativaGeracao ?? 0, 10) != Math.Round(m.ReativaGeracao ?? 0, 10))
|
||||||
{
|
{
|
||||||
alterados.Add(m);
|
alterados.Add(m);
|
||||||
}
|
}
|
||||||
@ -407,5 +381,18 @@ namespace Application
|
|||||||
tex_req = tex_req.Replace("PAGNUM", pagina.ToString());
|
tex_req = tex_req.Replace("PAGNUM", pagina.ToString());
|
||||||
return tex_req;
|
return tex_req;
|
||||||
}
|
}
|
||||||
|
private static HttpClient CreateHttpClient()
|
||||||
|
{
|
||||||
|
// Configura o HttpClientHandler para ignorar erros SSL
|
||||||
|
var handler = new HttpClientHandler
|
||||||
|
{
|
||||||
|
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adiciona o certificado SSL
|
||||||
|
handler.ClientCertificates.Add(new X509Certificate2(@"X:\Back\APP Smart\Certificado\cert_ssl.pfx", "appsmart"));
|
||||||
|
|
||||||
|
return new HttpClient(handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,11 +19,11 @@ namespace Infrastructure
|
|||||||
using var connection = new OleDbConnection(_connectionString);
|
using var connection = new OleDbConnection(_connectionString);
|
||||||
await connection.OpenAsync(ct);
|
await connection.OpenAsync(ct);
|
||||||
|
|
||||||
//string sql = $"SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 AND Unidade_gerenciada ORDER BY cod_smart_unidade";
|
string sql = $"SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 AND Unidade_gerenciada ORDER BY cod_smart_unidade";
|
||||||
string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and (Cliente = 'RMC ALIMENTOS' OR Cliente = 'FERREIRA SUPERMERCADO' OR Cliente = 'VANGUARDA ALIMENTOS') AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and (Cliente = 'RMC ALIMENTOS' OR Cliente = 'FERREIRA SUPERMERCADO' OR Cliente = 'VANGUARDA ALIMENTOS') AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'ABEVÊ' and Unidade = 'ABV LOJA 29 - COXIM' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'ABEVÊ' and Unidade = 'ABV LOJA 29 - COXIM' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'RMC ALIMENTOS' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'RMC ALIMENTOS' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Codigo_SCDE = '3016021620'";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Codigo_SCDE = 'MTTMAUENTR101'";
|
||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
using var reader = await command.ExecuteReaderAsync(ct);
|
using var reader = await command.ExecuteReaderAsync(ct);
|
||||||
|
|||||||
@ -16,21 +16,13 @@ class Program
|
|||||||
//DateTime dataIni = new DateTime(inicio.Year, inicio.Month, 1);
|
//DateTime dataIni = new DateTime(inicio.Year, inicio.Month, 1);
|
||||||
//DateTime dataFim = new DateTime(inicio.Year, inicio.Month, inicio.Day);
|
//DateTime dataFim = new DateTime(inicio.Year, inicio.Month, inicio.Day);
|
||||||
DateTime dataIni = new DateTime(inicio.Year, 10, 01);
|
DateTime dataIni = new DateTime(inicio.Year, 10, 01);
|
||||||
DateTime dataFim = new DateTime(inicio.Year, 10, 23);
|
DateTime dataFim = new DateTime(inicio.Year, 10, 28);
|
||||||
|
|
||||||
// Configuração de dependências (pode usar um container DI depois)
|
// Configuração de dependências (pode usar um container DI depois)
|
||||||
var postgresRepo = new PostgresRepository(PG_CONN_STRING_PROD);
|
var postgresRepo = new PostgresRepository(PG_CONN_STRING_PROD);
|
||||||
var accessRepo = new AccessRepository(ACCESS_CONN_STRING);
|
var accessRepo = new AccessRepository(ACCESS_CONN_STRING);
|
||||||
var httpClient = new HttpClient(new HttpClientHandler
|
|
||||||
{
|
|
||||||
ClientCertificateOptions = ClientCertificateOption.Automatic,
|
|
||||||
Proxy = new WebProxy("127.0.0.1", 8888),
|
|
||||||
UseProxy = true,
|
|
||||||
ServerCertificateCustomValidationCallback = (HttpRequestMessage req, X509Certificate2? cert, X509Chain? chain, SslPolicyErrors errors) => true
|
|
||||||
});
|
|
||||||
|
|
||||||
var rateLimiter = new RateLimiter(12, TimeSpan.FromSeconds(1));
|
var useCase = new ProcessarMedicoesUseCase(postgresRepo, accessRepo);
|
||||||
var useCase = new ProcessarMedicoesUseCase(postgresRepo, accessRepo, httpClient, rateLimiter);
|
|
||||||
|
|
||||||
await useCase.ExecuteAsync(dataIni, dataFim, caminhoLog, CancellationToken.None);
|
await useCase.ExecuteAsync(dataIni, dataFim, caminhoLog, CancellationToken.None);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user