Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add SubjectResource entity and db migration #1048

Merged
merged 27 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
54520c3
Add SubjectResource entity and db migration
elsand Aug 24, 2024
8a51085
Add function skeleton
elsand Aug 24, 2024
a7867bb
wip
elsand Aug 26, 2024
29f931e
wip
elsand Aug 26, 2024
28782db
wip
elsand Aug 26, 2024
e66417d
Add Janitor console project
elsand Aug 30, 2024
6ee7243
Re-add localdev decorators, add note about FusionCache without Redis/…
elsand Aug 30, 2024
734f44c
Remove vscode extension recommendation for azure functions
elsand Aug 30, 2024
b4e9470
Merge branch 'main' into feat/resourcesubject-mappings-sync
elsand Aug 30, 2024
26b8a21
Suggestions to Bjørn (#1069)
MagnusSandgren Sep 1, 2024
a2209f4
feat(janitor): add deployment and dockerfile (#1064)
arealmaas Sep 1, 2024
1d223d9
Update README
elsand Sep 1, 2024
d3fba0f
fix: rename to new name for job
arealmaas Sep 2, 2024
3244474
Bypass EF, use npgsql directly, implement streaming/iasyncenumerator,…
elsand Sep 2, 2024
77da7b6
Rename command to synchronize-subject-resource-mappings
elsand Sep 2, 2024
a8805f5
Use dashed command name
elsand Sep 2, 2024
7366a2e
Rename to sync-subject-resource-mappings
elsand Sep 2, 2024
890ce77
change name of job
arealmaas Sep 3, 2024
484731d
naming suggestions
arealmaas Sep 3, 2024
6163b70
Some suggestions to Bjørn (#1077)
MagnusSandgren Sep 4, 2024
67881a7
suggestion: Add transaction to entire subject-resource sync command (…
MagnusSandgren Sep 4, 2024
31d110c
Remove last updated entity, minor clean ups
elsand Sep 4, 2024
17d6544
Merge branch 'main' into feat/resourcesubject-mappings-sync
elsand Sep 4, 2024
9c7c9d1
Use microseconds instead of ticks
elsand Sep 4, 2024
3841704
Add dispose method to UnitOfWork.cs
MagnusSandgren Sep 4, 2024
d5384e7
Merge branch 'main' into feat/resourcesubject-mappings-sync
elsand Sep 4, 2024
36d2446
Update src/Digdir.Domain.Dialogporten.Janitor/Commands.cs
elsand Sep 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Digdir.Domain.Dialogporten.sln
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Domain.Dialogporten.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Domain.Dialogporten.GraphQl.Unit.Tests", "tests\Digdir.Domain.Dialogporten.GraphQl.Unit.Tests\Digdir.Domain.Dialogporten.GraphQl.Unit.Tests.csproj", "{AF35FFCA-1206-4C08-A003-DA4A1344CCD5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Domain.Dialogporten.Janitor", "src\Digdir.Domain.Dialogporten.Janitor\Digdir.Domain.Dialogporten.Janitor.csproj", "{0900E3CF-F9D8-4B29-957F-484B3B028D6D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -141,6 +143,10 @@ Global
{AF35FFCA-1206-4C08-A003-DA4A1344CCD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF35FFCA-1206-4C08-A003-DA4A1344CCD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF35FFCA-1206-4C08-A003-DA4A1344CCD5}.Release|Any CPU.Build.0 = Release|Any CPU
{0900E3CF-F9D8-4B29-957F-484B3B028D6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0900E3CF-F9D8-4B29-957F-484B3B028D6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0900E3CF-F9D8-4B29-957F-484B3B028D6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0900E3CF-F9D8-4B29-957F-484B3B028D6D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -168,6 +174,7 @@ Global
{234FE24D-1047-4E29-A625-1EB406C37A2D} = {320B47A0-5EB8-4B6E-8C84-90633A1849CA}
{1EF1AE42-17F1-4761-ACFE-DF8E8A9B9429} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{AF35FFCA-1206-4C08-A003-DA4A1344CCD5} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{0900E3CF-F9D8-4B29-957F-484B3B028D6D} = {320B47A0-5EB8-4B6E-8C84-90633A1849CA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B2FE67FF-7622-4AFB-AD8E-961B6A39D888}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents;
using Digdir.Domain.Dialogporten.Domain.SubjectResources;

namespace Digdir.Domain.Dialogporten.Application.Externals;

Expand Down Expand Up @@ -40,6 +41,8 @@ public interface IDialogDbContext

DbSet<OutboxMessage> OutboxMessages { get; }
DbSet<OutboxMessageConsumer> OutboxMessageConsumers { get; }
DbSet<SubjectResource> SubjectResources { get; }
DbSet<SubjectResourceLastUpdate> SubjectResourceLastUpdates { get; }

/// <summary>
/// Validate a property on the <typeparamref name="TEntity"/> using a lambda
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public interface IResourceRegistry
{
Task<IReadOnlyCollection<ServiceResourceInformation>> GetResourceInformationForOrg(string orgNumber, CancellationToken cancellationToken);
Task<ServiceResourceInformation?> GetResourceInformation(string serviceResourceId, CancellationToken cancellationToken);
Task<List<UpdatedSubjectResource>> GetUpdatedSubjectResources(DateTimeOffset since, CancellationToken cancellationToken);
}

public sealed record ServiceResourceInformation
Expand All @@ -19,3 +20,11 @@ public ServiceResourceInformation(string resourceId, string resourceType, string
OwnerOrgNumber = ownerOrgNumber.ToLowerInvariant();
}
}

public sealed record UpdatedSubjectResource
{
public Uri Subject { get; set; } = null!;
public Uri Resource { get; set; } = null!;
public DateTimeOffset UpdatedAt { get; set; }
public bool Deleted { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Digdir.Library.Entity.Abstractions;
using Digdir.Library.Entity.Abstractions.Features.Updatable;

namespace Digdir.Domain.Dialogporten.Domain.SubjectResources;

public class SubjectResource : IEntity
{
public Guid Id { get; set; }
public string Subject { get; set; } = null!;
public string Resource { get; set; } = null!;
public DateTimeOffset UpdatedAt { get; set; }
public DateTimeOffset CreatedAt { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Digdir.Library.Entity.Abstractions.Features.Identifiable;

namespace Digdir.Domain.Dialogporten.Domain.SubjectResources;

public class SubjectResourceLastUpdate : IIdentifiableEntity
{
public Guid Id { get; set; }
public DateTimeOffset LastUpdate { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public async Task<IReadOnlyCollection<ServiceResourceInformation>> GetResourceIn
new ServiceResourceInformation(serviceResourceId, LocalResourceType, LocalOrgId));
}

#pragma warning disable CA1822
public async Task<List<UpdatedSubjectResource>> GetUpdatedSubjectResources(DateTimeOffset _, CancellationToken __)
#pragma warning restore CA1822
{
return await Task.FromResult(new List<UpdatedSubjectResource>());
}

private sealed class ServiceResourceInformationEqualityComparer : IEqualityComparer<ServiceResourceInformation>
{
public bool Equals(ServiceResourceInformation? x, ServiceResourceInformation? y)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ public async Task<IReadOnlyCollection<ServiceResourceInformation>> GetResourceIn
return resource;
}

public async Task<List<UpdatedSubjectResource>> GetUpdatedSubjectResources(DateTimeOffset since, CancellationToken cancellationToken)
elsand marked this conversation as resolved.
Show resolved Hide resolved
{
const string searchEndpoint = "resourceregistry/api/v1/resource/updated";
var resources = new List<UpdatedSubjectResource>();
var nextUrl = searchEndpoint + "?since=" + Uri.EscapeDataString(since.ToString("O"));
do
{
var response = await _client
.GetFromJsonEnsuredAsync<UpdatedResponse>(nextUrl,
cancellationToken: cancellationToken);

resources.AddRange(response.Data.Select(item =>
new UpdatedSubjectResource
{
Resource = item.ResourceUrn,
Subject = item.SubjectUrn,
UpdatedAt = item.UpdatedAt,
Deleted = item.Deleted
}));

nextUrl = response.Links.Next?.ToString();

} while (nextUrl is not null);

return resources;
}

private async Task<Dictionary<string, ServiceResourceInformation[]>> GetOrSetResourceInformationByOrg(
CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -76,7 +103,7 @@ private async Task<ServiceResourceInformation[]> FetchServiceResourceInformation
const string searchEndpoint = "resourceregistry/api/v1/resource/resourcelist";

var response = await _client
.GetFromJsonEnsuredAsync<List<ResourceRegistryResponse>>(searchEndpoint,
.GetFromJsonEnsuredAsync<List<ResourceListResponse>>(searchEndpoint,
cancellationToken: cancellationToken);

return response
Expand All @@ -92,7 +119,7 @@ ResourceTypeAltinnApp or
.ToArray();
}

private sealed class ResourceRegistryResponse
private sealed class ResourceListResponse
{
public required string Identifier { get; init; }
public required CompetentAuthority HasCompetentAuthority { get; init; }
Expand All @@ -106,5 +133,23 @@ private sealed class CompetentAuthority
public string? Organization { get; init; }
public required string OrgCode { get; init; }
}
}

private sealed class UpdatedResponse
{
public required UpdatedResponseLinks Links { get; init; }
public required List<UpdatedResponseItem> Data { get; init; }
}

private sealed class UpdatedResponseLinks
{
public Uri? Next { get; init; }
}

private sealed class UpdatedResponseItem
{
public required Uri SubjectUrn { get; init; }
public required Uri ResourceUrn { get; init; }
public required DateTimeOffset UpdatedAt { get; init; }
public required bool Deleted { get; init; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,11 @@ private static IServiceCollection ConfigureFusionCache(this IServiceCollection s
SkipMemoryCache = settings.SkipMemoryCache
})
.WithRegisteredSerializer()
.WithRegisteredDistributedCache()
.WithRegisteredBackplane();
// If Redis is disabled (eg. in local development or non-web runtimes), we must instruct FusionCache to
// allow the use of InMemoryDistributedCache (it is by default ignored as a IDistributedCache implementation)
// TryWithRegisteredBackplane is used to ensure that we can continue without Redis as backplane
.WithRegisteredDistributedCache(ignoreMemoryDistributedCache: false)
.TryWithRegisteredBackplane();

return services;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Digdir.Domain.Dialogporten.Domain.SubjectResources;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.Configurations.SubjectResources;

internal sealed class SubjectResourceConfiguration : IEntityTypeConfiguration<SubjectResource>
{
public void Configure(EntityTypeBuilder<SubjectResource> builder)
{
builder.ToTable("SubjectResource");
elsand marked this conversation as resolved.
Show resolved Hide resolved
builder.HasIndex("Subject");
builder.HasIndex("Resource");
elsand marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Digdir.Domain.Dialogporten.Domain.SubjectResources;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.Configurations.SubjectResources;

internal sealed class SubjectResourceLastUpdateConfiguration : IEntityTypeConfiguration<SubjectResourceLastUpdate>
{
public void Configure(EntityTypeBuilder<SubjectResourceLastUpdate> builder)
{
builder.ToTable("SubjectResourceLastUpdate");
elsand marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents;
using Digdir.Domain.Dialogporten.Domain.SubjectResources;

namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence;

Expand All @@ -41,6 +42,8 @@ public DialogDbContext(DbContextOptions<DialogDbContext> options) : base(options
public DbSet<DialogContentType> DialogContentTypes => Set<DialogContentType>();
public DbSet<OutboxMessage> OutboxMessages => Set<OutboxMessage>();
public DbSet<OutboxMessageConsumer> OutboxMessageConsumers => Set<OutboxMessageConsumer>();
public DbSet<SubjectResource> SubjectResources => Set<SubjectResource>();
public DbSet<SubjectResourceLastUpdate> SubjectResourceLastUpdates => Set<SubjectResourceLastUpdate>();

//protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
// optionsBuilder.LogTo(Console.WriteLine);
Expand Down
Loading
Loading