Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine the Dapr Sidecar API #574

Open
FullStackChef opened this issue Mar 13, 2025 · 7 comments
Open

Refine the Dapr Sidecar API #574

FullStackChef opened this issue Mar 13, 2025 · 7 comments

Comments

@FullStackChef
Copy link
Contributor

FullStackChef commented Mar 13, 2025

Related to an existing integration?

Yes

Existing integration

CommunityToolkit.Aspire.Hosting.Dapr

Overview

Revisit and refine the Dapr sidecar API to ensure it integrates smoothly with the overall builder pattern without breaking the chaining mechanism.

Usage example

With the release of CommunityToolkit 9.3 the following will be possible

var redis = builder.AddRedis("redis").WithRedisInsight();

var stateStore = builder.AddDaprStateStore("statestore").WithReference(redis); // <- Reference an aspire resource

var consumerId = builder.AddParameter("consumerID");

var redisPassword = builder.AddParameter("redisPassword", true);

var pubSub = builder.AddDaprPubSub("pubsub")
                    .WithMetadata("redisHost", "localhost:6379") // <- Ability to specify a metadata value
                    .WithMetadata("redisPassword", redisPassword) // <- Ability to specify a metadata secret 
                    .WithMetadata("consumerID", consumerId) // <- Ability to specify a metadata value
                    .WaitFor(redis);

From here it would be good to refine the dapr sidecar api

var daprSidecar = builder.AddDaprSidecar("sidecar") // <- Create a dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("servicea")
       .WithReference(daprSidecar) // <- reference the sidecar
       .WaitFor(redis);

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("serviceb")
       .WithReference(daprSidecar) // <- Should this be allowed or trigger an error?
       .WaitFor(redis);

and for Azure:

var daprSidecar = builder.AddAzureDaprSidecar("sidecar") // <- Create an azure dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("servicea")
       .WithReference(daprSidecar) // <- reference the sidecar
       .WaitFor(redis);

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("serviceb")
       .WithReference(daprSidecar) // <- Should this be allowed or trigger an error?
       .WaitFor(redis);

Breaking change?

Yes - but the existing api should be marked as deprecated and removed in a later version

Alternatives

Additional context

The approach above is based on that of the Orleans integration.

AddAzureDaprSidecar / AddDaprSidecar is based on the approach demonstrated by the Redis integration

Sidecar Reference:

  • Option 1: Restrict the daprSidecar resource so that it can only be referenced by a single project. An analyzer could be implemented to enforce this rule to prevent accidental misuse and ensure clarity of sidecar ownership.
  • Option 2: Allow the sidecar to be shared across multiple projects if each reference results in its own unique sidecar instance, because each reference would represent an individual sidecar instance, this would allow the sidecars to be defined by the combination of components rather than one for every resource which would be more verbose.

Help us help you

Yes, I'd like to be assigned to work on this item

@WhitWaldo
Copy link

I like the example you've got for what's coming with 9.3.

With regards to the later examples though, I'm inclined to suggest that the Dapr sidecar should not itself be independently referenceable given that each service within Dapr may have different components or different options applied to the same components (e.g. namespaces), in addition to exposing different ports.

@FullStackChef
Copy link
Contributor Author

So just to clarify, are you saying that you don't like

var daprSidecar = builder.AddAzureDaprSidecar("sidecar") // <- Create an azure dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

or the following:

BAD

var daprSidecar = builder.AddAzureDaprSidecar("sidecar") // <- Create an azure dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("servicea")
       .WithReference(daprSidecar) // <- reference the sidecar
       .WaitFor(redis);

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("serviceb")
       .WithReference(daprSidecar) // <- Trigger an error "A sidecar resource can only be referenced by one application"
       .WaitFor(redis);

GOOD

var daprSidecar1 = builder.AddAzureDaprSidecar("sidecara") // <- Create an azure dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("servicea")
       .WithReference(daprSidecar1) // <- reference the sidecar
       .WaitFor(redis);

var daprSidecar2 = builder.AddAzureDaprSidecar("sidecarb") // <- Create an azure dapr sidecar
                         .WithReference(stateStore) // <- reference a dapr component
                         .WithReference(pubSub); // <- reference another dapr component

builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("serviceb")
       .WithReference(daprSidecar2) 
       .WaitFor(redis);

@oising
Copy link

oising commented Mar 19, 2025

What is an "azure" dapr sidecar with respect to a regular one? If you mean the former would be dapr in ACA, wouldn't this just be a distinction made by the publishing target, and not something you need to put in the apphost?

@FullStackChef
Copy link
Contributor Author

@oising its the same with the sql and redis integrations which expose Add and AddAzure methods

Ultimately there are additional packages required for supporting publishing to azure and the alternative to this separation is bloating the main package

An alternative to this is what I've currently done, which was to reference shared code files in two packages

  • Hosting.Dapr
  • Hosting.Azure.Dapr

This still requires an explicit change but it's at the package level rather than the api level

The downside to this is that installing both packages causes conflicts so you still have to make an upfront choice.

Additionally it would limit the ability to build component level integrations that can be shared across the two

@oising
Copy link

oising commented Mar 19, 2025

I'm not really following the distinction. Mssql and azure Sql are genuinely two distinct products with differing features, as are azure redis and redis. Dapr is... Dapr, no? It seems like an unnecessary abstraction/complication IMHO

@FullStackChef
Copy link
Contributor Author

You could be right, which of the differences between sql /redis and their azure counterparts require the difference in apphost registration (I'm using the same client packages and code in my applications)?

You are welcome to contribute an alternative approach, this is the best I could come up with on my own

@oising
Copy link

oising commented Mar 20, 2025

@FullStackChef Ping/DM me on discord, Brett -- might be easier to chat about the challenges there in real time.

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

No branches or pull requests

3 participants