microsoft / FeatureManagement-Dotnet

Microsoft.FeatureManagement provides standardized APIs for enabling feature flags within applications. Utilize this library to secure a consistent experience when developing applications that use patterns such as beta access, rollout, dark deployments, and more.
MIT License
1.03k stars 111 forks source link

Caching for a custom FeatureDefinitionProvider #367

Open tahazayed opened 7 months ago

tahazayed commented 7 months ago

I am building a custom FeatureDefinitionProvider and I want to support caching for it, but this interface IFeatureDefinitionProviderCacheable is internal; would you please change it to be public?

thompson-tomo commented 7 months ago

Why don't you implement a configuration provider to fetch you feature flag definitions, that way the config layer would act as the caching?

tahazayed commented 7 months ago

I am using the same way as tests/Tests.FeatureManagement/InMemoryFeatureDefinitionProvider.cs, in either way, I need IFeatureDefinitionProviderCacheable to be public to use the caching as ConfigurationFeatureDefinitionProvider depends on IFeatureDefinitionProviderCacheable to support caching

thompson-tomo commented 7 months ago

You shouldn't need to add that interface to your provider given it is simply to alter handling for test cases and is not needed in actual use case. Please try it without and also what i would be doing is, implementing your provider as a configuration provider that way you definitions are immediately cached for the library to use.

jimmyca15 commented 7 months ago

@tahazayed Indeed this functionality should be available to you.

@rossgrambo this conversation mentions a plan to open up this functionality and to file an issue. Are we tracking it?

rossgrambo commented 7 months ago

No, I don't believe it was ever tracked. I'll treat this as the tracking task and look into it.

tahazayed commented 7 months ago

@jimmyca15 , @rossgrambo Thank you. In my circumstances, the alternative SaaS dynamic feature management costs $20,000 per month.

rossgrambo commented 7 months ago

Hey @tahazayed, thanks for letting us know. I want to align on our different caching to ensure you're getting the caching you want.

IFeatureDefinitionProviderCacheable is an interface that enables a specific cache. This cache is for the binding of IConfiguration to a specific class. For our TimeWindowFilter- this cache prevents IConfiguration.Get() from firing too much, as this type conversion is expensive a few ms, and can be reduced to roughly ~1/100th of the time with this cache.

Separately, there's the more common caching concern- Feature Flags from a server being supplied to the Feature Management library. FeatureManagement reads flags though the IFeatureDefinitionProvider injected dependency. FeatureManagement does not handle caching in this way, instead, it will always request feature definitions directly from the provider. The provider is in charge of caching or to pull from a cache. The provided ConfigurationFeatureDefinitionProvider pulls from IConfiguration, which is essentially our cache for the flag data. Our server provider (Azure App Configuration's .NET Provider), updates the Configuration in order to dynamically update flags. This is what @thompson-tomo was referring to when they said the "config layer would act as the caching".

Being described like this, @tahazayed, which caching were you hoping to take advantage of?

I'll work on making IFeatureDefinitionProviderCacheable public / opening up that performance gain caching either way, but I don't want you to wait on it if it's not the cache you care about.

tahazayed commented 7 months ago

Thank you for letting me know. I think I want to use what @thompson-tomo is referring to. Do you have an example of how to inject a custom configuration definition provider?

thompson-tomo commented 7 months ago

@tahazayed easiest way i have found is to follow the example from Microsoft: https://learn.microsoft.com/en-us/dotnet/core/extensions/custom-configuration-provider and look at some of the samples around.

tahazayed commented 7 months ago

I wonder where the cache configuration is and when it became invalid, as it seems after implementation, the cache lasts forever

thompson-tomo commented 7 months ago

configuration never expires, it is up to the configuration provider to implement an update/expiration mechanism

tahazayed commented 7 months ago

What is the value of using it (other than modularity)? I get the same result as using AppSettings.json

thompson-tomo commented 7 months ago

Value of using a custom configuration provider? Benefit is you can source your feature flags from an external system with the config provider doing the transformation to a dictionary hence making it usable.

tahazayed commented 7 months ago

I can achieve the same with a custom FeatureDefinitionProvider as I have to implement a cachig with expiration myself anyway, Also, if I use a configuration provider, I have to hide a property called "Data" from the base class ConfigurationProvider to get the caching work

thompson-tomo commented 7 months ago

would work it work for you to simply periodically reload your config after an interval has elapsed? From memory this is what Azure does and can all be achieved by your custom config provider.

tahazayed commented 7 months ago

It is more complex than FeatureDefinitionProvider as per the proposed solution I have to build a background job and keep it running with a timer to reload the configuration. Thank you anyway

thompson-tomo commented 7 months ago

I don't think it is as complex as you are thinking. Perhaps take a look at: https://learn.microsoft.com/en-us/azure/azure-app-configuration/enable-dynamic-configuration-dotnet-core?tabs=core6x

tahazayed commented 6 months ago

I have tried it; I had to write three classes instead of one.