diff --git a/src/Altinn.Auth.AuditLog/AuditLogHost.cs b/src/Altinn.Auth.AuditLog/AuditLogHost.cs index 71a6578..60c6379 100644 --- a/src/Altinn.Auth.AuditLog/AuditLogHost.cs +++ b/src/Altinn.Auth.AuditLog/AuditLogHost.cs @@ -32,7 +32,7 @@ public static WebApplication Create(string[] args) services.Configure(config.GetSection("kvSetting")); builder.AddAuditLogPersistence(); builder.Services.AddSingleton(); - //builder.Services.AddHostedService(sp => sp.GetRequiredService()); + builder.Services.AddHostedService(sp => sp.GetRequiredService()); services.AddSingleton(); services.AddSingleton(); services.Configure(config.GetSection("PostgreSQLSettings")); diff --git a/src/Altinn.Auth.AuditLog/Services/PartitionCreationHostedService.cs b/src/Altinn.Auth.AuditLog/Services/PartitionCreationHostedService.cs index e81544f..3645a34 100644 --- a/src/Altinn.Auth.AuditLog/Services/PartitionCreationHostedService.cs +++ b/src/Altinn.Auth.AuditLog/Services/PartitionCreationHostedService.cs @@ -91,7 +91,7 @@ private void CreateMonthlyPartitionFromTimer() newJob = Task.Run(async () => { var token = _stoppingCts!.Token; - + try { await CreateMonthlyPartition(token); @@ -123,6 +123,13 @@ private void CreateMonthlyPartitionFromTimer() } private async Task CreateMonthlyPartition(CancellationToken cancellationToken) + { + var partitions = GetPartitionsForCurrentAndAdjacentMonths(); + + await _partitionManagerRepository.CreatePartitions(partitions, cancellationToken); + } + + internal IReadOnlyList GetPartitionsForCurrentAndAdjacentMonths() { string authenticationSchemaName = "authentication"; string authzSchemaName = "authz"; @@ -130,14 +137,10 @@ private async Task CreateMonthlyPartition(CancellationToken cancellationToken) // Get current dateonly var now = DateOnly.FromDateTime(_timeProvider.GetUtcNow().UtcDateTime); - // Define the date ranges for the past, current and next month partitions - var currentMonthStartDate = now; - var currentMonthEndDate = currentMonthStartDate.AddMonths(1); - DateOnly pastMonthStartDate = now.AddMonths(-1); - DateOnly pastMonthEndDate = now; - DateOnly nextMonthStartDate = now.AddMonths(1); - DateOnly nextMonthEndDate = nextMonthStartDate.AddMonths(1); + var (currentMonthStartDate, currentMonthEndDate) = GetMonthStartAndEndDate(now); + var (pastMonthStartDate, pastMonthEndDate) = GetMonthStartAndEndDate(now.AddMonths(-1)); + var (nextMonthStartDate, nextMonthEndDate) = GetMonthStartAndEndDate(now.AddMonths(1)); // Create partition names var pastMonthPartitionName = $"eventlogv1_y{pastMonthStartDate.Year}m{pastMonthStartDate.Month:D2}"; @@ -145,16 +148,22 @@ private async Task CreateMonthlyPartition(CancellationToken cancellationToken) var nextMonthPartitionName = $"eventlogv1_y{nextMonthStartDate.Year}m{nextMonthStartDate.Month:D2}"; // List of partitions for both schemas - IReadOnlyList partitions = [ + return new List + { new Partition { SchemaName = authenticationSchemaName, Name = pastMonthPartitionName, StartDate = pastMonthStartDate, EndDate = pastMonthEndDate }, new Partition { SchemaName = authenticationSchemaName, Name = currentMonthPartitionName, StartDate = currentMonthStartDate, EndDate = currentMonthEndDate }, new Partition { SchemaName = authenticationSchemaName, Name = nextMonthPartitionName, StartDate = nextMonthStartDate, EndDate = nextMonthEndDate }, new Partition { SchemaName = authzSchemaName, Name = pastMonthPartitionName, StartDate = pastMonthStartDate, EndDate = pastMonthEndDate }, new Partition { SchemaName = authzSchemaName, Name = currentMonthPartitionName, StartDate = currentMonthStartDate, EndDate = currentMonthEndDate }, new Partition { SchemaName = authzSchemaName, Name = nextMonthPartitionName, StartDate = nextMonthStartDate, EndDate = nextMonthEndDate } - ]; + }; + } - await _partitionManagerRepository.CreatePartitions(partitions, cancellationToken); + internal (DateOnly startDate, DateOnly endDate) GetMonthStartAndEndDate(DateOnly date) + { + DateOnly startDate = new DateOnly(date.Year, date.Month, 1); + DateOnly endDate = startDate.AddMonths(1).AddDays(-1); + return (startDate, endDate); } } } diff --git a/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthenticationEventControllerTest.cs b/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthenticationEventControllerTest.cs index 46c31a8..240283c 100644 --- a/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthenticationEventControllerTest.cs +++ b/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthenticationEventControllerTest.cs @@ -23,7 +23,7 @@ private HttpClient CreateEventClient() return client; } - [Fact(Skip = "Ignored")] + [Fact] public async Task CreateAuthenticationEvent_Ok() { using var client = CreateEventClient(); diff --git a/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthorizationEventControllerTest.cs b/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthorizationEventControllerTest.cs index e2e5b45..3428248 100644 --- a/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthorizationEventControllerTest.cs +++ b/test/Altinn.Auth.AuditLog.Tests/Controllers/AuthorizationEventControllerTest.cs @@ -24,7 +24,7 @@ private HttpClient CreateEventClient() return client; } - [Fact(Skip = "Ignored")] + [Fact] public async Task CreateAuthorizationEvent_Ok() { using var client = CreateEventClient(); diff --git a/test/Altinn.Auth.AuditLog.Tests/PartitionCreationHostewdServiceIntegrationTests.cs b/test/Altinn.Auth.AuditLog.Tests/Integration/PartitionCreationHostedServiceIntegrationTests.cs similarity index 97% rename from test/Altinn.Auth.AuditLog.Tests/PartitionCreationHostewdServiceIntegrationTests.cs rename to test/Altinn.Auth.AuditLog.Tests/Integration/PartitionCreationHostedServiceIntegrationTests.cs index 360b2df..ffa9805 100644 --- a/test/Altinn.Auth.AuditLog.Tests/PartitionCreationHostewdServiceIntegrationTests.cs +++ b/test/Altinn.Auth.AuditLog.Tests/Integration/PartitionCreationHostedServiceIntegrationTests.cs @@ -16,7 +16,7 @@ using Testcontainers.PostgreSql; using static System.Net.Mime.MediaTypeNames; -namespace Altinn.Auth.AuditLog.Tests; +namespace Altinn.Auth.AuditLog.Tests.Integration; public class PartitionCreationHostedServiceIntegrationTests(DbFixture dbFixture, WebApplicationFixture webApplicationFixture) : WebApplicationTests(dbFixture, webApplicationFixture) @@ -29,7 +29,7 @@ protected Task WaitForPartitionJob() return HostedService.RunningJob; } - [Fact(Skip = "Ignored")] + [Fact] public async Task ExecuteAsync_CreatesCurrentMonthPartition_OnlyOnce() { TimeProvider.Advance(TimeSpan.FromDays(1) + TimeSpan.FromHours(1)); diff --git a/test/Altinn.Auth.AuditLog.Tests/PartitionCreationHosterServiceTests.cs b/test/Altinn.Auth.AuditLog.Tests/PartitionCreationHosterServiceTests.cs new file mode 100644 index 0000000..934da50 --- /dev/null +++ b/test/Altinn.Auth.AuditLog.Tests/PartitionCreationHosterServiceTests.cs @@ -0,0 +1,62 @@ +using Altinn.Auth.AuditLog.Core.Models; +using Altinn.Auth.AuditLog.Services; +using Microsoft.Extensions.Time.Testing; +using System; +using System.Collections.Generic; +using Xunit; + +namespace Altinn.Auth.AuditLog.Tests; +public class PartitionCreationHostedServiceTests +{ + [Fact] + public void GetPartitionsForCurrentAndAdjacentMonths_ReturnsCorrectPartitions() + { + // Arrange + var timeProvider = new FakeTimeProvider(new DateTime(2023, 10, 15)); + var service = new PartitionCreationHostedService(null, null, timeProvider); + + // Act + var partitions = service.GetPartitionsForCurrentAndAdjacentMonths(); + + // Assert + Assert.Equal(6, partitions.Count); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2023m09" && p.StartDate == new DateOnly(2023, 9, 1) && p.EndDate == new DateOnly(2023, 9, 30)); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2023m10" && p.StartDate == new DateOnly(2023, 10, 1) && p.EndDate == new DateOnly(2023, 10, 31)); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2023m11" && p.StartDate == new DateOnly(2023, 11, 1) && p.EndDate == new DateOnly(2023, 11, 30)); + } + + [Theory] + [InlineData(2023, 10, 15, 2023, 10, 1, 2023, 10, 31)] + [InlineData(2023, 2, 1, 2023, 2, 1, 2023, 2, 28)] + [InlineData(2024, 2, 1, 2024, 2, 1, 2024, 2, 29)] // Leap year + public void GetMonthStartAndEndDate_ReturnsCorrectDates(int year, int month, int day, int expectedStartYear, int expectedStartMonth, int expectedStartDay, int expectedEndYear, int expectedEndMonth, int expectedEndDay) + { + // Arrange + var service = new PartitionCreationHostedService(null, null, null); + var date = new DateOnly(year, month, day); + + // Act + var (startDate, endDate) = service.GetMonthStartAndEndDate(date); + + // Assert + Assert.Equal(new DateOnly(expectedStartYear, expectedStartMonth, expectedStartDay), startDate); + Assert.Equal(new DateOnly(expectedEndYear, expectedEndMonth, expectedEndDay), endDate); + } + + [Fact] + public void GetPartitionsForCurrentAndAdjacentMonths_CrossYearBoundary_ReturnsCorrectPartitions() + { + // Arrange + var timeProvider = new FakeTimeProvider(new DateTime(2023, 12, 15)); + var service = new PartitionCreationHostedService(null, null, timeProvider); + + // Act + var partitions = service.GetPartitionsForCurrentAndAdjacentMonths(); + + // Assert + Assert.Equal(6, partitions.Count); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2023m11" && p.StartDate == new DateOnly(2023, 11, 1) && p.EndDate == new DateOnly(2023, 11, 30)); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2023m12" && p.StartDate == new DateOnly(2023, 12, 1) && p.EndDate == new DateOnly(2023, 12, 31)); + Assert.Contains(partitions, p => p.Name == "eventlogv1_y2024m01" && p.StartDate == new DateOnly(2024, 1, 1) && p.EndDate == new DateOnly(2024, 1, 31)); + } +}