Skip to content

feat(streaming): add Aspire SQS integration - #10797

Open
ReubenBond wants to merge 32 commits into
dotnet:mainfrom
ReubenBond:rb-add-orleans-sqs-aspire
Open

feat(streaming): add Aspire SQS integration#10797
ReubenBond wants to merge 32 commits into
dotnet:mainfrom
ReubenBond:rb-add-orleans-sqs-aspire

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 23, 2026

Copy link
Copy Markdown
Member

Problem

Orleans SQS streaming owns a deterministic partitioned queue topology, so a generic single-queue Aspire resource or a copied private provider class could not safely keep AWS infrastructure and silo/client configuration synchronized.

Solution

  • add configuration-driven SQS runtime provider builders and startup validation
  • add the packable Microsoft.Orleans.Streaming.SQS.Aspire AppHost bridge, separate from the runtime SQS package
  • expose public WithSqsStreaming / AddSqsStreaming, SqsStreamingOptions, and SqsStreamingResource APIs
  • use one validated options snapshot to provision every partition queue through AWS CDK and emit matching Orleans__Streaming__<name>__* settings
  • share the physical queue-name implementation with the runtime provider, require a concrete stable ServiceId, attach AWS SDK for .NET v4 configuration, and automatically wait for the CDK stack on referenced silos and clients
  • cover the public bridge model and activation on net10 in the existing AWS test project, while preserving provider/app-model/live ElasticMQ coverage on net8 and net10
  • add compiled AppHost, silo, and client guidance

Rationale

The AppHost package owns AWS CDK provisioning while the runtime package remains free of Aspire, AWS provisioning, and CDK dependencies. A shared naming invariant and one immutable configuration model keep CloudFormation resources and Orleans runtime topology aligned.

Fixes #10783

Part of #10784

Microsoft Reviewers: Open in CodeFlow

Copilot AI lite review requested due to automatic review settings August 23, 2026 12:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class configuration/Aspire integration for the Microsoft.Orleans.Streaming.SQS provider by introducing configuration-driven provider builders (silo + client), normalizing SQS connection string parsing, and adding Aspire app-model plus live ElasticMQ coverage in the existing AWS test project.

Changes:

  • Add SqsStreamProviderBuilder with stable provider aliases (SQS, AmazonSQS) for both silo and client activation from configuration.
  • Introduce a dedicated SQS connection-string parser and update SQSStorage to use it for more actionable startup validation.
  • Add Aspire app-model generation tests and a live ElasticMQ streaming test, plus update docs/snippets to include compiled Aspire examples.
