Skip to content
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ on:
branches: [ "main" ]

jobs:
test-net9:
test-net10:
runs-on: ubuntu-latest
container: mcr.microsoft.com/dotnet/sdk:9.0
container: mcr.microsoft.com/dotnet/sdk:10.0

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '9'
dotnet-version: '10'
- name: Nuget Push
env:
nuget_key: ${{ secrets.NUGETAPIKEY }}
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Authors>Cnblogs</Authors>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@
<Link>CqrsVersionExtensions.cs</Link>
</Compile>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.10.0" />
</ItemGroup>
</Project>
71 changes: 46 additions & 25 deletions src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/InjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Net;
using System.Net.Http.Headers;
using Cnblogs.Architecture.Ddd.Cqrs.AspNetCore;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
using Microsoft.Extensions.Http.Logging;
using Microsoft.Extensions.Http.Resilience;

namespace Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent;

Expand All @@ -17,47 +16,64 @@ public static class InjectExtensions
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="baseUri">The base uri for api.</param>
/// <param name="policy">The polly policy for underlying httpclient.</param>
/// <param name="loggingConfigure">Configure logging behavior.</param>
/// <param name="pollyConfigure">The polly policy for underlying httpclient.</param>
/// <typeparam name="TClient">The type of service agent</typeparam>
/// <returns></returns>
public static IHttpClientBuilder AddServiceAgent<TClient>(
this IServiceCollection services,
string baseUri,
IAsyncPolicy<HttpResponseMessage>? policy = null)
Action<LoggingOptions>? loggingConfigure = null,
Action<HttpStandardResilienceOptions>? pollyConfigure = null)
where TClient : class
{
policy ??= GetDefaultPolicy();
return services.AddHttpClient<TClient>(
h =>
{
h.BaseAddress = new Uri(baseUri);
h.AddCqrsAcceptHeaders();
}).AddPolicyHandler(policy);
var builder = services.AddHttpClient<TClient>(h =>
{
h.BaseAddress = new Uri(baseUri);
h.AddCqrsAcceptHeaders();
});
builder.AddLogging(loggingConfigure);
builder.ApplyResilienceConfigure(pollyConfigure);
return builder;
}

/// <summary>
/// Inject a service agent to services.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="baseUri">The base uri for api.</param>
/// <param name="policy">The polly policy for underlying httpclient.</param>
/// <param name="loggingConfigure">Configure logging behavior.</param>
/// <param name="pollyConfigure">The polly policy for underlying httpclient.</param>
/// <typeparam name="TClient">The type of api client.</typeparam>
/// <typeparam name="TImplementation">The type of service agent</typeparam>
/// <returns></returns>
public static IHttpClientBuilder AddServiceAgent<TClient, TImplementation>(
this IServiceCollection services,
string baseUri,
IAsyncPolicy<HttpResponseMessage>? policy = null)
Action<LoggingOptions>? loggingConfigure = null,
Action<HttpStandardResilienceOptions>? pollyConfigure = null)
where TClient : class
where TImplementation : class, TClient
{
policy ??= GetDefaultPolicy();
return services.AddHttpClient<TClient, TImplementation>(
h =>
{
h.BaseAddress = new Uri(baseUri);
h.AddCqrsAcceptHeaders();
}).AddPolicyHandler(policy);
var builder = services.AddHttpClient<TClient, TImplementation>(h =>
{
h.BaseAddress = new Uri(baseUri);
h.AddCqrsAcceptHeaders();
});
builder.AddLogging(loggingConfigure);
builder.ApplyResilienceConfigure(pollyConfigure);
return builder;
}

private static void AddLogging(this IHttpClientBuilder h, Action<LoggingOptions>? configure = null)
{
h.AddExtendedHttpClientLogging(o =>
{
o.LogBody = false;
o.LogRequestStart = false;
o.BodySizeLimit = 2000;
configure?.Invoke(o);
});
}

private static void AddCqrsAcceptHeaders(this HttpClient h)
Expand All @@ -66,10 +82,15 @@ private static void AddCqrsAcceptHeaders(this HttpClient h)
h.DefaultRequestHeaders.AppendCurrentCqrsVersion();
}

