Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ private static (string? City, string? State) ExtractLocation(HttpContext context

private async Task<bool> IsLocationAllowedAsync(string? city, string? state, IGeographicValidationService? geographicValidationService, CancellationToken cancellationToken)
{
// Se não conseguiu detectar localização, permitir (fail-open)
// Mas se a string estiver vazia (Length == 0), significa que detectamos malformação ou header vazio
if (city?.Length == 0 || state?.Length == 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,19 @@ public void Configure(EntityTypeBuilder<Booking> builder)
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();

// Índice para busca de agendamentos por prestador e data
builder.HasIndex(b => new { b.ProviderId, b.Date, b.Status });

builder.HasIndex(b => b.ClientId);
// Índice composto para busca de agendamentos ativos por prestador, data e status
// Otimiza: GetActiveByProviderAndDateAsync (WHERE provider_id=X AND booking_date=X AND status=X)
builder.HasIndex(b => new { b.ProviderId, b.Date, b.Status })
.HasDatabaseName("ix_bookings_provider_date_status");

// Índice composto para paginação por cliente com ordenação por data
// Otimiza: GetByClientIdPagedAsync (WHERE client_id=X [date range] ORDER BY booking_date DESC)
builder.HasIndex(b => new { b.ClientId, b.Date })
.HasDatabaseName("ix_bookings_client_date");

// Índice composto para paginação por prestador com ordenação por data
// Otimiza: GetByProviderIdPagedAsync sem filtro de status (WHERE provider_id=X [date range] ORDER BY booking_date DESC)
builder.HasIndex(b => new { b.ProviderId, b.Date })
.HasDatabaseName("ix_bookings_provider_date");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public void Configure(EntityTypeBuilder<Provider> builder)
.HasForeignKey(ps => ps.ProviderId)
.OnDelete(DeleteBehavior.Cascade);

// Índices
// Índices simples
builder.HasIndex(p => p.UserId)
.IsUnique()
.HasDatabaseName("ix_providers_user_id");
Expand All @@ -270,5 +270,26 @@ public void Configure(EntityTypeBuilder<Provider> builder)

builder.HasIndex(p => p.IsDeleted)
.HasDatabaseName("ix_providers_is_deleted");

// Índices compostos para hot paths de listagem paginada
// Otimiza: WHERE !is_deleted ORDER BY created_at DESC, id DESC
builder.HasIndex(p => new { p.IsDeleted, p.CreatedAt })
.HasDatabaseName("ix_providers_deleted_created")
.HasFilter("is_deleted = false");

// Otimiza: WHERE !is_deleted AND status = X ORDER BY created_at DESC
builder.HasIndex(p => new { p.IsDeleted, p.Status, p.CreatedAt })
.HasDatabaseName("ix_providers_deleted_status_created")
.HasFilter("is_deleted = false");

// Otimiza: WHERE !is_deleted AND verification_status = X ORDER BY created_at DESC
builder.HasIndex(p => new { p.IsDeleted, p.VerificationStatus, p.CreatedAt })
.HasDatabaseName("ix_providers_deleted_verification_created")
.HasFilter("is_deleted = false");

// Otimiza: WHERE !is_deleted AND type = X ORDER BY created_at DESC
builder.HasIndex(p => new { p.IsDeleted, p.Type, p.CreatedAt })
.HasDatabaseName("ix_providers_deleted_type_created")
.HasFilter("is_deleted = false");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ public async Task InvokeAsync_WhenPathHasNoVersionNumber_ShouldNOTRecordBusiness
// Não deve registrar métricas específicas de negócio (user registration, login, help requests, etc)
// se o caminho não for reconhecido como versionado.
// Métricas de API (RecordApiCall) ainda são registradas, então verificamos as métricas de negócio específicas.
var businessMetrics = _longMeasurements.Where(m =>
var businessMetricsList = _longMeasurements.Where(m =>
{
var tagsArray = m.Tags.ToArray();
return tagsArray.Any(t => t.Key == "category" || t.Key == "type");
}).ToList();
businessMetrics.Should().BeEmpty();
businessMetricsList.Should().BeEmpty();
}

public void Dispose()
Expand Down
Loading