Skip to content

Commit d0203d2

Browse files
authored
Add NServiceBus 10 custom-recoverability sample (#7594)
* Add comprehensive Dockerfile and test script for custom-recoverability Core_9 sample - Tests both normal operation and fault scenarios - Validates custom recoverability policy behavior - ArgumentNullException triggers default retries as expected * Add custom-recoverability Core_10 sample for NServiceBus 10 - Updated to use .NET 10 and C# preview language version - Updated to NServiceBus 10.0.0-alpha.1 and related prerelease packages - Updated Microsoft.Extensions packages to .NET 10 previews - Comprehensive Docker testing validates both normal and fault scenarios - Added prerelease.txt file as required for prerelease samples * Apply C# 12+ language features to custom-recoverability Core_10 sample - Use primary constructor in MyHandler class for cleaner dependency injection - Use structured logging with template instead of string interpolation - Simplify object initialization syntax - Improved lambda expression formatting for better readability * Update Dockerfiles and test scripts with final improvements - Fix Dockerfile path references and build commands - Update test scripts with proper validations and error handling - Ensure comprehensive testing of all sample scenarios
1 parent 9cbdf6e commit d0203d2

File tree

13 files changed

+494
-0
lines changed

13 files changed

+494
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net10.0</TargetFramework>
4+
<OutputType>Exe</OutputType>
5+
<LangVersion>preview</LangVersion>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<ProjectReference Include="..\Shared\Shared.csproj" />
9+
</ItemGroup>
10+
</Project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using NServiceBus;
4+
5+
class Program
6+
{
7+
static async Task Main()
8+
{
9+
Console.Title = "Client";
10+
var endpointConfiguration = new EndpointConfiguration("Samples.CustomRecoverability.Client");
11+
endpointConfiguration.UsePersistence<LearningPersistence>();
12+
endpointConfiguration.UseTransport(new LearningTransport());
13+
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
14+
15+
var endpointInstance = await Endpoint.Start(endpointConfiguration);
16+
Console.WriteLine("Press enter to send a message");
17+
Console.WriteLine("Press any key to exit");
18+
19+
while (true)
20+
{
21+
var key = Console.ReadKey();
22+
if (key.Key != ConsoleKey.Enter)
23+
{
24+
break;
25+
}
26+
var id = Guid.NewGuid();
27+
var myMessage = new MyMessage
28+
{
29+
Id = id
30+
};
31+
await endpointInstance.Send("Samples.CustomRecoverability.Server", myMessage);
32+
33+
Console.WriteLine($"Sent a message with id: {id:N}");
34+
}
35+
await endpointInstance.Stop();
36+
}
37+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29728.190
5+
MinimumVisualStudioVersion = 15.0.26730.12
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{37DA8514-2536-4E76-ABFF-D1E90FB65122}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{5728DE02-C264-4697-B554-DDA5FAD10A47}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{1BEFE50E-24CA-4CAA-8B2C-7F8CD1771CB5}"
11+
EndProject
12+
Global
13+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
14+
Debug|Any CPU = Debug|Any CPU
15+
EndGlobalSection
16+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
17+
{37DA8514-2536-4E76-ABFF-D1E90FB65122}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18+
{37DA8514-2536-4E76-ABFF-D1E90FB65122}.Debug|Any CPU.Build.0 = Debug|Any CPU
19+
{5728DE02-C264-4697-B554-DDA5FAD10A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20+
{5728DE02-C264-4697-B554-DDA5FAD10A47}.Debug|Any CPU.Build.0 = Debug|Any CPU
21+
{1BEFE50E-24CA-4CAA-8B2C-7F8CD1771CB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22+
{1BEFE50E-24CA-4CAA-8B2C-7F8CD1771CB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
23+
EndGlobalSection
24+
GlobalSection(SolutionProperties) = preSolution
25+
HideSolutionNode = FALSE
26+
EndGlobalSection
27+
EndGlobal
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Custom Recoverability Sample - Core 10 Version
2+
# This Dockerfile builds and runs the Custom Recoverability sample
3+
#
4+
# Build from the repository root directory:
5+
# Docker: docker build -f samples/custom-recoverability/Core_10/Dockerfile -t custom-recoverability-core10 .
6+
# Podman: podman build -f samples/custom-recoverability/Core_10/Dockerfile -t custom-recoverability-core10 .
7+
#
8+
# Run the container:
9+
# Docker: docker run -it --rm custom-recoverability-core10
10+
# Podman: podman run -it --rm custom-recoverability-core10
11+
12+
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
13+
14+
# Install expect for automation
15+
RUN apt-get update && apt-get install -y expect procps && rm -rf /var/lib/apt/lists/*
16+
17+
# Copy repository configuration files
18+
COPY nuget.config /src/
19+
COPY Directory.Build.props /src/
20+
COPY BannedSymbols.txt /src/
21+
22+
# Copy the sample source
23+
COPY samples/custom-recoverability/Core_10/ /src/sample/
24+
25+
WORKDIR /src/sample
26+
27+
# Build the normal version (build projects individually to avoid .NET 10 preview file locking issues)
28+
RUN dotnet build Shared --framework net10.0
29+
RUN dotnet build Server --framework net10.0
30+
RUN dotnet build Client --framework net10.0
31+
32+
# Create fault scenario version by modifying the handler
33+
RUN cp -r Server Server_Fault
34+
RUN sed -i 's|//throw new ArgumentNullException("Uh oh - something went wrong....");|throw new ArgumentNullException("Uh oh - something went wrong....");|' Server_Fault/MyHandler.cs
35+
RUN sed -i 's|return Task.CompletedTask;|//return Task.CompletedTask;|' Server_Fault/MyHandler.cs
36+
RUN sed -i '1i using System;' Server_Fault/MyHandler.cs
37+
38+
# Build the fault version
39+
RUN dotnet build Server_Fault/Server.csproj --framework net10.0
40+
41+
# Copy the run script
42+
COPY samples/custom-recoverability/Core_10/run_sample.sh /src/run_sample.sh
43+
RUN chmod +x /src/run_sample.sh
44+
45+
# Set runtime image
46+
FROM mcr.microsoft.com/dotnet/runtime:10.0-preview
47+
48+
# Install expect and process tools for runtime
49+
RUN apt-get update && apt-get install -y expect procps && rm -rf /var/lib/apt/lists/*
50+
51+
# Copy built applications and run script
52+
COPY --from=build /src/sample/ /app/
53+
COPY --from=build /src/run_sample.sh /app/
54+
55+
WORKDIR /app
56+
57+
# Run the script by default
58+
CMD ["./run_sample.sh"]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using NServiceBus;
2+
using System.Threading.Tasks;
3+
using Microsoft.Extensions.Logging;
4+
5+
#region MyHandler
6+
public class MyHandler(ILogger<MyHandler> logger) : IHandleMessages<MyMessage>
7+
{
8+
public Task Handle(MyMessage message, IMessageHandlerContext context)
9+
{
10+
logger.LogInformation($"Message received. Id: {message.Id}");
11+
//throw new ArgumentNullException("Uh oh - something went wrong....");
12+
//throw new DivideByZeroException("DivideByZeroException - something went wrong....");
13+
return Task.CompletedTask;
14+
}
15+
}
16+
#endregion
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Microsoft.Extensions.Hosting;
5+
using NServiceBus;
6+
using NServiceBus.Transport;
7+
8+
class Program
9+
{
10+
11+
public static async Task Main(string[] args)
12+
{
13+
await CreateHostBuilder(args).Build().RunAsync();
14+
}
15+
16+
public static IHostBuilder CreateHostBuilder(string[] args) =>
17+
Host.CreateDefaultBuilder(args)
18+
.ConfigureServices((hostContext, services) =>
19+
{
20+
Console.Title = "Server";
21+
}).UseNServiceBus(x =>
22+
{
23+
var endpointConfiguration = new EndpointConfiguration("Samples.CustomRecoverability.Server");
24+
endpointConfiguration.UsePersistence<LearningPersistence>();
25+
endpointConfiguration.UseTransport(new LearningTransport());
26+
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
27+
var recoverability = endpointConfiguration.Recoverability();
28+
29+
#region disable
30+
//recoverability.Delayed(settings =>
31+
//{
32+
// settings.NumberOfRetries(0);
33+
//});
34+
#endregion
35+
36+
#region addcustompolicy
37+
recoverability.CustomPolicy(MyCustomRetryPolicy());
38+
#endregion
39+
40+
#region addcustomheaders
41+
recoverability.Failed(
42+
failed =>
43+
{
44+
failed.HeaderCustomization(headers =>
45+
{
46+
if (headers.ContainsKey("NServiceBus.ExceptionInfo.Message"))
47+
{
48+
headers["NServiceBus.ExceptionInfo.Message"] = "message override";
49+
}
50+
});
51+
});
52+
#endregion
53+
54+
return endpointConfiguration;
55+
});
56+
57+
58+
#region mycustomretrypolicy
59+
private static Func<RecoverabilityConfig, ErrorContext, RecoverabilityAction> MyCustomRetryPolicy()
60+
{
61+
return (config, errorContext) =>
62+
errorContext.Exception is ArgumentNullException
63+
? DefaultRecoverabilityPolicy.Invoke(config, errorContext)
64+
: RecoverabilityAction.MoveToError("error");
65+
}
66+
#endregion
67+
68+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net10.0</TargetFramework>
4+
<OutputType>Exe</OutputType>
5+
<LangVersion>preview</LangVersion>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.0-preview.5.25277.114" />
9+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.0-preview.5.25277.114" />
10+
<PackageReference Include="NServiceBus.Extensions.Hosting" Version="4.0.0-alpha.1" />
11+
</ItemGroup>
12+
<ItemGroup>
13+
<ProjectReference Include="..\Shared\Shared.csproj" />
14+
</ItemGroup>
15+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System;
2+
using NServiceBus;
3+
4+
public class MyMessage :
5+
IMessage
6+
{
7+
public Guid Id { get; set; }
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net10.0</TargetFramework>
4+
<LangVersion>preview</LangVersion>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="NServiceBus" Version="10.0.0-alpha.1" />
8+
</ItemGroup>
9+
</Project>

samples/custom-recoverability/Core_10/prerelease.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)