orleans icon indicating copy to clipboard operation
orleans copied to clipboard

Unable to use Streaming with Aspire configured queue storage

Open abbottdev opened this issue 1 year ago • 2 comments

Hi,

I've attached a repo project here: https://github.com/abbottdev/orleans-aspire-repo

I'm unable to start the linked repository, I receive an start-up error I believe as the Aspire configuration/environment variable/di registration isn't quite right.

The UseOrleans call fails with the following stack trace:

Exception has occurred: CLR/System.InvalidOperationException
Exception thrown: 'System.InvalidOperationException' in Orleans.Runtime.dll: 'Could not find Streaming provider named 'AzureQueueStorage'. This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced by your application.'
   at Orleans.Hosting.DefaultSiloServices.<ApplyConfiguration>g__GetRequiredProvider|2_3(Dictionary`2 knownProviderTypes, String kind, String name)
   at Orleans.Hosting.DefaultSiloServices.<ApplyConfiguration>g__ConfigureProvider|2_2(ISiloBuilder builder, Dictionary`2 knownProviderTypes, String kind, String name, IConfigurationSection configurationSection)
   at Orleans.Hosting.DefaultSiloServices.<ApplyConfiguration>g__ApplyNamedSubsections|2_6(ISiloBuilder builder, IConfigurationSection cfg, Dictionary`2 knownProviderTypes, String sectionName)
   at Orleans.Hosting.DefaultSiloServices.ApplyConfiguration(ISiloBuilder builder)
   at Orleans.Hosting.DefaultSiloServices.AddDefaultServices(ISiloBuilder builder)
   at Orleans.Hosting.SiloBuilder..ctor(IServiceCollection services, IConfiguration configuration)
   at Microsoft.Extensions.Hosting.OrleansSiloGenericHostExtensions.AddOrleansCore(IServiceCollection services, IConfiguration configuration)
   at Microsoft.Extensions.Hosting.OrleansSiloGenericHostExtensions.UseOrleans(IHostApplicationBuilder hostAppBuilder, Action`1 configureDelegate)
   at Microsoft.Extensions.Hosting.OrleansSiloGenericHostExtensions.UseOrleans(IHostApplicationBuilder hostAppBuilder)
   at Program.<<Main>$>d__0.MoveNext() in c:\Repos\Gymotion\OrleansSample.Service\Program.cs:line 9

I believe the fix required here is similar to https://github.com/dotnet/aspire/issues/4010 and potentially the fix for https://github.com/dotnet/orleans/pull/9045 is the same that's required here for streaming.

Operating system: Windows 11 Package versions:

    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
    <PackageReference Include="Aspire.Azure.Data.Tables" Version="8.0.2" />
    <PackageReference Include="Aspire.Azure.Storage.Blobs" Version="8.0.1" />
    <PackageReference Include="Aspire.Azure.Storage.Queues" Version="8.0.2" />
    <PackageReference Include="Microsoft.Orleans.Server" Version="8.2.0" />
    <PackageReference Include="Microsoft.Orleans.Sdk" Version="8.2.0" />
    <PackageReference Include="Microsoft.Orleans.Persistence.AzureStorage" Version="8.2.0" />
    <PackageReference Include="Microsoft.Orleans.Clustering.AzureStorage" Version="8.2.0" />
    <PackageReference Include="Microsoft.Orleans.Reminders.AzureStorage" Version="8.2.0" />
    <PackageReference Include="Microsoft.Orleans.Streaming.AzureStorage" Version="8.2.0" />

abbottdev avatar Jul 22 '24 20:07 abbottdev

https://github.com/dotnet/orleans/pull/8929

tskimmett avatar Sep 27 '24 12:09 tskimmett

I was able to get this working for the time being using the following "hack."

  1. Add the storage account queue reference directly to the Silo project instead of Orleans.
  2. Use the various Configure extension methods to configure Orleans manually as you would without using Aspire.

In the Aspire AppHost Program.cs:

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage").RunAsEmulator();
var clusteringTable = storage.AddTables("clustering");
var pubSubTable = storage.AddTables("pubsub");
var grainStorage = storage.AddBlobs("grain-state");
var streamingQueue = storage.AddQueues("streaming");

var orleans = builder.AddOrleans("default")
    .WithClustering(clusteringTable)
    .WithGrainStorage("Default", grainStorage)
    .WithGrainStorage("PubSubStore", pubSubTable);

var silo = builder.AddProject<Projects.Distributed_Host>("silo")
    .WithReference(orleans)
    .WithReference(streamingQueue)
    .WithExternalHttpEndpoints();

builder.Build().Run();

And then in the silo project Program.cs:

using Azure.Storage.Queues;
using Distributed.Abstractions;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedAzureTableClient("clustering");
builder.AddKeyedAzureTableClient("pubsub");
builder.AddKeyedAzureBlobClient("grain-state");
builder.AddKeyedAzureQueueClient("streaming");

builder.UseOrleans(silo =>
{
    silo.AddAzureQueueStreams("AzureQueueProvider", (SiloAzureQueueStreamConfigurator configurator) =>
    {
        configurator.ConfigureAzureQueue(options =>
        {
            options.Configure<IServiceProvider>((queueOptions, sp) =>
            {
                queueOptions.QueueServiceClient = sp.GetKeyedService<QueueServiceClient>("streaming");
            });
        });
    });
});

var app = builder.Build();

app.MapDefaultEndpoints();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.Run();

rjygraham avatar Oct 17 '24 16:10 rjygraham

This is working as of 9.1.1 and can probably be closed. @ReubenBond

I have tested it here: https://github.com/jsedlak/orleans-samples/tree/main/azure-storage

jsedlak avatar Feb 13 '25 11:02 jsedlak