- 
                Notifications
    You must be signed in to change notification settings 
- Fork 132
feat(dapr): add IValueProvider support for component metadata configuration #810
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
feat(dapr): add IValueProvider support for component metadata configuration #810
Conversation
Implements IResourceWithWaitSupport for IDaprSidecarResource to enable proper service startup sequencing. This allows Dapr sidecars to wait for dependent services (like Redis for pubsub) to be ready before starting, preventing component loading failures during application startup. Fixes CommunityToolkit#604 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Added new WithMetadata overload that accepts EndpointReference parameter - Extracts URL from EndpointReference for metadata configuration - Added comprehensive tests for the new functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…tern - Removed placeholder values from DaprDistributedApplicationLifecycleHook - Replaced with cleaner hasValueProviders flag for tracking value providers - Consolidated tests from EndpointReferenceTests into ResourceBuilderExtensionsTests - Deleted redundant EndpointReferenceTests.cs file - All tests pass with cleaner separation of concerns 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
| /// Represents a Dapr sidecar resource. | ||
| /// </summary> | ||
| public interface IDaprSidecarResource : IResource | ||
| public interface IDaprSidecarResource : IResource, IResourceWithWaitSupport | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you implement the waiting? To make this work, the resource needs a lifecycle, see https://github.com/dotnet/aspire/blob/main/docs/specs/appmodel.md#built-in-resources--lifecycle.
When you implement IResourceWithWaitSupport, at some point you have to raise https://github.com/dotnet/aspire/blob/364382724b4cd3590ec75010525ce36ef0b5e769/src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs#L92
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented it, don't know if it's the correct approach but I followed the examples. Also implemented on the IDaprComponentResource as it seems it was missing support
…ation - Add comprehensive XML documentation for WithMetadata method explaining runtime value resolution - Implement DaprSidecarAvailableEvent for sidecar lifecycle tracking - Add automatic dependency detection and wait logic for value provider resources - Ensure sidecars wait for dependent resources before starting - Add proper state management for sidecar resources (NotStarted -> Starting -> Running) - Improve error handling with FailedToStart state on initialization errors This improves reliability when using dynamic endpoint references and ensures proper initialization order. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…ifecycle - Add SetupComponentLifecycle method to configure WaitAnnotations for Dapr components - Extract resource dependencies from value provider annotations - Ensure components wait for their dependencies before becoming ready - Follow the same pattern as SetupSidecarLifecycle for consistency This ensures proper dependency ordering when Dapr components reference other resources through value providers, preventing initialization failures. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…e parent resource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for using IValueProvider (including EndpointReference) in Dapr component metadata configuration, enabling dynamic endpoint resolution at runtime while maintaining backward compatibility.
Key changes include:
- Added new WithMetadataoverload acceptingIValueProviderfor flexible metadata configuration
- Implemented deferred value resolution through environment variables and secretKeyRef mechanism
- Enhanced lifecycle management with proper dependency tracking and state management for Dapr sidecars
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description | 
|---|---|
| src/Shared/Dapr/Core/DaprMetadataResourceBuilderExtensions.cs | Added new WithMetadata overload for IValueProvider with environment variable generation and secretKeyRef configuration | 
| src/Shared/Dapr/Core/DaprDistributedApplicationLifecycleHook.cs | Enhanced lifecycle hook with value provider resolution, dependency management, and async environment variable setup | 
| src/Shared/Dapr/Core/DaprComponentValueProviderAnnotation.cs | New annotation class to track value providers requiring deferred resolution | 
| src/Shared/Dapr/Core/DaprComponentSchema.cs | Added async value resolution capabilities and new metadata provider type | 
| src/Shared/Dapr/Core/IDistributedApplicationComponentBuilderExtensions.cs | Enhanced sidecar lifecycle with dependency tracking, state management, and proper event publishing | 
| src/Shared/Dapr/Core/IDaprSidecarResource.cs | Added IResourceWithWaitSupport interface for proper dependency management | 
| src/Shared/Dapr/Core/DaprSidecarEvents.cs | New event class for Dapr sidecar availability notifications | 
| src/Shared/Dapr/Core/DaprComponentMetadataAnnotation.cs | Updated annotation to support async configuration with cancellation tokens | 
| tests/dapr-shared/ResourceBuilderExtensionsTests.cs | Added comprehensive tests for EndpointReference metadata configuration and value provider resolution | 
| tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs | Added test verifying sidecar WaitFor functionality | 
| examples/dapr/CommunityToolkit.Aspire.Hosting.Dapr.AppHost/Program.cs | Updated example to demonstrate Redis endpoint usage with the new IValueProvider feature | 
| Properties = [], | ||
| ResourceType = "DaprSidecar", | ||
| IsHidden = true, | ||
| State = KnownResourceStates.NotStarted | 
    
      
    
      Copilot