private static IAsyncPolicy<HttpResponseMessage> GetDefaultPolicy()
private static void ApplyResilienceConfigure(
this IHttpClientBuilder builder,
Action<HttpStandardResilienceOptions>? extraConfigure)
{
return HttpPolicyExtensions.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(1500));
builder.AddStandardResilienceHandler(options =>
{
options.Retry.DisableForUnsafeHttpMethods();
options.Retry.MaxRetryAttempts = 3;
extraConfigure?.Invoke(options);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Cnblogs.Architecture.Ddd.EventBus.Abstractions;
/// <summary>
/// The hosted service for publishing integration event at background.
/// </summary>
public sealed class PublishIntegrationEventHostedService : BackgroundService
public sealed partial class PublishIntegrationEventHostedService : BackgroundService
{
private readonly EventBusOptions _options;
private readonly IServiceProvider _serviceProvider;
Expand Down Expand Up @@ -38,7 +38,7 @@ public PublishIntegrationEventHostedService(
/// <inheritdoc />
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Integration event publisher running");
LogIntegrationEventPublisherStarted();
var watch = new Stopwatch();
var failureCounter = 0;
var successCounter = 0;
Expand All @@ -57,26 +57,18 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
if (sent > 0)
{
successCounter++;
_logger.LogInformation(
"Published {PublishedEventCount} events in {Duration} ms, resting count: {RestingEventCount}",
sent,
watch.ElapsedMilliseconds,
afterCount);
LogEventsPublished(sent, watch.ElapsedMilliseconds, afterCount);
}
}
catch (Exception e)
{
failureCounter++;
_logger.LogWarning(
e,
"Publish integration event failed, pending count: {Count}, failure count: {FailureCount}",
_eventBuffer.Count,
failureCounter);
LogPublishEventFailed(e, _eventBuffer.Count, failureCounter);
}

if (downgraded == false && failureCounter >= _options.FailureCountBeforeDowngrade)
{
_logger.LogError("Integration event publisher downgraded");
LogIntegrationEventPublisherDowngraded();
downgraded = true;
currentTimer = failedTimer;
successCounter = 0;
Expand All @@ -87,7 +79,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
downgraded = false;
currentTimer = normalTimer;
failureCounter = 0;
_logger.LogWarning("Integration event publisher recovered from downgrade");
LogIntegrationEventPublisherRecoveredFromDowngrade();
}
}
}
Expand Down Expand Up @@ -117,4 +109,19 @@ private async Task<int> PublishEventAsync()

return publishedEventCount;
}

[LoggerMessage(LogLevel.Information, "Integration event publisher running")]
partial void LogIntegrationEventPublisherStarted();

[LoggerMessage(LogLevel.Information, "Published {PublishedEventCount} events in {Duration} ms, resting count: {RestingEventCount}")]
partial void LogEventsPublished(int publishedEventCount, long duration, int restingEventCount);

[LoggerMessage(LogLevel.Warning, "Publish integration event failed, pending count: {Count}, failure count: {FailureCount}")]
partial void LogPublishEventFailed(Exception e, int count, int failureCount);

[LoggerMessage(LogLevel.Error, "Integration event publisher downgraded")]
partial void LogIntegrationEventPublisherDowngraded();

[LoggerMessage(LogLevel.Warning, "Integration event publisher recovered from downgrade")]
partial void LogIntegrationEventPublisherRecoveredFromDowngrade();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ItemGroup>
<ProjectReference Include="..\Cnblogs.Architecture.Ddd.Cqrs.DependencyInjection\Cnblogs.Architecture.Ddd.Cqrs.DependencyInjection.csproj"/>
<ProjectReference Include="..\Cnblogs.Architecture.Ddd.Infrastructure.Abstractions\Cnblogs.Architecture.Ddd.Infrastructure.Abstractions.csproj"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Net.Http.Json;
using Cnblogs.Architecture.Ddd.Cqrs.Abstractions;
using Cnblogs.Architecture.Ddd.Cqrs.AspNetCore;
using Cnblogs.Architecture.IntegrationTestProject;
using Cnblogs.Architecture.IntegrationTestProject.Application.Commands;
using Cnblogs.Architecture.IntegrationTestProject.Application.Errors;
using Cnblogs.Architecture.IntegrationTestProject.Application.Queries;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Net;
using System.Net.Http.Json;
using Cnblogs.Architecture.Ddd.Infrastructure.Abstractions;
using Cnblogs.Architecture.IntegrationTestProject;
using Cnblogs.Architecture.IntegrationTestProject.Application.Commands;
using Microsoft.AspNetCore.Mvc.Testing;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using Cnblogs.Architecture.IntegrationTestProject;
using Cnblogs.Architecture.IntegrationTestProject.Models;
using Microsoft.AspNetCore.Mvc.Testing;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Net;
using System.Net.Http.Json;
using Cnblogs.Architecture.Ddd.Infrastructure.Abstractions;
using Cnblogs.Architecture.IntegrationTestProject;

using Microsoft.AspNetCore.Mvc.Testing;

namespace Cnblogs.Architecture.IntegrationTests;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Net;
using System.Net.Http.Json;
using Cnblogs.Architecture.Ddd.EventBus.Abstractions;
using Cnblogs.Architecture.IntegrationTestProject;
using Cnblogs.Architecture.IntegrationTestProject.Payloads;
using Cnblogs.Architecture.TestIntegrationEvents;
using Microsoft.AspNetCore.Mvc.Testing;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Cnblogs.Architecture.IntegrationTestProject;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.Mvc.Testing;

namespace Cnblogs.Architecture.IntegrationTests;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Cnblogs.Architecture.IntegrationTestProject;
using Microsoft.AspNetCore.Mvc.Testing;

namespace Cnblogs.Architecture.IntegrationTests;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Cnblogs.Architecture.IntegrationTestProject;
using Microsoft.AspNetCore.Mvc.Testing;

namespace Cnblogs.Architecture.IntegrationTests;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="NSubstitute" Version="5.3.0"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.9"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0-rc.2.25502.107" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down