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

[Feature] First class support for Azure App Configuration Feature Management #3053

Open
Jonny-Freemarket opened this issue Apr 11, 2024 · 1 comment

Comments

@Jonny-Freemarket
Copy link

Azure App Configuration has a Feature Manager that allows you to toggle features on and off. These feature switch values can refreshed as part of the HTTP pipeline in ASP.NET Core, or by explicitly refreshing them with the Azure App Configuration SDK.

Brighter has the IAmAFeatureSwitchRegistry that allows for the Azure App Configuration Feature Manager to be used to control whether a Brighter handler runs or not in the pipeline. The basic building blocks of this are:

Configure the Azure App Configuration SDK to use Feature Manager

builder.Configuration
          .AddAzureAppConfiguration(options =>
          {
             ...
              
              options.Connect(..)
                  ...
                  .UseFeatureFlags(opts => opts.Select("YourServiceName_*", "flags"))
                  .ConfigureRefresh(refresh => refresh.Register("FeatureManagement").SetCacheExpiration(TimeSpan.FromSeconds(30)));
              
              builder.Services.AddSingleton(options.GetRefresher());
          });

Implement concrete IAmAFeatureSwitchRegistry

public class AppConfigurationFeatureSwitchRegistry : IAmAFeatureSwitchRegistry
{
    private readonly IFeatureManagerSnapshot _featureManager;
    private readonly IConfigurationRefresher _configurationRefresher;

    public AppConfigurationFeatureSwitchRegistry(IFeatureManagerSnapshot featureManager, IConfigurationRefresher configurationRefresher)
    {
        _featureManager = featureManager;
        _configurationRefresher = configurationRefresher;
    }

    public FeatureSwitchStatus StatusOf(Type handler)
    {
        ...
        // Removed for brevity
        ...
    }

    // As Brighter handlers not always part of an HTTP pipeline we have to force a refresh of the feature flags
    private async Task<bool?> CheckFeatureFlags(string feature)
    {
        await _configurationRefresher.TryRefreshAsync();

        await foreach (var featureName in _featureManager.GetFeatureNamesAsync())
        {
            if (featureName == feature)
                return await _featureManager.IsEnabledAsync(feature);
        }

        return null;
    }

    // If I feature switch is not found, but the handler is decorated with the attribute then
    // then the handler will still be allowed to run
    public MissingConfigStrategy MissingConfigStrategy { get; set; } = MissingConfigStrategy.SilentOn;
}

Decorating Brighter Handler with Feature Switch

...
[FeatureSwitchAsync(typeof(YourCommandHandler), FeatureSwitchStatus.Config, 0)]
public override async Task<YourCommand> HandleAsync(YourCommandmessage, CancellationToken cancellationToken = new CancellationToken())
{
    ...
}
...

Proposed Change

  • We wrap up the required plumbing into extension methods / bundled classes
  • Introduce a new Brighter attribute to use instead of the [FeatureSwitchAsync(..)] attribute, something like:

[AppConfigurationFeatureSwitchAsync(nameof(YourCommandHandler), 0)]

@iancooper
Copy link
Member

Looks good to me.

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

No branches or pull requests

3 participants