feat(floci): model Service Bus as a child resource of AddFlociAzure - #1555
feat(floci): model Service Bus as a child resource of AddFlociAzure#1555thomhurst wants to merge 6 commits into
Conversation
WithServiceBus() adds a FlociAzureServiceBusResource child that enables the
floci-az Service Bus data plane (MOCKED=false, START_ON_BOOT=true) and pins
the host ports its Artemis sidecar publishes — free ports by default so
concurrent AppHosts don't collide. Referencing the child with Aspire's
standard WithReference injects the official emulator's connection-string
shape (Endpoint=sb://localhost:{port};...;UseDevelopmentEmulator=true;) so
AddAzureServiceBusClient works unchanged.
The sidecar publishes directly on the Docker host, outside Aspire's endpoint
model, so the endpoint is host-relative; the management plane stays on the
base endpoint from WithReference(azure).
Blocked on a floci-az release with start-on-boot support
(floci-io/floci-az#249, PR floci-io/floci-az#250).
Fixes CommunityToolkit#1552
Claude-Session: https://claude.ai/code/session_01K8waTF6dPtQNUmXz3i8xnG
|
@thomhurst - are you interested in being added as a contributor and being given the CODEOWNER for the floci integration? |
Model sidecar ports as proxyless endpoints so DCP allocates them before the Floci container environment resolves.
|
Happy to be added as a contributor but not sure I'll have time to be a code owner and review all the changes if it gets busy |
|
Well, the floci changes seem to mostly come from you 😅 |
aaronpowell
left a comment
There was a problem hiding this comment.
Looks good to merge when the external blocker is resolved.
|
Looks like this got released in https://github.com/floci-io/floci-az/releases/tag/0.12.0 . Is this Pr ready for review? |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical issues affect container connectivity, child-name uniqueness, and endpoint validation.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds Floci Azure Service Bus child-resource support with AMQP/AMQPS endpoints, connection-string injection, documentation, and integration coverage.
Changes:
- Adds
WithServiceBus()and Service Bus resource modeling. - Configures emulator startup and endpoint allocation.
- Adds unit and Docker functional tests.
- Updates documentation and package dependencies.
File summaries
| File | Summary |
|---|---|
tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/CommunityToolkit.Aspire.Hosting.Floci.Tests.csproj |
Adds the Service Bus SDK test dependency. |
tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/AzureServiceBusResourceTests.cs |
Tests Service Bus resource behavior. |
tests/CommunityToolkit.Aspire.Hosting.Floci.Tests/AzureServiceBusFunctionalTests.cs |
Verifies real emulator messaging operations. |
src/CommunityToolkit.Aspire.Hosting.Floci/README.md |
Documents Service Bus usage and runtime requirements. |
src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Azure.cs |
Adds Service Bus configuration and export support. |
src/CommunityToolkit.Aspire.Hosting.Floci/FlociAzureServiceBusResource.cs |
Defines the Service Bus child resource and connection properties. |
Directory.Packages.props |
Pins the Service Bus SDK version. |
Review details
Suppressed comments (1)
src/CommunityToolkit.Aspire.Hosting.Floci/FlociHostingExtension.Azure.cs:113
- When a parent already has a child, this branch ignores
nameand returns the existing resource after checking only ports. Thusazure.WithServiceBus("first"); azure.WithServiceBus("second")returns a builder whose resource is stillfirst, so a laterWithReferenceinjects the wrong connection-string key. Reject a different name (or otherwise honor it) before returning.
if (existing is not null)
{
int? existingAmqpPort = existing.AmqpEndpoint.EndpointAnnotation.Port;
int? existingAmqpTlsPort = existing.AmqpTlsEndpoint.EndpointAnnotation.Port;
if ((amqpPort is not null && amqpPort != existingAmqpPort)
- Files reviewed: 8/8 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| public ReferenceExpression ConnectionStringExpression => | ||
| ReferenceExpression.Create( | ||
| $"Endpoint={AmqpEndpoint};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey={DefaultSasKey};UseDevelopmentEmulator=true;"); |
| ArgumentNullException.ThrowIfNull(builder); | ||
| ArgumentException.ThrowIfNullOrWhiteSpace(name); |
| var serviceBus = new FlociAzureServiceBusResource(name, builder.Resource); | ||
| var serviceBusBuilder = builder.ApplicationBuilder | ||
| .AddResource(serviceBus) |
| if (context.ExecutionContext.IsPublishMode) | ||
| { | ||
| return; | ||
| } |
| [AspireExport] | ||
| public static IResourceBuilder<FlociAzureServiceBusResource> WithServiceBus( |
Fixes #1552.
Adds
WithServiceBus()to model the Floci Azure Service Bus AMQP data plane as a child resource. The emulator starts its Artemis sidecar at boot, and Aspire allocates proxyless AMQP/AMQPS endpoints. Referencing the child injects the connection string used byAddAzureServiceBusClient("servicebus").Requires floci-az 0.12.0, already pinned on this branch. That release includes namespace startup, batched sends, and .NET administration-client routing. The management plane remains on the parent emulator endpoint. Multiple emulator instances on one Docker host need distinct
FLOCI_AZ_DOCKER_RESOURCE_NAMESPACEvalues; the README documents this requirement.Validation includes eight unit tests and two Docker integration cases. The integration cases start the real emulator, verify both listeners before queue creation, resolve the consumer's
WithReferenceenvironment, create a queue withServiceBusAdministrationClient, and send, receive, and complete single messages and a three-message batch withServiceBusClient. Each case uses an isolated Docker namespace and a bounded timeout.Also fixes the TypeScript sample's bind mount to create a portable local directory instead of assuming
/tmp/floci-dataexists. The branch includes currentmain, which removes the obsolete Source Link dependency that blocked restore.Local validation:
dotnet test --project tests/CommunityToolkit.Aspire.Hosting.Floci.Tests -c Release --no-progress --output Normalpassed all 75 tests, with no skips, including TypeScript AppHost compilation/startup and the Docker integration cases. NuGet audit remained enabled.