Skip to content

Commit

Permalink
Add timer trigger for status and notification sending (#53)
Browse files Browse the repository at this point in the history
* Added Update Status timer trigger

Also started on notifications

* Added notification sending

* Update to ensure we only send when completed or failed

* Update IntegrationEventProvider.cs

* Fixed spelling error

Also increased expire time for notification
Moved dispatch of notifications events to status trigger

* Added tests for notifications for repo

* Update OrchestrationSettlementReportsAppFixture.cs

* Update SettlementReportRequestHandlerIntegrationTests.cs

* Added new function app project for our timer trigger

* Updates after review

* Update Program.cs

* Added new project to output

* Update action.yml

* Update action.yml

* Update Program.cs
  • Loading branch information
FirestarJes authored Oct 31, 2024
1 parent f6f370b commit 7448e36
Show file tree
Hide file tree
Showing 21 changed files with 494 additions and 9 deletions.
10 changes: 10 additions & 0 deletions .github/actions/dotnet-prepare-outputs/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@ runs:
--no-restore \
--configuration Release \
--output '${{ inputs.output_path }}\migration\databasemigration'
- name: Publish Settlement Reports Functions
shell: bash
run: |
dotnet publish \
'.\source\settlement-report\SettlementReports.Function\SettlementReports.Function.csproj' \
--no-build \
--no-restore \
--configuration Release \
--output '${{ inputs.output_path }}\functions\settlement-reports'
7 changes: 7 additions & 0 deletions SettlementReport.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SettlementReports.Interface
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SettlementReports.UnitTests", "source\settlement-report\SettlementReports.UnitTests\SettlementReports.UnitTests.csproj", "{AC7E764C-12EF-492A-A60D-2E284AF2D31D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SettlementReports.Function", "source\settlement-report\SettlementReports.Function\SettlementReports.Function.csproj", "{323D0FB4-7D5C-4C44-8C52-C629766750F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -82,6 +84,10 @@ Global
{AC7E764C-12EF-492A-A60D-2E284AF2D31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC7E764C-12EF-492A-A60D-2E284AF2D31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC7E764C-12EF-492A-A60D-2E284AF2D31D}.Release|Any CPU.Build.0 = Release|Any CPU
{323D0FB4-7D5C-4C44-8C52-C629766750F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{323D0FB4-7D5C-4C44-8C52-C629766750F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{323D0FB4-7D5C-4C44-8C52-C629766750F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{323D0FB4-7D5C-4C44-8C52-C629766750F8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8A8252D2-968E-4097-8D84-5E1A4287AB23} = {9805FFFF-9C74-4E1F-9FE8-0423C9469E33}
Expand All @@ -96,5 +102,6 @@ Global
{B9A8CF9A-7B62-481E-A155-DA07CD3172E9} = {8A8252D2-968E-4097-8D84-5E1A4287AB23}
{16B95F69-FEED-4E17-9010-B97C3591CBD5} = {8A8252D2-968E-4097-8D84-5E1A4287AB23}
{AC7E764C-12EF-492A-A60D-2E284AF2D31D} = {8A8252D2-968E-4097-8D84-5E1A4287AB23}
{323D0FB4-7D5C-4C44-8C52-C629766750F8} = {8A8252D2-968E-4097-8D84-5E1A4287AB23}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ limitations under the License.
<EmbeddedResource Include="Scripts\202409101100_Add_EndedDateTime_to_SettlementReport.sql" />
<EmbeddedResource Include="Scripts\202406210900_Add_IsHiddenFromActor_to_SettlementReport.sql" />
<EmbeddedResource Include="Scripts\202409081607_Add_JobId_To_SettlementReport.sql" />
<EmbeddedResource Include="Scripts\202410261405_Add_IsNotificationSent_to_SettlementReport.sql" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE [settlementreports].[SettlementReport]
ADD [IsNotificationSent] [bit] NOT NULL DEFAULT(1); --For all existing records, we will assume that notification has been sent.
GO
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Energinet.DataHub.Core.FunctionApp.TestCommon.Azurite;
using Energinet.DataHub.Core.FunctionApp.TestCommon.Configuration;
using Energinet.DataHub.Core.FunctionApp.TestCommon.FunctionAppHost;
using Energinet.DataHub.Core.Messaging.Communication.Extensions.Options;
using Energinet.DataHub.Core.TestCommon.Diagnostics;
using Energinet.DataHub.SettlementReport.Common.Infrastructure.Extensions.Options;
using Energinet.DataHub.SettlementReport.Infrastructure.Extensions.Options;
Expand Down Expand Up @@ -238,6 +239,11 @@ private FunctionAppHostSettings CreateAppHostSettings(ref int port)
$"RevisionLogOptions:ApiAddress",
MockServer.Url! + "/revision-log");

// Integration events
appHostSettings.ProcessEnvironmentVariables.Add($"{IntegrationEventsOptions.SectionName}__{nameof(IntegrationEventsOptions.SubscriptionName)}", "fake_value");
appHostSettings.ProcessEnvironmentVariables.Add($"{IntegrationEventsOptions.SectionName}__{nameof(IntegrationEventsOptions.TopicName)}", "fake_value");
appHostSettings.ProcessEnvironmentVariables.Add($"{ServiceBusNamespaceOptions.SectionName}__{nameof(ServiceBusNamespaceOptions.FullyQualifiedNamespace)}", "fake_value");

return appHostSettings;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Energinet.DataHub.RevisionLog.Integration" Version="1.1.3" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageReference Include="Energinet.DataHub.Core.App.FunctionApp" Version="13.3.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ public interface ISettlementReportRepository
Task<IEnumerable<SettlementReport>> GetForJobsAsync();

Task<IEnumerable<SettlementReport>> GetForJobsAsync(Guid actorId);

Task<IEnumerable<SettlementReport>> GetPendingNotificationsForCompletedAndFailed();
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public sealed class SettlementReport

public long? JobId { get; init; }

public bool IsNotificationSent { get; private set; }

public SettlementReport(
IClock clock,
Guid userId,
Expand All @@ -80,6 +82,7 @@ public SettlementReport(
SplitReportPerGridArea = request.SplitReportPerGridArea;
IncludeMonthlyAmount = request.IncludeMonthlyAmount;
GridAreas = JsonSerializer.Serialize(request.Filter.GridAreas);
IsNotificationSent = false;
}

public SettlementReport(
Expand All @@ -106,6 +109,7 @@ public SettlementReport(
SplitReportPerGridArea = request.SplitReportPerGridArea;
IncludeMonthlyAmount = request.IncludeMonthlyAmount;
GridAreas = JsonSerializer.Serialize(request.Filter.GridAreas);
IsNotificationSent = false;
}

// EF Core Constructor.
Expand All @@ -132,4 +136,9 @@ public void MarkAsFailed()
{
Status = SettlementReportStatus.Failed;
}

public void MarkAsNotificationSent()
{
IsNotificationSent = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.Core.Messaging.Communication.Publisher;
using Energinet.DataHub.SettlementReport.Application.Handlers;
using Microsoft.Azure.Functions.Worker;

namespace SettlementReports.Function.Functions;

internal sealed class SettlementReportUpdateStatusTimerTrigger
{
private readonly IListSettlementReportJobsHandler _listSettlementReportJobsHandler;
private readonly IPublisher _publisher;

public SettlementReportUpdateStatusTimerTrigger(
IListSettlementReportJobsHandler listSettlementReportJobsHandler,
IPublisher publisher)
{
_listSettlementReportJobsHandler = listSettlementReportJobsHandler;
_publisher = publisher;
}

[Function(nameof(UpdateStatusForSettlementReports))]
public async Task UpdateStatusForSettlementReports(
[TimerTrigger("0 */5 * * * *")] TimerInfo timer,
FunctionContext executionContext)
{
ArgumentNullException.ThrowIfNull(executionContext);

// We are not interested in the result of the handler, as the handler will update the status of the settlement reports
// It will also handle sending Notifications to the expected recipients
await _listSettlementReportJobsHandler.HandleAsync().ConfigureAwait(false);
await _publisher.PublishAsync(executionContext.CancellationToken).ConfigureAwait(false);
}
}
47 changes: 47 additions & 0 deletions source/settlement-report/SettlementReports.Function/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.Core.App.Common.Extensions.DependencyInjection;
using Energinet.DataHub.Core.App.FunctionApp.Extensions.Builder;
using Energinet.DataHub.Core.App.FunctionApp.Extensions.DependencyInjection;
using Energinet.DataHub.RevisionLog.Integration.Extensions.DependencyInjection;
using Energinet.DataHub.SettlementReport.Common.Infrastructure.Security;
using Energinet.DataHub.SettlementReport.Common.Infrastructure.Telemetry;
using Energinet.DataHub.SettlementReport.Infrastructure.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices((context, services) =>
{
// Common
services.AddApplicationInsightsForIsolatedWorker(SubsystemInformation.SubsystemName);
services.AddHealthChecksForIsolatedWorker();

// Shared by modules
services.AddNodaTimeForApplication();

// revision log
services.AddRevisionLogIntegrationModule(context.Configuration);

// Modules
services.AddSettlementReportsV2Module(context.Configuration);
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddLoggingConfigurationForIsolatedWorker(hostingContext);
})
.Build();

host.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"profiles": {
"SettlementReports.Function": {
"commandName": "Project",
"commandLineArgs": "--port 7232",
"launchBrowser": false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>V4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Energinet.DataHub.RevisionLog.Integration" Version="1.1.3" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageReference Include="Energinet.DataHub.Core.App.FunctionApp" Version="13.3.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.4.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.18.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common.Infrastructure\Common.Infrastructure.csproj" />
<ProjectReference Include="..\SettlementReports.Infrastructure\SettlementReports.Infrastructure.csproj" />
<ProjectReference Include="..\SettlementReports.Interfaces\SettlementReports.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
</ItemGroup>
</Project>
12 changes: 12 additions & 0 deletions source/settlement-report/SettlementReports.Function/host.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
},
"enableLiveMetricsFilters": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Energinet.DataHub.SettlementReport.Infrastructure.Contracts;

public partial class UserNotificationTriggered
{
public const string EventName = "UserNotificationTriggered";
public const int CurrentMinorVersion = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Copyright 2020 Energinet DataHub A/S
*
* Licensed under the Apache License, Version 2.0 (the "License2");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

syntax = "proto3";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Energinet.DataHub.SettlementReport.Infrastructure.Contracts";

/*
* UserNotificationTriggered Integration Event.
*
* Occurs when some action triggers the notification of a set of users.
*/
message UserNotificationTriggered {

/*
* An identifier specifying the reason for the notification.
*/
string reason_identifier = 1;

/*
* The unique identifier of the actor whose users will receive the notification.
*/
string target_actor_id = 2;

oneof target {

/*
* The unique identifier of the user that should receive the notification.
*/
string target_user_id = 3;

/*
* The unique identifier of the group of users having the specified permission that should receive the notification.
*/
string target_permissions = 4;
}

/*
* A reason-specific id of an entity that the notification targets.
*/
string related_id = 5;

/*
* A timestamp for when the notification was generated.
*/
google.protobuf.Timestamp occurred_at = 6;

/*
* A timestamp for when the notification expires by itself.
*/
google.protobuf.Timestamp expires_at = 7;
}
Loading

0 comments on commit 7448e36

Please sign in to comment.