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: calculate for which buildings to invalidate the cache upon parcel changes #1268

Merged
merged 9 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/deploy_prd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
services: [
'building-api',
'building-backoffice-api',
#'building-cache-invalidator',
'building-consumer-address',
'building-consumer-parcel',
'building-producer',
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,20 @@ jobs:
dotnet-version: ${{ vars.VBR_DOTNET_VERSION_8 }}
secrets: inherit

build-cache-invalidator:
name: Build Cache Invalidator
uses: Informatievlaanderen/build-pipeline/.github/workflows/build-image.yml@main
needs: [ set-release-version ]
if: ${{ (github.repository_owner == 'Informatievlaanderen') && (needs.set-release-version.outputs.version != 'none') }}
with:
registry: ${{ vars.VBR_DEVOPS_DOCKER_REGISTRY }}/building-registry
image-file: br-cache-invalidator-image.tar
image-name: cache-invalidator
test-project: BuildingRegistry.Tests
build-project: BuildingRegistry.Cache.Invalidator
semver: ${{ needs.set-release-version.outputs.version }}
dotnet-version: ${{ vars.VBR_DOTNET_VERSION_8 }}

build-consumer-address:
name: Build Consumer Address
uses: Informatievlaanderen/build-pipeline/.github/workflows/build-image.yml@main
Expand Down Expand Up @@ -301,6 +315,7 @@ jobs:
build-projector,
build-projections-backoffice,
build-projections-last-changed-list,
build-cache-invalidator,
build-consumer-address,
build-consumer-read-parcel,
build-producer,
Expand Down Expand Up @@ -591,6 +606,7 @@ jobs:
'projector',
'projections-backoffice',
'projections-last-changed-list-console',
'cache-invalidator',
'consumer-address',
'consumer-read-parcel',
'producer',
Expand Down Expand Up @@ -668,6 +684,7 @@ jobs:
services: [
'building-api',
'building-backoffice-api',
'building-cache-invalidator',
'building-consumer-address',
'building-consumer-parcel',
'building-producer',
Expand Down Expand Up @@ -818,6 +835,7 @@ jobs:
services: [
'building-api',
'building-backoffice-api',
'building-cache-invalidator',
'building-consumer-address',
'building-consumer-parcel',
'building-producer',
Expand Down
7 changes: 7 additions & 0 deletions BuildingRegistry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildingRegistry.Projection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildingRegistry.Projections.LastChangedList.Console", "src\BuildingRegistry.Projections.LastChangedList.Console\BuildingRegistry.Projections.LastChangedList.Console.csproj", "{20D6D053-A641-4DE1-8137-781CBECDB486}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildingRegistry.Cache.Invalidator", "src\BuildingRegistry.Cache.Invalidator\BuildingRegistry.Cache.Invalidator.csproj", "{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -182,6 +184,10 @@ Global
{20D6D053-A641-4DE1-8137-781CBECDB486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20D6D053-A641-4DE1-8137-781CBECDB486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20D6D053-A641-4DE1-8137-781CBECDB486}.Release|Any CPU.Build.0 = Release|Any CPU
{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -212,6 +218,7 @@ Global
{6F18B5C9-0E57-4352-B320-7976094B0738} = {24B47154-C5F0-4356-B059-49A1E72C38A6}
{2CD597C6-43AB-4AB8-AF3A-5AC186AB92A3} = {24B47154-C5F0-4356-B059-49A1E72C38A6}
{20D6D053-A641-4DE1-8137-781CBECDB486} = {24B47154-C5F0-4356-B059-49A1E72C38A6}
{51EBEEC6-0B7E-4A5A-B03E-BF8D2A9C2B68} = {24B47154-C5F0-4356-B059-49A1E72C38A6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65FA30D5-DDFC-40EC-9BC9-3BF93D1B430F}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace BuildingRegistry.Api.Oslo.Building.Count
using Be.Vlaanderen.Basisregisters.Api.Search.Pagination;
using Be.Vlaanderen.Basisregisters.GrAr.Legacy;
using Consumer.Read.Parcel;
using Infrastructure.ParcelMatching;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Projections.Legacy;
Expand All @@ -17,22 +16,22 @@ public class BuildingCountHandlerV2 : IRequestHandler<BuildingCountRequest, Tota
{
private readonly LegacyContext _legacyContext;
private readonly ConsumerParcelContext _consumerParcelContext;
private readonly IParcelMatching _parcelMatching;
private readonly IBuildingMatching _buildingMatching;

public BuildingCountHandlerV2(
LegacyContext legacyContext, ConsumerParcelContext consumerParcelContext, IParcelMatching parcelMatching)
LegacyContext legacyContext, ConsumerParcelContext consumerParcelContext, IBuildingMatching buildingMatching)
{
_legacyContext = legacyContext;
_consumerParcelContext = consumerParcelContext;
_parcelMatching = parcelMatching;
_buildingMatching = buildingMatching;
}

public async Task<TotaalAantalResponse> Handle(BuildingCountRequest request, CancellationToken cancellationToken)
{
return new TotaalAantalResponse
{
Aantal = request.FilteringHeader.ShouldFilter
? await new BuildingListOsloQueryV2(_legacyContext, _consumerParcelContext, _parcelMatching)
? await new BuildingListOsloQueryV2(_legacyContext, _consumerParcelContext, _buildingMatching)
.Fetch(request.FilteringHeader, request.SortingHeader, new NoPaginationRequest())
.Items
.CountAsync(cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ namespace BuildingRegistry.Api.Oslo.Building.Detail
using Consumer.Read.Parcel;
using Converters;
using Infrastructure.Options;
using Infrastructure.ParcelMatching;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace BuildingRegistry.Api.Oslo.Building.List
using Converters;
using Infrastructure;
using Infrastructure.Options;
using Infrastructure.ParcelMatching;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
Expand All @@ -19,24 +18,24 @@ public class BuildingListHandlerV2 : IRequestHandler<BuildingListRequest, Buildi
{
private readonly LegacyContext _legacyContext;
private readonly ConsumerParcelContext _consumerParcelContext;
private readonly IParcelMatching _parcelMatching;
private readonly IBuildingMatching _buildingMatching;
private readonly IOptions<ResponseOptions> _responseOptions;

public BuildingListHandlerV2(
LegacyContext legacyContext,
IOptions<ResponseOptions> responseOptions,
ConsumerParcelContext consumerParcelContext,
IParcelMatching parcelMatching)
IBuildingMatching buildingMatching)
{
_legacyContext = legacyContext;
_responseOptions = responseOptions;
_consumerParcelContext = consumerParcelContext;
_parcelMatching = parcelMatching;
_buildingMatching = buildingMatching;
}

public async Task<BuildingListOsloResponse> Handle(BuildingListRequest request, CancellationToken cancellationToken)
{
var pagedBuildings = new BuildingListOsloQueryV2(_legacyContext, _consumerParcelContext, _parcelMatching)
var pagedBuildings = new BuildingListOsloQueryV2(_legacyContext, _consumerParcelContext, _buildingMatching)
.Fetch(request.FilteringHeader, request.SortingHeader, request.PaginationRequest);

var buildings = await pagedBuildings.Items.ToListAsync(cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace BuildingRegistry.Api.Oslo.Building.Query
using Consumer.Read.Parcel;
using Consumer.Read.Parcel.ParcelWithCount;
using Converters;
using Infrastructure.ParcelMatching;
using Microsoft.EntityFrameworkCore;
using Projections.Legacy;
using Projections.Legacy.BuildingDetailV2;
Expand All @@ -19,14 +18,17 @@ public class BuildingListOsloQueryV2 : Query<BuildingQueryItem, BuildingFilter>
{
private readonly LegacyContext _context;
private readonly ConsumerParcelContext _consumerParcelContext;
private readonly IParcelMatching _parcelMatching;
private readonly IBuildingMatching _buildingMatching;
protected override ISorting Sorting => new BuildingSorting();

public BuildingListOsloQueryV2(LegacyContext context, ConsumerParcelContext consumerParcelContext, IParcelMatching parcelMatching)
public BuildingListOsloQueryV2(
LegacyContext context,
ConsumerParcelContext consumerParcelContext,
IBuildingMatching buildingMatching)
{
_context = context;
_consumerParcelContext = consumerParcelContext;
_parcelMatching = parcelMatching;
_buildingMatching = buildingMatching;
}

protected override IQueryable<BuildingQueryItem> Filter(FilteringHeader<BuildingFilter> filtering)
Expand Down Expand Up @@ -63,7 +65,7 @@ protected override IQueryable<BuildingQueryItem> Filter(FilteringHeader<Building
var parcel = _consumerParcelContext.ParcelConsumerItemsWithCount.FirstOrDefault(x => x.CaPaKey == filtering.Filter.CaPaKey);
if (parcel is not null && parcel.Status == ParcelStatus.Realized)
{
var underlyingBuildings = _parcelMatching.GetUnderlyingBuildings(parcel.Geometry);
var underlyingBuildings = _buildingMatching.GetUnderlyingBuildings(parcel.Geometry);
buildings = buildings.Where(x => underlyingBuildings.Contains(x.PersistentLocalId));
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected override void Load(ContainerBuilder builder)
{
builder
.RegisterModule(new MediatRModule())
.RegisterModule(new ParcelMatchingModule())
.RegisterModule(new ParcelBuildingMatchingModule())
.RegisterModule(new LegacyModule(_configuration, _services, _loggerFactory))
.RegisterModule(new ConsumerParcelModule(_configuration, _services, _loggerFactory));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
namespace BuildingRegistry.Api.Oslo.Infrastructure.Modules
{
using Autofac;
using ParcelMatching;
using Consumer.Read.Parcel;
using Projections.Legacy;

public class ParcelMatchingModule : Module
public class ParcelBuildingMatchingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder
.RegisterType<ParcelMatching>()
.AsImplementedInterfaces();

builder
.RegisterType<BuildingMatching>()
.AsImplementedInterfaces();
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\packages\Be.Vlaanderen.Basisregisters.Build.Pipeline\Content\Be.Vlaanderen.Basisregisters.Build.Pipeline.Settings.App.props" />

<PropertyGroup>
<!-- Error NETSDK1152: https://docs.microsoft.com/en-us/dotnet/core/compatibility/sdk/6.0/duplicate-files-in-output -->
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
<ServerGarbageCollection>true</ServerGarbageCollection>
<EnableDefaultContentItems>false</EnableDefaultContentItems>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>

<ItemGroup>
<Content Include="Dockerfile" CopyToOutputDirectory="Always" />
<Content Include="appsettings.json" CopyToOutputDirectory="Always" />
<Content Include="appsettings.*.json" CopyToOutputDirectory="Always" />
<Content Include="init.sh" CopyToOutputDirectory="Always" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BuildingRegistry.Consumer.Read.Parcel\BuildingRegistry.Consumer.Read.Parcel.csproj" />
<ProjectReference Include="..\BuildingRegistry.Infrastructure\BuildingRegistry.Infrastructure.csproj" />
<ProjectReference Include="..\BuildingRegistry.Projections.Legacy\BuildingRegistry.Projections.Legacy.csproj" />
</ItemGroup>

<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
41 changes: 41 additions & 0 deletions src/BuildingRegistry.Cache.Invalidator/CacheInvalidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace BuildingRegistry.Cache.Invalidator
{
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Building;
using Consumer.Read.Parcel;
using Microsoft.Extensions.Hosting;

public class CacheInvalidator : BackgroundService
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ConsumerParcelContext _consumerParcelContext;
private readonly IRedisCacheInvalidateService _redisCacheInvalidateService;

public CacheInvalidator(
IHostApplicationLifetime hostApplicationLifetime,
ConsumerParcelContext consumerParcelContext,
IRedisCacheInvalidateService redisCacheInvalidateService)
{
_hostApplicationLifetime = hostApplicationLifetime;
_consumerParcelContext = consumerParcelContext;
_redisCacheInvalidateService = redisCacheInvalidateService;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var buildingsToInvalidate = _consumerParcelContext.BuildingsToInvalidate.ToList();

var buildingPersistentLocalIds = buildingsToInvalidate
.Select(x => new BuildingPersistentLocalId(x.BuildingPersistentLocalId))
.ToList();
await _redisCacheInvalidateService.Invalidate(buildingPersistentLocalIds);

_consumerParcelContext.BuildingsToInvalidate.RemoveRange(buildingsToInvalidate);
await _consumerParcelContext.SaveChangesAsync(stoppingToken);

_hostApplicationLifetime.StopApplication();
}
}
}
28 changes: 28 additions & 0 deletions src/BuildingRegistry.Cache.Invalidator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0.2-bookworm-slim-amd64

# create work dir and set permissions as WORKDIR sets permissions as root
RUN mkdir /app && chown -R app:app /app
WORKDIR /app

LABEL maintainer="Digitaal Vlaanderen <digitaal.vlaanderen@vlaanderen.be>"
LABEL registry="building-registry"

COPY / /app
WORKDIR /app

RUN apt-get update && \
apt-get install curl jq -y && \
chmod +x ./init.sh

ENV CORECLR_ENABLE_PROFILING=1
ENV CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8}
ENV CORECLR_PROFILER_PATH=/app/datadog/linux-x64/Datadog.Trace.ClrProfiler.Native.so
ENV DD_DOTNET_TRACER_HOME=/app/datadog

# Run the createLogPath script on Linux to ensure the automatic instrumentation logs are generated without permission issues
RUN /app/datadog/createLogPath.sh

# switch to created user
USER app

ENTRYPOINT ["./init.sh"]
Loading
Loading