Skip to content

Commit

Permalink
Merge branch 'main' into feat/flipt-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitryrogov authored Apr 30, 2024
2 parents 8160721 + 6108d45 commit c04e8a1
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"src/OpenFeature.Contrib.Providers.Flagsmith": "0.1.6",
"src/OpenFeature.Contrib.Providers.ConfigCat": "0.0.2",
"src/OpenFeature.Contrib.Providers.FeatureManagement": "0.0.1",
"src/OpenFeature.Contrib.Providers.Statsig": "0.0.3"
"src/OpenFeature.Contrib.Providers.Statsig": "0.0.4"
}
2 changes: 1 addition & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
#
# Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-dotnet/workgroup.yaml
#
* @open-feature/sdk-dotnet-maintainers
* @open-feature/sdk-dotnet-maintainers @open-feature/sdk-dotnet-approvers
10 changes: 6 additions & 4 deletions src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public sealed class FlagdProvider : FeatureProvider
{
const string ProviderName = "flagd Provider";
private readonly FlagdConfig _config;
private ProviderStatus _status;
private ProviderStatus _status = ProviderStatus.NotReady;
private readonly Metadata _providerMetadata = new Metadata(ProviderName);

private readonly Resolver.Resolver _resolver;
Expand Down Expand Up @@ -118,11 +118,13 @@ public override Task Initialize(EvaluationContext context)
{
await _resolver.Init();
_status = ProviderStatus.Ready;
}).ContinueWith((t) =>
{
_status = ProviderStatus.Error;
if (t.IsFaulted) throw t.Exception;
if (t.IsFaulted)
{
_status = ProviderStatus.Error;
throw t.Exception;
};
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Flagsmith" Version="5.2.2" />
<PackageReference Include="Flagsmith" Version="5.3.0" />
<PackageReference Include="System.Text.Json" Version="8.0.3" />
</ItemGroup>

Expand Down
8 changes: 8 additions & 0 deletions src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [0.0.4](https://github.com/open-feature/dotnet-sdk-contrib/compare/OpenFeature.Contrib.Providers.Statsig-v0.0.3...OpenFeature.Contrib.Providers.Statsig-v0.0.4) (2024-04-16)


### 🐛 Bug Fixes

* Fix Statsig nuget package name ([#172](https://github.com/open-feature/dotnet-sdk-contrib/issues/172)) ([3d089f5](https://github.com/open-feature/dotnet-sdk-contrib/commit/3d089f5c48478d7151fcf5964aa545471a0afe5c))
* Use new Statsig Api to return default value when flag is not defined ([#177](https://github.com/open-feature/dotnet-sdk-contrib/issues/177)) ([5efc8a6](https://github.com/open-feature/dotnet-sdk-contrib/commit/5efc8a603d1ad9d8887d75e38f95d5168a2319fa))

## [0.0.3](https://github.com/open-feature/dotnet-sdk-contrib/compare/OpenFeature.Contrib.Providers.Statsig-v0.0.2...OpenFeature.Contrib.Providers.Statsig-v0.0.3) (2024-04-03)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<PackageId>OpenFeature.Contrib.Providers.Statsig</PackageId>
<VersionNumber>0.0.3</VersionNumber><!--x-release-please-version -->
<VersionNumber>0.0.4</VersionNumber><!--x-release-please-version -->
<VersionPrefix>$(VersionNumber)</VersionPrefix>
<VersionSuffix>preview</VersionSuffix>
<AssemblyVersion>$(VersionNumber)</AssemblyVersion>
Expand Down
3 changes: 0 additions & 3 deletions src/OpenFeature.Contrib.Providers.Statsig/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,3 @@ The following parameters are mapped to the corresponding Statsig pre-defined par

## Known issues and limitations
- Only `ResolveBooleanValue` implemented for now

- Gate BooleanEvaluation with default value true cannot fallback to true.
https://github.com/statsig-io/dotnet-sdk/issues/33
37 changes: 29 additions & 8 deletions src/OpenFeature.Contrib.Providers.Statsig/StatsigProvider.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using OpenFeature.Constant;
using OpenFeature.Error;
using OpenFeature.Model;
using Statsig;
using Statsig.Server;
using Statsig.Server.Evaluation;
using System;
using System.Threading.Tasks;

Expand Down Expand Up @@ -46,13 +46,34 @@ public StatsigProvider(string sdkKey = null, StatsigServerOptions statsigServerO
/// <inheritdoc/>
public override Task<ResolutionDetails<bool>> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null)
{
//TODO: defaultvalue = true not yet supported due to https://github.com/statsig-io/dotnet-sdk/issues/33
if (defaultValue == true)
throw new FeatureProviderException(ErrorType.General, "defaultvalue = true not supported (https://github.com/statsig-io/dotnet-sdk/issues/33)");
if (GetStatus() != ProviderStatus.Ready)
return Task.FromResult(new ResolutionDetails<bool>(flagKey, defaultValue, ErrorType.ProviderNotReady));
var result = ServerDriver.CheckGateSync(context.AsStatsigUser(), flagKey);
return Task.FromResult(new ResolutionDetails<bool>(flagKey, result));
var result = ServerDriver.GetFeatureGate(context.AsStatsigUser(), flagKey);
var gateFound = false;
var responseType = ErrorType.None;

switch (result.Reason)
{
case EvaluationReason.Network:
case EvaluationReason.LocalOverride:
case EvaluationReason.Bootstrap:
case EvaluationReason.DataAdapter:
gateFound = true;
break;
case EvaluationReason.Unrecognized:
responseType = ErrorType.FlagNotFound;
break;
case EvaluationReason.Uninitialized:
responseType = ErrorType.ProviderNotReady;
break;
case EvaluationReason.Unsupported:
responseType = ErrorType.InvalidContext;
break;
case EvaluationReason.Error:
responseType = ErrorType.General;
break;
case null:
break;
}
return Task.FromResult(new ResolutionDetails<bool>(flagKey, gateFound ? result.Value : defaultValue, responseType));
}

/// <inheritdoc/>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenFeature.Contrib.Providers.Statsig/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.3
0.0.4
23 changes: 23 additions & 0 deletions test/OpenFeature.Contrib.Providers.Flagd.Test/FlagdProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using NSubstitute.ReceivedExtensions;
using OpenFeature.Constant;
using OpenFeature.Contrib.Providers.Flagd.Resolver.InProcess;
Expand Down Expand Up @@ -525,6 +526,28 @@ public async Task TestCacheAsync()
mockGrpcClient.Received(Quantity.AtLeastOne()).EventStream(Arg.Any<EventStreamRequest>(), null, null, CancellationToken.None);
}

[Fact]
public async Task TestResolverInit_Success_Ready()
{
var mockResolver = Substitute.For<Resolver.Resolver>();
mockResolver.Init().Returns(Task.CompletedTask);
var provider = new FlagdProvider(resolver: mockResolver);
await provider.Initialize(EvaluationContext.Empty);

Assert.Equal(ProviderStatus.Ready, provider.GetStatus());
}

[Fact]
public async Task TestResolverInit_Failure_Error()
{
var mockResolver = Substitute.For<Resolver.Resolver>();
mockResolver.Init().ThrowsAsync(new Exception("fake exception"));
var provider = new FlagdProvider(resolver: mockResolver);
await Assert.ThrowsAsync<AggregateException>(() => provider.Initialize(EvaluationContext.Empty));

Assert.Equal(ProviderStatus.Error, provider.GetStatus());
}

[Fact]
public async Task TestCacheHitAsync()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class UnitTestFlagsmithProvider
private static FlagsmithConfiguration GetDefaultFlagsmithConfiguration() => new()
{
ApiUrl = "https://edge.api.flagsmith.com/api/v1/",
EnvironmentKey = string.Empty,
EnvironmentKey = "some-key",
EnableClientSideEvaluation = false,
EnvironmentRefreshIntervalSeconds = 60,
EnableAnalytics = false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using AutoFixture.Xunit2;
using OpenFeature.Constant;
using OpenFeature.Error;
using OpenFeature.Model;
using System.Threading.Tasks;
using Xunit;
Expand Down Expand Up @@ -41,25 +40,32 @@ public async Task GetBooleanValue_ForFeatureWithContext(bool flagValue, bool exp
[Theory]
[InlineAutoData(true, false)]
[InlineAutoData(false, false)]
public async Task GetBooleanValue_ForFeatureWithNoContext_ReturnsFalse(bool flagValue, bool expectedValue, string flagName)
public async Task GetBooleanValue_ForFeatureWithNoContext_ReturnsDefaultValue(bool flagValue, bool defaultValue, string flagName)
{
// Arrange
await statsigProvider.Initialize(null);
statsigProvider.ServerDriver.OverrideGate(flagName, flagValue);

// Act & Assert
Assert.Equal(expectedValue, statsigProvider.ResolveBooleanValue(flagName, false).Result.Value);
Assert.Equal(defaultValue, statsigProvider.ResolveBooleanValue(flagName, defaultValue).Result.Value);
}

[Theory]
[AutoData]
public async Task GetBooleanValue_ForFeatureWithDefaultTrue_ThrowsException(string flagName)
[InlineAutoData(false)]
[InlineAutoData(true)]
public async Task GetBooleanValue_ForFeatureWithDefault(bool defaultValue, string flagName, string userId)
{
// Arrange
await statsigProvider.Initialize(null);

// Act & Assert
Assert.ThrowsAny<FeatureProviderException>(() => statsigProvider.ResolveBooleanValue(flagName, true).Result.Value);
var ec = EvaluationContext.Builder().SetTargetingKey(userId).Build();

// Act
var result = await statsigProvider.ResolveBooleanValue(flagName, defaultValue, ec);

//Assert
Assert.Equal(defaultValue, result.Value);
}

[Fact]
Expand Down

0 comments on commit c04e8a1

Please sign in to comment.