Show a summary per file
File Description
test/Extensions/Orleans.AWS.Tests/Streaming/SQSStreamProviderBuilderTests.cs Unit coverage for provider registration, option binding, topology determinism, adapter selection, and validation errors.
test/Extensions/Orleans.AWS.Tests/Streaming/SQSAspireLiveStreamTests.cs Functional live test proving Aspire-generated config can publish/consume via ElasticMQ and cleans up queues.
test/Extensions/Orleans.AWS.Tests/Streaming/SQSAspireIntegrationTests.cs App-model + activation tests validating emitted environment/config for silo and client roles.
test/Extensions/Orleans.AWS.Tests/Orleans.AWS.Tests.csproj Adds Aspire AppHost/Orleans (and net10 testing) dependencies needed for the new Aspire tests.
src/AWS/Orleans.Streaming.SQS/Storage/SQSStorage.cs Switches connection-string parsing to the new shared parser and improves missing-Service error handling.
src/AWS/Orleans.Streaming.SQS/SqsConnectionString.cs Adds strict parsing/validation for key=value;... SQS connection strings.
src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs New configuration-driven provider builder for silo/client, including startup validation and adapter wiring.
src/api/AWS/Orleans.Streaming.SQS/Orleans.Streaming.SQS.cs Updates generated public API surface to include SqsStreamProviderBuilder.
docs/site/src/content/docs/streaming/sqs-streaming.md Adds Aspire configuration guidance for SQS streaming and references compiled snippets.
docs/site/src/content/docs/host/snippets/aspire/Silo/SiloProgram.cs Adds compiled silo snippet showing UseOrleans activating generated config.
docs/site/src/content/docs/host/snippets/aspire/Silo/Silo.csproj Adds SQS streaming package reference for the compiled silo snippet project.
docs/site/src/content/docs/host/snippets/aspire/Client/ClientProgram.cs Adds compiled client snippet showing UseOrleansClient activating generated config.
docs/site/src/content/docs/host/snippets/aspire/Client/Client.csproj Adds SQS streaming package reference for the compiled client snippet project.
docs/site/src/content/docs/host/snippets/aspire/AppHost/AppHostExamples.cs Adds compiled AppHost example and provider configuration snippet for SQS streaming.
docs/site/src/content/docs/host/snippets/aspire/AppHost/AppHost.csproj Adds Aspire.Hosting.AWS dependency for the AppHost compiled snippet project.
Directory.Packages.props Adds Aspire.Hosting.AWS package version under the net10 conditional block.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs:236

  • The DataAdapterKey/DataAdapterServiceKey conflict check is case-sensitive. Since configuration keys and most Aspire-generated values are case-insensitive, this can throw for values which resolve to the same keyed adapter (e.g., "Adapter" vs "adapter"). Consider using OrdinalIgnoreCase here, consistent with connection-string parsing using OrdinalIgnoreCase keys.
        if (!string.IsNullOrWhiteSpace(dataAdapterKey)
            && !string.IsNullOrWhiteSpace(dataAdapterServiceKey)
            && !string.Equals(dataAdapterKey, dataAdapterServiceKey, StringComparison.Ordinal))
        {
            throw new OrleansConfigurationException(
  • Files reviewed: 16/16 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread src/AWS/Orleans.Streaming.SQS/SqsConnectionString.cs Outdated
Comment thread src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs
Comment thread docs/site/src/content/docs/host/snippets/aspire/AppHost/AppHostExamples.cs Outdated
Copilot AI review requested due to automatic review settings August 23, 2026 13:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs:110

  • The ServiceKey/ConnectionName conflict check is case-sensitive (StringComparison.Ordinal), but connection-string keys in IConfiguration are effectively case-insensitive. This can throw an OrleansConfigurationException even when both values refer to the same connection string (e.g., "MySqs" vs "mysqs").
        if (!string.IsNullOrWhiteSpace(serviceKey)
            && !string.IsNullOrWhiteSpace(connectionName)
            && !string.Equals(serviceKey, connectionName, StringComparison.Ordinal))
        {
            throw new OrleansConfigurationException(

docs/site/src/content/docs/host/snippets/aspire/AppHost/AppHost.csproj:16

  • This snippet project pins most Aspire.Hosting.* packages to 13.4.6, but references Aspire.Hosting.AWS at 13.6.0. Mixing Aspire package versions within a single AppHost can lead to restore/downgrade warnings or runtime incompatibilities; it would be safer to align the versions (either bump the other Aspire.Hosting.* references to match AWS, or use an AWS version compatible with the rest).
    <PackageReference Include="Aspire.Hosting.AppHost" Version="13.4.6" />
    <PackageReference Include="Aspire.Hosting.AWS" Version="13.6.0" />
    <PackageReference Include="Aspire.Hosting.Orleans" Version="13.4.6" />
    <PackageReference Include="Aspire.Hosting.Redis" Version="13.4.6" />
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs:204

  • ValidateServiceLocation only validates values which contain "://". If a user sets Service/Region (or the Service value inside ConnectionString) to a host:port value like "localhost:9324" (missing scheme), this is treated as an AWS region and will flow into SQSStorage.CreateClient, which will then use AWSUtils.GetRegionEndpoint(service) instead of ServiceURL. That yields a non-actionable misconfiguration path (likely failing at runtime with hard-to-diagnose AWS endpoint errors). Consider rejecting colon-delimited values which are not absolute http/https URIs so startup validation stays actionable.
    private static void ValidateServiceLocation(string service)
    {
        if (service.Contains("://", StringComparison.Ordinal))
        {
            ValidateServiceEndpoint(service);
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request
Lines 81.56% (105,555 / 129,413)
Branches 70.35% (30,041 / 42,704)

Report-only conclusion: current-main baseline stale.

The newest successful coverage run tested 84352a7, not current main 325e7d6.

Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities.

The comparison remains report-only while normal line and branch variance is calibrated.

Coverage details

Copilot AI review requested due to automatic review settings August 23, 2026 16:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 17/17 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread test/Extensions/Orleans.AWS.Tests/Streaming/SqsAspireTestApp.cs
Comment thread test/Extensions/Orleans.AWS.Tests/Streaming/SQSAspireLiveStreamTests.cs Outdated
@ReubenBond

Copy link
Copy Markdown
Member Author

The current head has a repository-wide restore/build blocker. Orleans.AWS.Tests and Orleans.Transactions.DynamoDB.Test require AWSSDK.Lambda, AWSSDK.SSO, and AWSSDK.SSOOIDC, but those packages are unavailable through the repository's mapped CI feeds.

Failed run: https://github.com/dotnet/orleans/actions/runs/32652145773

Please remove the unavailable dependency path (as in the updated Aspire provider integration approach), verify dotnet build Orleans.slnx -bl, and push a corrected head.

Copilot AI review requested due to automatic review settings August 23, 2026 16:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs:134

  • ResolveConnectionString treats "ServiceEndpoint" and its alias "Endpoint" by picking the first non-empty value, but it does not detect the case where both are configured with different values. That makes startup validation non-deterministic (one value is silently ignored) and can hide misconfiguration.
        var service = configurationSection["Service"];
        var region = configurationSection["Region"];
        var serviceEndpoint = GetFirstNonWhiteSpace(
            configurationSection["ServiceEndpoint"],
            configurationSection["Endpoint"]);
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings August 23, 2026 17:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

test/Extensions/Orleans.AWS.Tests/Orleans.AWS.Tests.csproj:23

  • These Aspire integration/live tests are effectively net10-only (Aspire.Hosting.* references are conditioned on net10.0, and the test sources are wrapped in #if NET10_0). However, the repo test TFMs are net8.0;net10.0 (test/Directory.Build.props:19) and the PR description/linked acceptance criteria call out running the Aspire-configured SQS tests on both net8.0 and net10.0. If the intent is dual-framework validation, these tests need to compile and execute for net8.0 as well (or the PR/issue criteria should be updated to match the net10-only constraint).
  <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
    <PackageReference Include="Aspire.Hosting.Orleans" />
    <PackageReference Include="Aspire.Hosting.Testing" />
  </ItemGroup>
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings August 23, 2026 18:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs:134

  • ResolveConnectionString treats ServiceEndpoint and Endpoint as aliases but silently prefers ServiceEndpoint when both are set. If both keys are present with different values, the configuration is ambiguous and should throw an OrleansConfigurationException (similar to the ServiceKey/ConnectionName validation) instead of ignoring one value.
        var service = configurationSection["Service"];
        var region = configurationSection["Region"];
        var serviceEndpoint = GetFirstNonWhiteSpace(
            configurationSection["ServiceEndpoint"],
            configurationSection["Endpoint"]);

docs/site/src/content/docs/host/snippets/aspire/AppHost/AppHost.csproj:16

  • This snippet project pins Aspire.Hosting.AWS to 13.4.0 while all other Aspire.Hosting.* references in the same project use 13.4.6. That version skew can lead to confusing dependency resolution or restore/build warnings (which are treated as errors in this repo). Consider aligning the AWS integration package version with the rest of the Aspire stack used in this snippet, or documenting why it must differ.
  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.AppHost" Version="13.4.6" />
    <PackageReference Include="Aspire.Hosting.AWS" Version="13.4.0" />
    <PackageReference Include="Aspire.Hosting.Orleans" Version="13.4.6" />
    <PackageReference Include="Aspire.Hosting.Redis" Version="13.4.6" />
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ReubenBond
ReubenBond requested a review from halter73 August 24, 2026 15:12
@ReubenBond
ReubenBond enabled auto-merge August 24, 2026 15:12
Copilot AI review requested due to automatic review settings August 24, 2026 15:43
@ReubenBond
ReubenBond force-pushed the rb-add-orleans-sqs-aspire branch from 6f736c9 to f950aff Compare August 24, 2026 15:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 16/16 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread test/Extensions/Orleans.AWS.Tests/Streaming/SQSAspireIntegrationTests.cs Outdated
Comment thread src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It introduces new public packages/APIs and provisioning/configuration behavior across runtime, tests, restore sources, and docs which warrants final human validation.

Review tier: Lite
Findings: 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity test/​Extensions/​Orleans.AWS.Tests/​Orleans.AWS.Tests.csprojMicrosoft.Testing.Platform.MSBuild is already centrally versioned in Directory.Packages.props

Comment thread test/Extensions/Orleans.AWS.Tests/Orleans.AWS.Tests.csproj

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Startup validation currently allows Service=host:port values which can silently resolve to an unintended AWS region instead of failing with an actionable configuration error.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity src/​AWS/​Orleans.Streaming.SQS/​Hosting/​SqsStreamProviderBuilder.cs — ValidateServiceLocation only treats values containing "://" as endpoints. A common misconfiguration…
Issues resolved since last review (1)
Severity Finding
Low severity test/​Extensions/​Orleans.AWS.Tests/​Orleans.AWS.Tests.csprojMicrosoft.Testing.Platform.MSBuild is already centrally versioned in Directory.Packages.propsView resolved comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

test/Extensions/Orleans.AWS.Tests/Orleans.AWS.Tests.csproj:30

  • These Roslyn package references specify VersionOverride="5.0.0", but Directory.Packages.props already updates Microsoft.CodeAnalysis.* packages to 5.0.0 for net10.0. Keeping the redundant overrides increases maintenance cost and can drift from central package management in the future.

Comment thread src/AWS/Orleans.Streaming.SQS/Hosting/SqsStreamProviderBuilder.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It introduces a new shipping Aspire bridge package with AWS CDK provisioning and cross-package validation logic (including private-member access), which warrants careful human review for long-term compatibility and supportability.

Review tier: Lite
Findings: None

Issues resolved since last review (1)
Severity Finding
High severity src/​AWS/​Orleans.Streaming.SQS/​Hosting/​SqsStreamProviderBuilder.cs — ValidateServiceLocation only treats values containing "://" as endpoints. A common misconfiguration… View resolved comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/AWS/Orleans.Streaming.SQS.Aspire/OrleansSqsStreamingExtensions.cs:247

  • ValidateServiceId relies on [UnsafeAccessor] to call a non-public OrleansService getter ("get_ServiceId"). This is brittle against upstream Aspire/Orleans integration changes (renames/signature changes can break at runtime) and can be incompatible with trimming/AOT scenarios, since it bypasses public surface-area contracts.

Consider avoiding private-member access by tracking the expected ServiceId via a resource/annotation owned by this package (and validating against that), or by using a public Aspire/Orleans API if one is available to read the configured ServiceId.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Orleans SQS integration for Aspire with end-to-end tests

2 participants