AI
    
    
    
      Aug 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The State property assignment should be moved to after the resource is created but before the configureSidecar call, as the configureSidecar callback might expect the resource to have an initial state set.
| daprSidecar.Annotations.Add(new EnvironmentCallbackAnnotation(async context => | ||
| { | ||
| foreach (var secret in secrets) | ||
| { | ||
| context.EnvironmentVariables.TryAdd(secret.Key, secret.Value); | ||
| } | ||
|  | ||
|  | ||
| // Add value provider references | ||
| foreach (var (envVarName, valueProvider) in endpointEnvironmentVars) | ||
| { | ||
| var value = await valueProvider.GetValueAsync(context.CancellationToken); | ||
| context.EnvironmentVariables.TryAdd(envVarName, value ?? string.Empty); | ||
| } | 
    
      
    
      Copilot
AI
    
    
    
      Aug 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The EnvironmentCallbackAnnotation constructor expects a synchronous delegate, but an async lambda is being passed. This could lead to fire-and-forget behavior where exceptions are swallowed. Consider using a synchronous approach or ensure proper exception handling.
| daprSidecar.Annotations.Add(new EnvironmentCallbackAnnotation(async context => | |
| { | |
| foreach (var secret in secrets) | |
| { | |
| context.EnvironmentVariables.TryAdd(secret.Key, secret.Value); | |
| } | |
| // Add value provider references | |
| foreach (var (envVarName, valueProvider) in endpointEnvironmentVars) | |
| { | |
| var value = await valueProvider.GetValueAsync(context.CancellationToken); | |
| context.EnvironmentVariables.TryAdd(envVarName, value ?? string.Empty); | |
| } | |
| // Precompute all value provider results asynchronously | |
| var precomputedEnvVars = new Dictionary<string, string>(); | |
| foreach (var secret in secrets) | |
| { | |
| precomputedEnvVars[secret.Key] = secret.Value; | |
| } | |
| foreach (var (envVarName, valueProvider) in endpointEnvironmentVars) | |
| { | |
| // Synchronously block here to get the value | |
| // (since we're already in an async method, this is safe) | |
| var value = valueProvider.GetValueAsync(cancellationToken).GetAwaiter().GetResult(); | |
| precomputedEnvVars[envVarName] = value ?? string.Empty; | |
| } | |
| daprSidecar.Annotations.Add(new EnvironmentCallbackAnnotation(context => | |
| { | |
| foreach (var kvp in precomputedEnvVars) | |
| { | |
| context.EnvironmentVariables.TryAdd(kvp.Key, kvp.Value); | |
| } | 
| [YamlMember(Order = 2)] | ||
| public required string Value { get; set; } | ||
| } | ||
|  | 
    
      
    
      Copilot
AI
    
    
    
      Aug 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This internal class lacks XML documentation comments. As it's a key component for value provider functionality, it should have proper documentation explaining its purpose and usage.
| /// <summary> | |
| /// Represents a Dapr component spec metadata item whose value is provided by an <see cref="IValueProvider"/> and can be resolved asynchronously. | |
| /// </summary> | 
| Here's the example: WaitForRecording.mov | 
| @gabynevada just checking the state of the PR - are you wanting this re-reviewed? is it ready to merge? | 
…ations Instead of passing WaitAnnotations from components to the Dapr CLI, components now: - Manage their own lifecycle state (NotStarted -> Starting -> Running) - Wait directly for their dependencies via WaitAnnotations - CLI resources wait for component resources to be ready This provides clearer dependency semantics where resources wait for configuration resources, which in turn wait for their actual dependencies. The refactoring follows the established SetupSidecarLifecycle pattern for consistency. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Components are long-lived configuration resources that should reach "Running" state and stay there. Using WaitForCompletion was incorrect as it expected components to reach "Completed" state. Now using WaitType.WaitUntilHealthy which properly waits for resources to be in a healthy/running state, matching the component lifecycle. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
| @FullStackChef was occupied on work so could not do the final changes. Pushed the final changes so that the dapr component resources have a lifecycle and thus other resources can wait for them to get to the running state. Let me know if anything needs to be changed! | 
Summary
IValueProvider(includingEndpointReference) in Dapr component metadata configurationChanges
WithMetadataoverload acceptingIValueProviderfor flexible metadata configurationDaprComponentValueProviderAnnotationto track value providers requiring resolutionDaprComponentSchemawith async value resolution capabilitiesTest Plan
Example Usage
This allows Dapr components to dynamically reference Aspire resource endpoints that are only known at runtime.
Closes #604