Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
cc5644c
Spike function manifests
andreasohlund Feb 10, 2026
d8b8b1f
Rebase and refactor to get transport from settings
andreasohlund Feb 11, 2026
06441cc
Separate code path for send only
andreasohlund Feb 11, 2026
91d6e01
Hook up the function manifest again
andreasohlund Feb 11, 2026
06b5ae0
Demo potential place where we need to set the connection name
andreasohlund Feb 11, 2026
d1a1616
Demo routing
andreasohlund Feb 11, 2026
f9c4137
Validate that all functions have been configured
andreasohlund Feb 11, 2026
0ca7748
Handle case where user has disabled the generator
andreasohlund Feb 11, 2026
cd1fe8e
Fixup
andreasohlund Feb 11, 2026
de0ed25
Cleanup
andreasohlund Feb 11, 2026
a04e6ee
Start adding alternative options for configuring functions
andreasohlund Feb 12, 2026
2bd1d46
Add option with generics
andreasohlund Feb 12, 2026
4587313
Add more options
andreasohlund Feb 12, 2026
f3252bb
Add crazy idea
andreasohlund Feb 12, 2026
0954be7
Add note about what happens when users forget to register functions
andreasohlund Feb 12, 2026
4ce8eb5
Show service locator
andreasohlund Feb 12, 2026
315bbd7
Bad idea, won't work since functions are per method not per class
andreasohlund Feb 12, 2026
cd71585
Use approach with config colocated with the function
andreasohlund Feb 13, 2026
9c21733
Cleanup
andreasohlund Feb 13, 2026
204abe4
More cleanup
andreasohlund Feb 13, 2026
9c9aa65
Demo diverging endpoint and queue names
andreasohlund Feb 13, 2026
70a085e
Move initalizer
andreasohlund Feb 13, 2026
6b4a4de
Demo using function class for config as well
andreasohlund Feb 13, 2026
efe53fa
Spike v3: Unification of approaches. Separate User libraries in manua…
mattmercurio Feb 13, 2026
1416ee5
Ceremony reduction. Support parameterless [NServiceBusFunction]
mattmercurio Feb 13, 2026
9b5f1c4
NServiceBusSendOnlyEndpoint attribute
mattmercurio Feb 13, 2026
8e585fd
Emit generated files
andreasohlund Feb 14, 2026
3d7e9ca
Consolidate config
andreasohlund Feb 14, 2026
4b36e3b
Merge sendonly config into http sender
andreasohlund Feb 14, 2026
2c23153
Make the http sender into the sales api endpoint
andreasohlund Feb 14, 2026
75ab4ac
Make sure to start nsb endpoints earlier to make sure that installers…
andreasohlund Feb 16, 2026
c780ea0
Enable logging
andreasohlund Feb 16, 2026
6cd55b5
remove http ref
andreasohlund Feb 16, 2026
01686b7
Make sure we have a logging scope with the endpoint name present when…
andreasohlund Feb 17, 2026
e85a6f3
Get rid of unneded abstraction
andreasohlund Feb 17, 2026
9671f13
Cleanup
andreasohlund Feb 17, 2026
1680a4c
Skip the interface and go with conventional method names instead
andreasohlund Feb 18, 2026
22daf94
Fixup
andreasohlund Feb 18, 2026
51afc50
Cleanup
andreasohlund Feb 18, 2026
e5f34c8
Use nameof
andreasohlund Feb 18, 2026
83b0fba
Demo use of default connection
andreasohlund Feb 18, 2026
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
37 changes: 37 additions & 0 deletions src/IntegrationTest.Billing/BillingFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace IntegrationTest.Billing;

using Azure.Messaging.ServiceBus;
using IntegrationTest.Shared;
using Microsoft.Azure.Functions.Worker;

// Pattern for multiple endpoints in one class with separate configs
public partial class BillingFunctions
{
[Function("BillingApi")]
[NServiceBusFunction]
public partial Task BillingApi(
[ServiceBusTrigger("billing-api", Connection = "AzureWebJobsServiceBus", AutoCompleteMessages = true)]
ServiceBusReceivedMessage message,
FunctionContext functionContext,
CancellationToken cancellationToken = default);

public static void ConfigureBillingApi(EndpointConfiguration configuration)
{
CommonEndpointConfig.Apply(configuration);
configuration.AddHandler<Handlers.ProcessPaymentHandler>();
}

[Function("BillingBackend")]
[NServiceBusFunction]
public partial Task BillingBackend(
[ServiceBusTrigger("billing-backend", Connection = "AzureWebJobsServiceBus", AutoCompleteMessages = true)]
ServiceBusReceivedMessage message,
FunctionContext functionContext,
CancellationToken cancellationToken = default);

public static void ConfigureBillingBackend(EndpointConfiguration configuration)
{
CommonEndpointConfig.Apply(configuration);
// different handlers for the backend queue
}
}
15 changes: 15 additions & 0 deletions src/IntegrationTest.Billing/Handlers/ProcessPaymentHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace IntegrationTest.Billing.Handlers;

