Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
64ec40f
feat: Implement event handling infrastructure in MultiProvider
askpt Aug 26, 2025
22a0887
feat: Implement event processing for MultiProvider
askpt Aug 26, 2025
c9f8699
feat: Enhance event handling in MultiProvider with improved status ma…
askpt Aug 26, 2025
084dbc0
feat: Add event emission for ProviderConfigurationChanged in MultiPro…
askpt Aug 26, 2025
0fe44b4
feat: Implement graceful shutdown for event processing in MultiProvider
askpt Aug 26, 2025
5e311c9
feat: Add error handling and event emission for evaluation failures i…
askpt Aug 26, 2025
89a25de
feat: Update test name for EvaluateAsync to reflect error handling fo…
askpt Aug 26, 2025
acc911b
feat: Add unit tests for event emission in MultiProvider
askpt Aug 26, 2025
4688602
feat: Enhance MultiProvider event tests with initialization and error…
askpt Aug 26, 2025
f6b9459
feat: Refactor event emission test for error state in MultiProvider
askpt Aug 26, 2025
f4e3dfd
feat: Refactor MultiProvider event tests for improved readability and…
askpt Aug 26, 2025
9fe5338
feat: Refactor MultiProvider event tests for improved clarity and con…
askpt Aug 26, 2025
f511821
feat: Improve event handling logic in MultiProvider for better perfor…
askpt Aug 26, 2025
0477338
feat: Add event handling documentation for MultiProvider
askpt Aug 27, 2025
445fdae
feat: Dispose event processing cancellation token in MultiProvider sh…
askpt Aug 29, 2025
518cd52
feat: Implement thread-safe access to provider status in MultiProvider
askpt Sep 5, 2025
cc0cb58
Replace Dictionary with ConcurrentDictionary for event listening task…
askpt Sep 5, 2025
bf29cb8
feat: Safeguard against ObjectDisposedException during event processi…
askpt Sep 5, 2025
7f2d259
Merge branch 'main' into askpt/552-feature-implement-events-in-multi-…
askpt Sep 11, 2025
406e408
Update src/OpenFeature.Providers.MultiProvider/MultiProvider.cs
askpt Sep 11, 2025
98c2d31
fix: prevent duplicate event listening tasks for registered providers
askpt Sep 26, 2025
0ca0a86
feat: enhance MultiProvider to include logging and prevent duplicate …
askpt Sep 26, 2025
2574dba
Merge branch 'main' into askpt/552-feature-implement-events-in-multi-…
askpt Sep 26, 2025
a70d9c0
refactor: remove unused config folder and reorganize test project ent…
askpt Sep 29, 2025
de418d7
Merge remote-tracking branch 'refs/remotes/origin/askpt/552-feature-i…
askpt Sep 29, 2025
4cfdb9b
fix: prevent duplicate event listening by checking existing tasks bef…
askpt Sep 29, 2025
8eb027a
fix: clear event listening tasks during provider shutdown
askpt Sep 29, 2025
a4814ba
fix: streamline event listening task addition by using TryAdd method
askpt Oct 2, 2025
edd102a
fix: remove setting of ProviderStatus to Fatal during shutdown
askpt Oct 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions OpenFeature.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
<File Path="renovate.json" />
<File Path="version.txt" />
</Folder>
<Folder Name="/.root/.config/">
<File Path=".config/dotnet-tools.json" />
</Folder>
<Folder Name="/.root/.github/" />
<Folder Name="/.root/.github/ISSUE_TEMPLATE/">
<File Path=".github/ISSUE_TEMPLATE/bug.yaml" />
Expand Down Expand Up @@ -59,14 +56,14 @@
<File Path="src/Directory.Build.targets" />
</Folder>
<Folder Name="/test/">
<Project Path="test/OpenFeature.AotCompatibility/OpenFeature.AotCompatibility.csproj" />
<Project Path="test/OpenFeature.Benchmarks/OpenFeature.Benchmarks.csproj" />
<Project Path="test/OpenFeature.DependencyInjection.Tests/OpenFeature.DependencyInjection.Tests.csproj" />
<Project Path="test/OpenFeature.E2ETests/OpenFeature.E2ETests.csproj" />
<Project Path="test/OpenFeature.Hosting.Tests/OpenFeature.Hosting.Tests.csproj" />
<Project Path="test/OpenFeature.IntegrationTests/OpenFeature.IntegrationTests.csproj" />
<Project Path="test/OpenFeature.Tests/OpenFeature.Tests.csproj" />
<Project Path="test/OpenFeature.AotCompatibility/OpenFeature.AotCompatibility.csproj" />
<Project Path="test/OpenFeature.Providers.MultiProvider.Tests/OpenFeature.Providers.MultiProvider.Tests.csproj" />
<Project Path="test/OpenFeature.Tests/OpenFeature.Tests.csproj" />
<File Path="test/Directory.Build.props" />
</Folder>
</Solution>
</Solution>
338 changes: 319 additions & 19 deletions src/OpenFeature.Providers.MultiProvider/MultiProvider.cs

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions src/OpenFeature.Providers.MultiProvider/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,69 @@ await multiProvider.ShutdownAsync();
await multiProvider.DisposeAsync();
```

## Events

The MultiProvider supports OpenFeature events and provides specification-compliant event handling. It follows the [OpenFeature Multi-Provider specification](https://openfeature.dev/specification/appendix-a#status-and-event-handling) for event handling behavior.

### Event Handling Example

```csharp
using OpenFeature;
using OpenFeature.Providers.MultiProvider;

