diff --git a/docker-compose.yml b/docker-compose.yml index 9c5b59f..b3dde43 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,47 @@ services: start_period: 30s restart: unless-stopped + # --------------------------------------------------------------------------- + # Inicialização do banco — roda os scripts SQL na ordem correta e encerra + # --------------------------------------------------------------------------- + db-init: + image: mcr.microsoft.com/mssql/server:2022-latest + depends_on: + sqlserver: + condition: service_healthy + environment: + SA_PASSWORD: "${SA_PASSWORD:-DataPulseCM@2024!}" + volumes: + - ./database/scripts:/scripts:ro + user: root + entrypoint: + - /bin/bash + - -c + - | + set -e + SQLCMD=/opt/mssql-tools18/bin/sqlcmd + SERVER="sqlserver,1433" + PASS="$$SA_PASSWORD" + + echo ">>> Criando banco DataPulseCM..." + $$SQLCMD -S $$SERVER -U sa -P "$$PASS" -No \ + -Q "IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'DataPulseCM') CREATE DATABASE [DataPulseCM]" + + echo ">>> 01 - Criando tabelas..." + $$SQLCMD -S $$SERVER -U sa -P "$$PASS" -d DataPulseCM -No -i /scripts/01-create-tables.sql + + echo ">>> 02 - Criando stored procedures..." + $$SQLCMD -S $$SERVER -U sa -P "$$PASS" -d DataPulseCM -No -i /scripts/02-create-stored-procedures.sql + + echo ">>> 03 - Inserindo dados de exemplo..." + $$SQLCMD -S $$SERVER -U sa -P "$$PASS" -d DataPulseCM -No -i /scripts/03-seed-data.sql + + echo ">>> 04 - Enriquecendo campos de log..." + $$SQLCMD -S $$SERVER -U sa -P "$$PASS" -d DataPulseCM -No -i /scripts/04-enrich-log-fields.sql + + echo ">>> Banco inicializado com sucesso!" + restart: "no" + # --------------------------------------------------------------------------- # API .NET 9 # --------------------------------------------------------------------------- @@ -36,6 +77,8 @@ services: depends_on: sqlserver: condition: service_healthy + db-init: + condition: service_completed_successfully volumes: - api_logs:/app/logs restart: unless-stopped diff --git a/src/EtlMonitoring.Api/Program.cs b/src/EtlMonitoring.Api/Program.cs index 819b727..6ecf7b8 100644 --- a/src/EtlMonitoring.Api/Program.cs +++ b/src/EtlMonitoring.Api/Program.cs @@ -48,7 +48,7 @@ builder.Services.AddFluentValidationAutoValidation(); builder.Services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); - // Exception Handler + // Exception Handler (registro opcional + middleware explicito no pipeline) builder.Services.AddExceptionHandler(); builder.Services.AddProblemDetails(); @@ -92,13 +92,15 @@ throw new InvalidOperationException("Connection string 'DefaultConnection' não encontrada."); } -builder.Services.AddScoped( - provider => new JobExecutionRepository(connectionString) -); +// Registrar fábrica de conexão e repositório via DI +builder.Services.AddTransient>(provider => + () => new Microsoft.Data.SqlClient.SqlConnection(connectionString)); + +builder.Services.AddScoped(); var app = builder.Build(); -// Adicionar Exception Handler no pipeline +// Adicionar Exception Handler no pipeline (usa implementação registrada via AddExceptionHandler) app.UseExceptionHandler(); // Configurar pipeline HTTP diff --git a/src/EtlMonitoring.Infrastructure/Repositories/JobExecutionRepository.cs b/src/EtlMonitoring.Infrastructure/Repositories/JobExecutionRepository.cs index c7612d7..a7ada16 100644 --- a/src/EtlMonitoring.Infrastructure/Repositories/JobExecutionRepository.cs +++ b/src/EtlMonitoring.Infrastructure/Repositories/JobExecutionRepository.cs @@ -8,16 +8,16 @@ namespace EtlMonitoring.Infrastructure.Repositories { public class JobExecutionRepository : IJobExecutionRepository { - private readonly string _connectionString; + private readonly System.Func _connectionFactory; - public JobExecutionRepository(string connectionString) + public JobExecutionRepository(System.Func connectionFactory) { - _connectionString = connectionString; + _connectionFactory = connectionFactory; } public async Task CreateJobExecutionAsync(string jobName) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var parameters = new DynamicParameters(); parameters.Add("@JobName", jobName); @@ -34,7 +34,7 @@ await connection.ExecuteAsync( public async Task UpdateJobExecutionAsync(long executionId, string status, string? errorMessage = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var parameters = new DynamicParameters(); parameters.Add("@ExecutionId", executionId); @@ -50,7 +50,7 @@ await connection.ExecuteAsync( public async Task> GetJobExecutionsAsync(JobExecutionFiltrosDto filtros) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var parameters = new DynamicParameters(); parameters.Add("@JobName", filtros.JobName); @@ -70,7 +70,7 @@ public async Task> GetJobExecutionsAsync(JobExecutionFilt public async Task GetJobExecutionByIdAsync(long executionId) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT @@ -113,7 +113,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task> GetRecentExecutionsAsync(int limit = 50) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var result = await connection.QueryAsync( "usp_ETL_GetRecentExecutions", @@ -126,7 +126,7 @@ public async Task> GetRecentExecutionsAsync(int limit public async Task GetTotalExecutionsAsync(DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT COUNT(*) @@ -140,7 +140,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task GetSuccessfulExecutionsAsync(DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT COUNT(*) @@ -155,7 +155,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task GetFailedExecutionsAsync(DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT COUNT(*) @@ -170,7 +170,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task GetSuccessRateAsync(DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT @@ -188,7 +188,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task> GetFailedExecutionsAsync(int limit = 20) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT TOP (@Limit) @@ -216,7 +216,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task> GetExecutionsByStatusAsync(DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT Status, COUNT(*) AS Count @@ -231,7 +231,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task GetLastExecutionByJobNameAsync(string jobName) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT TOP 1 @@ -259,7 +259,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task> GetExecutionHistoryByJobNameAsync(string jobName, int limit = 50) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT TOP (@Limit) @@ -287,7 +287,7 @@ FROM [dbo].[ETL_JobExecutionLog] public async Task GetJobSuccessRateAsync(string jobName, DateTime? startDate = null, DateTime? endDate = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT @@ -307,7 +307,7 @@ FROM [dbo].[ETL_JobExecutionLog] // Job Execution Details (Steps) public async Task CreateJobExecutionDetailAsync(long executionId, string stepName, int stepOrder, string? stepMessage = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" INSERT INTO [dbo].[ETL_JobExecutionDetails] @@ -329,7 +329,7 @@ INSERT INTO [dbo].[ETL_JobExecutionDetails] public async Task UpdateJobExecutionDetailAsync(long detailId, string stepStatus, string? stepMessage = null) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" UPDATE [dbo].[ETL_JobExecutionDetails] @@ -349,7 +349,7 @@ UPDATE [dbo].[ETL_JobExecutionDetails] public async Task> GetExecutionDetailsByExecutionIdAsync(long executionId) { - using var connection = new SqlConnection(_connectionString); + using var connection = _connectionFactory(); var sql = @" SELECT