using IntegrationTest.Shared;
using Microsoft.Extensions.Logging;
using NServiceBus;

public class ProcessPaymentHandler(ILogger<ProcessPaymentHandler> logger) : IHandleMessages<OrderSubmitted>
{
public async Task Handle(OrderSubmitted message, IMessageHandlerContext context)
{
logger.LogWarning($"Handling {nameof(OrderSubmitted)} in {nameof(ProcessPaymentHandler)}");

await context.Publish(new PaymentCleared()).ConfigureAwait(false);
}
}
23 changes: 23 additions & 0 deletions src/IntegrationTest.Billing/IntegrationTest.Billing.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);NServiceBus</InterceptorsPreviewNamespaces>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NServiceBus.AzureFunctions.AzureServiceBus\NServiceBus.AzureFunctions.AzureServiceBus.csproj" />
<ProjectReference Include="..\NServiceBus.AzureFunctions.Analyzer\NServiceBus.AzureFunctions.Analyzer.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
<ProjectReference Include="..\IntegrationTest.Shared\IntegrationTest.Shared.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.24.0" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions src/IntegrationTest.Sales/Handlers/AcceptOrderHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace IntegrationTest.Sales.Handlers;

using IntegrationTest.Shared;
using Microsoft.Extensions.Logging;
using NServiceBus;

public class AcceptOrderHandler(ILogger<AcceptOrderHandler> logger) : IHandleMessages<SubmitOrder>
{
public async Task Handle(SubmitOrder message, IMessageHandlerContext context)
{
logger.LogWarning($"Handling {nameof(SubmitOrder)} in {nameof(AcceptOrderHandler)}");

await context.Publish(new OrderSubmitted()).ConfigureAwait(false);
}
}
24 changes: 24 additions & 0 deletions src/IntegrationTest.Sales/IntegrationTest.Sales.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);NServiceBus</InterceptorsPreviewNamespaces>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NServiceBus.AzureFunctions.AzureServiceBus\NServiceBus.AzureFunctions.AzureServiceBus.csproj" />
<ProjectReference Include="..\NServiceBus.AzureFunctions.Analyzer\NServiceBus.AzureFunctions.Analyzer.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
<ProjectReference Include="..\IntegrationTest.Shared\IntegrationTest.Shared.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.24.0" />
</ItemGroup>

</Project>
39 changes: 39 additions & 0 deletions src/IntegrationTest.Sales/SalesApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace IntegrationTest.Sales;

using System.Net;
using System.Threading.Tasks;
using IntegrationTest.Shared;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NServiceBus;

[NServiceBusSendOnlyEndpoint]
class SalesApi([FromKeyedServices("SalesApi")] IMessageSession session, ILogger<SalesApi> logger)
{
[Function("SalesApi")]
public async Task<HttpResponseData> Api(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequestData req,
CancellationToken cancellationToken)
{
logger.LogInformation("C# HTTP trigger function received a request.");

await session.Send(new SubmitOrder(), cancellationToken).ConfigureAwait(false);

var r = req.CreateResponse(HttpStatusCode.OK);
await r.WriteStringAsync($"{nameof(SubmitOrder)} sent.", cancellationToken).ConfigureAwait(false);
return r;
}

public static void ConfigureSalesApi(EndpointConfiguration configuration)
{
var transport = new AzureServiceBusServerlessTransport(TopicTopology.Default) { ConnectionName = "AzureWebJobsServiceBus" };

var routing = configuration.UseTransport(transport);

routing.RouteToEndpoint(typeof(SubmitOrder), "sales");
configuration.UseSerialization<SystemJsonSerializer>();
}
}
23 changes: 23 additions & 0 deletions src/IntegrationTest.Sales/SalesEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace IntegrationTest.Sales;

using Azure.Messaging.ServiceBus;
using IntegrationTest.Shared;
using Microsoft.Azure.Functions.Worker;

