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.Globalization;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Domain;
|
||||
@ -11,19 +12,13 @@ namespace Application
|
||||
{
|
||||
private readonly IPostgresRepository _postgresRepository;
|
||||
private readonly IAccessRepository _accessRepository;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly RateLimiter _rateLimiter;
|
||||
|
||||
public ProcessarMedicoesUseCase(
|
||||
IPostgresRepository postgresRepository,
|
||||
IAccessRepository accessRepository,
|
||||
HttpClient httpClient,
|
||||
RateLimiter rateLimiter)
|
||||
IAccessRepository accessRepository)
|
||||
{
|
||||
_postgresRepository = postgresRepository;
|
||||
_accessRepository = accessRepository;
|
||||
_httpClient = httpClient;
|
||||
_rateLimiter = rateLimiter;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(DateTime dataIni, DateTime dataFim, string caminhoLog, CancellationToken ct)
|
||||
@ -32,15 +27,9 @@ namespace Application
|
||||
var operacoesLog = new ConcurrentBag<string>();
|
||||
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 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) =>
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now}: Iniciado ponto {perfil.CodigoSCDE}");
|
||||
@ -58,7 +47,7 @@ namespace Application
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProcessarDiaAsync(perfil, dia, existentes, endpoint, errosPersistentes, operacoesLog, ctDia, httpSemaphore);
|
||||
await ProcessarDiaAsync(perfil, dia, existentes, endpoint, errosPersistentes, operacoesLog, ctDia);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -110,8 +99,7 @@ namespace Application
|
||||
Uri endpoint,
|
||||
ConcurrentBag<string> errosPersistentes,
|
||||
ConcurrentBag<string> operacoesLog,
|
||||
CancellationToken ct,
|
||||
SemaphoreSlim httpSemaphore)
|
||||
CancellationToken ct)
|
||||
{
|
||||
if (perfil.DataDeMigracao > dia)
|
||||
{
|
||||
@ -129,21 +117,14 @@ namespace Application
|
||||
string payload = Xml_requisicao(dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, 1);
|
||||
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
||||
|
||||
// SEGURAR O SEMÁFORO APENAS NA CHAMADA HTTP
|
||||
await _rateLimiter.WaitAsync(ct);
|
||||
|
||||
HttpResponseMessage response;
|
||||
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();
|
||||
}
|
||||
finally
|
||||
{
|
||||
httpSemaphore.Release();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -199,7 +180,6 @@ namespace Application
|
||||
IDictionary<(string, double, int), Medicao> existentes,
|
||||
CancellationToken ct,
|
||||
Uri endpoint,
|
||||
SemaphoreSlim httpSemaphore,
|
||||
int paginaAtual = 1,
|
||||
List<XElement>? acumulador = null,
|
||||
int totalPaginas = 1,
|
||||
@ -223,21 +203,15 @@ namespace Application
|
||||
string payload = Xml_requisicao(dia, perfil, ponto, paginaAtual + 1);
|
||||
var conteudo = new StringContent(payload, Encoding.UTF8, "application/xml");
|
||||
|
||||
await _rateLimiter.WaitAsync(ct);
|
||||
|
||||
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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -364,10 +338,10 @@ namespace Application
|
||||
else
|
||||
{
|
||||
if (existente.Origem != m.Origem ||
|
||||
existente.AtivaConsumo != m.AtivaConsumo ||
|
||||
existente.AtivaGeracao != m.AtivaGeracao ||
|
||||
existente.ReativaConsumo != m.ReativaConsumo ||
|
||||
existente.ReativaGeracao != m.ReativaGeracao)
|
||||
Math.Round(existente.AtivaConsumo ?? 0, 10) != Math.Round(m.AtivaConsumo ?? 0, 10) ||
|
||||
Math.Round(existente.AtivaGeracao ?? 0, 10) != Math.Round(m.AtivaGeracao ?? 0, 10) ||
|
||||
Math.Round(existente.ReativaConsumo ?? 0, 10) != Math.Round(m.ReativaConsumo ?? 0, 10) ||
|
||||
Math.Round(existente.ReativaGeracao ?? 0, 10) != Math.Round(m.ReativaGeracao ?? 0, 10))
|
||||
{
|
||||
alterados.Add(m);
|
||||
}
|
||||
@ -407,5 +381,18 @@ namespace Application
|
||||
tex_req = tex_req.Replace("PAGNUM", pagina.ToString());
|
||||
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);
|
||||
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 (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 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 = '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 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 reader = await command.ExecuteReaderAsync(ct);
|
||||
|
||||
@ -16,21 +16,13 @@ class Program
|
||||
//DateTime dataIni = new DateTime(inicio.Year, inicio.Month, 1);
|
||||
//DateTime dataFim = new DateTime(inicio.Year, inicio.Month, inicio.Day);
|
||||
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)
|
||||
var postgresRepo = new PostgresRepository(PG_CONN_STRING_PROD);
|
||||
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, httpClient, rateLimiter);
|
||||
var useCase = new ProcessarMedicoesUseCase(postgresRepo, accessRepo);
|
||||
|
||||
await useCase.ExecuteAsync(dataIni, dataFim, caminhoLog, CancellationToken.None);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user