The Twelve-Factor App methodology describes treating backing resources as “attached resources”, so how do you ensure connectivity to FeatureBoard is as resilient as possible? The FeatureBoard SDK provides a fallback mechanism for you to maintain a copy of Features and its Audience Exceptions using a concept called an External State Store. When accessing features via the FeatureBoard SDK, if an External State Store is provided and connectivity is lost to FeatureBoard (e.g. perhaps by a severed Internet connection), the SDK will have fallback values for Features and its Audience Exceptions
Let’s start by adding the FeatureBoard .NET SDK to our project:
dotnet add package FeatureBoard.DotnetSdk
then creating a class that implements the IFeatureBoardExternalState
:
using FeatureBoard.DotnetSdk.Models;
using FeatureBoard.DotnetSdk.States;
public class MyExternalState: IFeatureBoardExternalState
{
public Task<IReadOnlyCollection<FeatureConfiguration>> GetState(CancellationToken cancellationToken)
{
// TODO: implement me
}
public Task UpdateState(IReadOnlyCollection<FeatureConfiguration> features, CancellationToken cancellationToken)
{
// TODO: implement me
}
}
Next let's make sure the new state store is registered in Program.cs:
builder.Services.AddFeatureBoard<WeatherFeatures, QueryStringAudienceProvider>()
.WithPollingUpdateStrategy()
.WithExternalState<MyExternalState>();
OK that’s the easy part done - how can we ensure this newly configured External State Store is as resilient as possible? Let’s say you have a Web Application that is already rated Highly Available by means of geo-redundancy or some other mechanism - let’s ensure the External state store is backed by a resource that is also Highly Available!
It is important to understand that with a fleet of Web Applications interacting with an External State Store, the FeatureBoard SDK will preference values that are “written last”. As such, please select a location for your External State store that can handle synchronous writes without blocking. Examples include:
A RDBMS (e.g. Azure SQL Server, MySQL)
A Cloud Storage Service (e.g. Azure Blob Storage, AWS S3)
In-Memory distributed state storage (e.g. REDIS)
So, for our example suppose your Web Application is hosted in a scaled Azure App Service and your organisation has Geo-Redundant Premium Azure Blob Storage
In the above example let's go ahead and create a service for writing to a blob store and wire it in to our External State Store. In the below example the MyStateStoreWriter class should contain implementation specifics for your chosen External State Store (e.g. how to write to an Azure Blob Store):
Program.cs:
services.AddTransient<MyStateStoreWriter>();
Now let’s update our state store:
using FeatureBoard.DotnetSdk.Models;
namespace MyApplication.State;
public class MyExternalState: IFeatureBoardExternalState
// This interface should handle fetching/updating State as required depending
// on where it may be hosted.
private IMyStateStoreWriter _stateStoreWriter;
public MyExternalState(IStateStoreWriter stateStoreWriter)
{
this._stateStoreWriter = stateStoreWriter;
}
public async Task<IReadOnlyCollection<FeatureConfiguration>> GetState(CancellationToken cancellationToken)
{
// i.e. will return a copy of the last written set of Features/Audiences
return await _stateStoreWriter.GetState(cancellationToken);
}
public async Task UpdateState(IReadOnlyCollection<FeatureConfiguration> features, CancellationToken cancellationToken)
{
// i.e. update the underlying data store with an updated state store values
await _stateStoreWriter.UpdateState(features, cancellationToken);
}
There you go! You’ve implemented a simple External State store with the FeatureBoard SDK! You should now be able to ensure all of your Highly Available Application nodes/instances have direct access to a more resilient set of Features and its Audience Exceptions.
Be sure to check FeatureBoard.DotnetSdk on NuGet for the latest updates to the .NET SDK.