// Create the MultiProvider with multiple providers
var providerEntries = new[]
{
new ProviderEntry(new ProviderA(), "provider-a"),
new ProviderEntry(new ProviderB(), "provider-b")
};
var multiProvider = new MultiProvider(providerEntries);

// Subscribe to MultiProvider events
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, (eventDetails) =>
{
Console.WriteLine($"MultiProvider is ready: {eventDetails?.ProviderName}");
});

Api.Instance.AddHandler(ProviderEventTypes.ProviderStale, (eventDetails) =>
{
Console.WriteLine($"MultiProvider became stale: {eventDetails?.Message}");
});

Api.Instance.AddHandler(ProviderEventTypes.ProviderConfigurationChanged, (eventDetails) =>
{
Console.WriteLine($"Configuration changed - Flags: {string.Join(", ", eventDetails?.FlagsChanged ?? [])}");
});

Api.Instance.AddHandler(ProviderEventTypes.ProviderError, (eventDetails) =>
{
Console.WriteLine($"MultiProvider error: {eventDetails?.Message}");
});

// Set the provider - this will initialize all underlying providers
// and emit PROVIDER_READY when all are successfully initialized
await Api.Instance.SetProviderAsync(multiProvider);

// Later, if an underlying provider becomes stale and changes MultiProvider status:
// Only then will a PROVIDER_STALE event be emitted from MultiProvider
```

### Event Lifecycle

1. **During Initialization**:

- MultiProvider emits `PROVIDER_READY` when all underlying providers initialize successfully
- MultiProvider emits `PROVIDER_ERROR` if any providers fail to initialize (causing aggregate status to become ERROR/FATAL)

2. **Runtime Status Changes**:

- Status-changing events from underlying providers are captured internally
- MultiProvider only emits events when its aggregate status changes due to these internal events
- Example: If MultiProvider is READY and one provider becomes STALE, MultiProvider emits `PROVIDER_STALE`

3. **Configuration Changes**:
- `PROVIDER_CONFIGURATION_CHANGED` events from underlying providers are always re-emitted

## Requirements

- .NET 8+
Expand Down
1 change: 1 addition & 0 deletions src/OpenFeature/OpenFeature.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<InternalsVisibleTo Include="OpenFeature.Tests" />
<InternalsVisibleTo Include="OpenFeature.E2ETests" />
<InternalsVisibleTo Include="OpenFeature.DependencyInjection" />
<InternalsVisibleTo Include="OpenFeature.Providers.MultiProvider" />
<InternalsVisibleTo Include="OpenFeature.Providers.MultiProvider.Tests" />
<None Include="../../README.md" Pack="true" PackagePath="/" />
</ItemGroup>
Expand Down
Loading