// Cleanest pattern for single-function endpoints
[NServiceBusFunction]
public partial class SalesEndpoint
{
[Function("Sales")]
public partial Task Sales(
[ServiceBusTrigger("sales", Connection = "AzureWebJobsServiceBus", AutoCompleteMessages = true)]
ServiceBusReceivedMessage message,
FunctionContext functionContext,
CancellationToken cancellationToken = default);

public static void ConfigureSales(EndpointConfiguration configuration)
{
CommonEndpointConfig.Apply(configuration);
configuration.AddHandler<Handlers.AcceptOrderHandler>();
}
}
12 changes: 12 additions & 0 deletions src/IntegrationTest.Shared/CommonEndpointConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace IntegrationTest.Shared;

public static class CommonEndpointConfig
{
public static void Apply(EndpointConfiguration configuration)
{
configuration.UseTransport(new AzureServiceBusServerlessTransport(TopicTopology.Default));
configuration.EnableInstallers();
configuration.UsePersistence<LearningPersistence>();
configuration.UseSerialization<SystemJsonSerializer>();
}
}
11 changes: 11 additions & 0 deletions src/IntegrationTest.Shared/IntegrationTest.Shared.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NServiceBus.AzureFunctions.AzureServiceBus\NServiceBus.AzureFunctions.AzureServiceBus.csproj" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions src/IntegrationTest.Shared/OrderSubmitted.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace IntegrationTest.Shared;

using NServiceBus;

public class OrderSubmitted : IEvent;
5 changes: 5 additions & 0 deletions src/IntegrationTest.Shared/PaymentCleared.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace IntegrationTest.Shared;

using NServiceBus;

public class PaymentCleared : IEvent;
5 changes: 5 additions & 0 deletions src/IntegrationTest.Shared/SubmitOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace IntegrationTest.Shared;

using NServiceBus;

public class SubmitOrder : ICommand;
15 changes: 15 additions & 0 deletions src/IntegrationTest.Shipping/Handlers/ShipOrderHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace IntegrationTest.Shipping.Handlers;

using IntegrationTest.Shared;
using Microsoft.Extensions.Logging;
using NServiceBus;

public class ShipOrderHandler(ILogger<ShipOrderHandler> logger) : IHandleMessages<PaymentCleared>
{
public Task Handle(PaymentCleared message, IMessageHandlerContext context)
{
logger.LogWarning($"Handling {nameof(PaymentCleared)} in {nameof(ShipOrderHandler)}");

return Task.CompletedTask;
}
}
23 changes: 23 additions & 0 deletions src/IntegrationTest.Shipping/IntegrationTest.Shipping.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);NServiceBus</InterceptorsPreviewNamespaces>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NServiceBus.AzureFunctions.AzureServiceBus\NServiceBus.AzureFunctions.AzureServiceBus.csproj" />
<ProjectReference Include="..\NServiceBus.AzureFunctions.Analyzer\NServiceBus.AzureFunctions.Analyzer.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
<ProjectReference Include="..\IntegrationTest.Shared\IntegrationTest.Shared.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.24.0" />
</ItemGroup>

</Project>
22 changes: 22 additions & 0 deletions src/IntegrationTest.Shipping/ShippingEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace IntegrationTest.Shipping;

using Azure.Messaging.ServiceBus;
using IntegrationTest.Shared;
using Microsoft.Azure.Functions.Worker;

[NServiceBusFunction]
public partial class ShippingEndpoint
{
[Function(nameof(Shipping))]
public partial Task Shipping(
[ServiceBusTrigger("shipping", AutoCompleteMessages = true)]
ServiceBusReceivedMessage message,
FunctionContext functionContext,
CancellationToken cancellationToken = default);

public static void ConfigureShipping(EndpointConfiguration endpoint)
{
CommonEndpointConfig.Apply(endpoint);
endpoint.AddHandler<Handlers.ShipOrderHandler>();
}
}
28 changes: 0 additions & 28 deletions src/IntegrationTest/HttpSender.cs

This file was deleted.

9 changes: 8 additions & 1 deletion src/IntegrationTest/IntegrationTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@
<TargetFramework>net10.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);NServiceBus</InterceptorsPreviewNamespaces>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NServiceBus.AzureFunctions.AzureServiceBus\NServiceBus.AzureFunctions.AzureServiceBus.csproj" />
<ProjectReference Include="..\NServiceBus.AzureFunctions.Analyzer\NServiceBus.AzureFunctions.Analyzer.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
<ProjectReference Include="..\IntegrationTest.Shared\IntegrationTest.Shared.csproj" />
<ProjectReference Include="..\IntegrationTest.Sales\IntegrationTest.Sales.csproj" />
<ProjectReference Include="..\IntegrationTest.Billing\IntegrationTest.Billing.csproj" />
<ProjectReference Include="..\IntegrationTest.Shipping\IntegrationTest.Shipping.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
</ItemGroup>

Expand Down
Loading