Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
2 changes: 1 addition & 1 deletion Flagsmith.Client.Test/Fixtures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Flagsmith.FlagsmithClientTest
{
internal class Fixtures
{
public static string ApiKey => "test_key";
public static string ApiKey => "ser.test_key";
public static string ApiUrl => "http://test_url/";
public static AnalyticsProcessorTest GetAnalyticalProcessorTest() => new(new HttpClient(), ApiKey, ApiUrl);
public static JObject JsonObject = JObject.Parse(@"{
Expand Down
31 changes: 26 additions & 5 deletions Flagsmith.Client.Test/FlagsmithTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -648,6 +648,27 @@ public void TestCannotCreateFlagsmithClientInRemoteEvaluationWithoutAPIKey()
Assert.Equal("ValueError: environmentKey is required", exception.Message);
}

[Fact]
public void TestCannotCreateFlagsmithClientInLocalEvaluationWithoutServerAPIKey()
{
// When
Action createFlagsmith = () => new FlagsmithClient(
new FlagsmithConfiguration
{
EnvironmentKey = "foobar",
EnableLocalEvaluation = true
}
);

// Then
var exception = Assert.Throws<Exception>(() => createFlagsmith());
Assert.Equal
(
"ValueError: In order to use local evaluation, please generate a server key in the environment settings page.",
exception.Message
);
}

[Fact]
/// <summary>
/// Test that analytics data is consistent with concurrent calls to get flags.
Expand Down Expand Up @@ -685,7 +706,7 @@ public async Task TestAnalyticsDataConsistencyWithConcurrentCallsToGetFlags()
featuresDictionary.TryAdd($"Feature_{i}", 0);
}

// When
// When
var tasks = new Task[numberOfThreads];

// Create numberOfThreads threads.
Expand All @@ -696,13 +717,13 @@ public async Task TestAnalyticsDataConsistencyWithConcurrentCallsToGetFlags()
// Prepare an array of feature names of length callsPerThread.
for (var j = 0; j < callsPerThread; j++)
{
// The feature names are randomly selected from the featuresDictionary and added to the
// list of features, which represents the features that have been evaluated.
// The feature names are randomly selected from the featuresDictionary and added to the
// list of features, which represents the features that have been evaluated.
string featureName = $"Feature_{new Random().Next(1, featuresDictionary.Count + 1)}";
features[j] = featureName;

// The relevant key in the featuresDictionary is incremented to simulate an evaluation
// to track for that feature.
// to track for that feature.
featuresDictionary[featureName]++;
}

Expand Down
668 changes: 0 additions & 668 deletions Flagsmith.Client.Test/FlagsmithTestDeprecated.cs

This file was deleted.

70 changes: 35 additions & 35 deletions Flagsmith.FlagsmithClient/Flagsmith.FlagsmithClient.csproj
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8</LangVersion>
<DefaultItemExcludes>$(DefaultItemExcludes);example/**;</DefaultItemExcludes>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<PackageId>Flagsmith</PackageId>
<Title>Flagsmith</Title>
<Version>7.1.0</Version>
<Authors>flagsmith</Authors>
<Company>Flagsmith</Company>
<PackageDescription>Client SDK for Flagsmith. Ship features with confidence using feature flags and remote config. Host yourself or use our hosted version at https://flagsmith.com/</PackageDescription>
<Copyright>Copyright © 2023 Bullet Train Ltd</Copyright>
<PackageProjectUrl>https://flagsmith.com/</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<PackageReleaseNotes>Singleton HTTP client</PackageReleaseNotes>
<PackageTags>feature flags remote config toggles</PackageTags>
<RepositoryUrl>https://github.com/Flagsmith/flagsmith-dotnet-client</RepositoryUrl>
<NeutralLanguage>en-GB</NeutralLanguage>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8</LangVersion>
<DefaultItemExcludes>$(DefaultItemExcludes);example/**;</DefaultItemExcludes>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<PackageId>Flagsmith</PackageId>
<Title>Flagsmith</Title>
<Version>8.0.0</Version>
<Authors>flagsmith</Authors>
<Company>Flagsmith</Company>
<PackageDescription>Client SDK for Flagsmith. Ship features with confidence using feature flags and remote config. Host yourself or use our hosted version at https://flagsmith.com/</PackageDescription>
<Copyright>Copyright © 2023 Bullet Train Ltd</Copyright>
<PackageProjectUrl>https://flagsmith.com/</PackageProjectUrl>
<PackageIcon>icon.png</PackageIcon>
<PackageReleaseNotes>Singleton HTTP client</PackageReleaseNotes>
<PackageTags>feature flags remote config toggles</PackageTags>
<RepositoryUrl>https://github.com/Flagsmith/flagsmith-dotnet-client</RepositoryUrl>
<NeutralLanguage>en-GB</NeutralLanguage>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="1.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="Polly" Version="7.2.3"/>
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="1.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

<!-- currently we duplicate the semver dependency here from Engine project -->
<!-- TODO: build the Engine at build time and reference it using a PackageReference -->
<PackageReference Include="semver" Version="2.3.0" />
<!-- currently we duplicate the semver dependency here from Engine project -->
<!-- TODO: build the Engine at build time and reference it using a PackageReference -->
<PackageReference Include="semver" Version="2.3.0"/>

<ProjectReference Include="..\Flagsmith.Engine\Flagsmith.Engine.csproj" PrivateAssets="all" />
<None Include="LICENSE" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ProjectReference Include="..\Flagsmith.Engine\Flagsmith.Engine.csproj" PrivateAssets="all"/>
<None Include="LICENSE" Pack="true" PackagePath=""/>
<None Include="icon.png" Pack="true" PackagePath="\"/>
</ItemGroup>

</Project>
83 changes: 2 additions & 81 deletions Flagsmith.FlagsmithClient/FlagsmithClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ private void Initialise()
{
if (!_config.EnvironmentKey!.StartsWith("ser."))
{
Console.WriteLine(
"In order to use local evaluation, please generate a server key in the environment settings page."
throw new Exception(
"ValueError: In order to use local evaluation, please generate a server key in the environment settings page."
);
}

Expand All @@ -99,85 +99,6 @@ public FlagsmithClient(FlagsmithConfiguration configuration)
Initialise();
}

/// <summary>
/// Create flagsmith client.
/// </summary>
/// <param name="environmentKey">The environment key obtained from Flagsmith interface. Required unless offlineMode is True</param>
/// <param name="apiUrl">Override the URL of the Flagsmith API to communicate with. Required unless offlineMode is True</param>
/// <param name="logger">Provide logger for logging polling info and errors which is only applicable when client side evalution is enabled and analytics errors.</param>
/// <param name="defaultFlagHandler">Callable which will be used in the case where flags cannot be retrieved from the API or a non existent feature is requested.</param>
/// <param name="enableAnalytics">if enabled, sends additional requests to the Flagsmith API to power flag analytics charts.</param>
/// <param name="enableClientSideEvaluation">If using local evaluation, specify the interval period between refreshes of local environment data.</param>
/// <param name="environmentRefreshIntervalSeconds"></param>
/// <param name="customHeaders">Additional headers to add to requests made to the Flagsmith API</param>
/// <param name="retries">Total http retries for every failing request before throwing the final error.</param>
/// <param name="requestTimeout">Number of seconds to wait for a request to complete before terminating the request</param>
/// <param name="httpClient">Http client used for flagsmith-API requests</param>
/// <param name="cacheConfig">Cache configuration. Example new CacheConfig(true) </param>
/// <param name="OfflineMode">Sets the client into offline mode. Relies on offlineHandler for evaluating flags.</param>
/// <param name="offlineHandler">Offline handler for evaluating flags. Required unless OfflineMode is False.</param>
/// <exception cref="FlagsmithAPIError">
/// Thrown when error occurs during any http request to Flagsmith api.Not applicable for polling or ananlytics.
/// </exception>
/// <exception cref="FlagsmithClientError">
/// A general exception with a error message. Example: Feature not found, etc.
/// </exception>
[Obsolete("Use FlagsmithClient(FlagsmithConfiguration) instead.")]
public FlagsmithClient(
string? environmentKey = null,
string apiUrl = "https://edge.api.flagsmith.com/api/v1/",
ILogger? logger = null,
Func<string, IFlag>? defaultFlagHandler = null,
bool enableAnalytics = false,
bool enableClientSideEvaluation = false,
int environmentRefreshIntervalSeconds = 60,
Dictionary<string, string>? customHeaders = null,
int retries = 1,
double? requestTimeout = null,
HttpClient? httpClient = null,
CacheConfig? cacheConfig = null,
bool offlineMode = false,
BaseOfflineHandler? offlineHandler = null
)
{
_config = new FlagsmithConfiguration
{
EnvironmentKey = environmentKey,
ApiUri = new Uri(apiUrl),
EnvironmentRefreshInterval = TimeSpan.FromSeconds(environmentRefreshIntervalSeconds),
EnableLocalEvaluation = enableClientSideEvaluation,
Logger = logger,
EnableAnalytics = enableAnalytics,
RequestTimeout = requestTimeout,
Retries = retries,
CustomHeaders = customHeaders,
CacheConfig = cacheConfig ?? new CacheConfig(false),
OfflineMode = offlineMode,
OfflineHandler = offlineHandler,
HttpClient = httpClient,
};
// The type of defaultFlagHandler in this constructor is `Func<string, IFlag>?`, but the type of
// IFlagsmithConfiguration.DefaultFlagHandler is `Func<string, Flag>`
if (defaultFlagHandler != null)
{
Flag Handler(string s) => (defaultFlagHandler(s) as Flag)!;
_config.DefaultFlagHandler = Handler;
}
Initialise();
}

/// <summary>
/// <para>Creates a Flagsmith client.</para>
/// <para>Deprecated since 7.1.0. Use <see cref="FlagsmithClient(FlagsmithConfiguration)"/> instead.</para>
/// </summary>
[Obsolete("This constructor is deprecated. Use FlagsmithClient(IFlagsmithConfiguration) instead.")]
public FlagsmithClient(IFlagsmithConfiguration configuration, HttpClient httpClient)
{
_config = (FlagsmithConfiguration)configuration;
_config.HttpClient = httpClient;
Initialise();
}

/// <summary>
/// Get all the default for flags for the current environment.
/// </summary>
Expand Down
41 changes: 4 additions & 37 deletions Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@
private static readonly Uri DefaultApiUri = new Uri("https://edge.api.flagsmith.com/api/v1/");
private TimeSpan _timeout;

/// <summary>
/// <para>Override the URL of the Flagsmith API to communicate with.</para>
/// <para>Deprecated since 7.1.0. Use <see cref="ApiUri"/> instead.</para>
/// </summary>
[Obsolete("Use ApiUri instead.")]
public string ApiUrl
{
get => ApiUri.ToString();
set => ApiUri = value.EndsWith("/") ? new Uri(value) : new Uri($"{value}/");
}

/// <summary>
/// Versioned base Flagsmith API URI to use for all requests. Defaults to
/// <c>https://edge.api.flagsmith.com/api/v1/</c>.
Expand All @@ -34,43 +23,26 @@
/// </summary>
public string EnvironmentKey { get; set; }

/// <summary>
/// Enables local evaluation of flags.
/// </summary>
[Obsolete("Use EnableLocalEvaluation instead.")]
public bool EnableClientSideEvaluation
{
get => EnableLocalEvaluation;
set => EnableLocalEvaluation = value;
}

/// <summary>
/// Enables local evaluation of flags.
/// </summary>
public bool EnableLocalEvaluation { get; set; }

/// <summary>
/// <para>If using local evaluation, specify the interval period between refreshes of local environment data.</para>
/// <para>Deprecated since 7.1.0. Use <see cref="EnvironmentRefreshInterval"/> instead.</para>
/// </summary>
[Obsolete("Use EnvironmentRefreshInterval instead.")]
public int EnvironmentRefreshIntervalSeconds
{
get => EnvironmentRefreshInterval.Seconds;
set => EnvironmentRefreshInterval = TimeSpan.FromSeconds(value);
}
/// <summary>
/// If using local evaluation, specify the interval period between refreshes of local environment data.
/// </summary>
public TimeSpan EnvironmentRefreshInterval { get; set; } = TimeSpan.FromSeconds(60);

/// <summary>
/// Callable which will be used in the case where flags cannot be retrieved from the API or a non existent feature is requested.
/// </summary>
public Func<string, Flag>? DefaultFlagHandler { get; set; }

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.FlagsmithClient)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.Engine)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 6.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.EngineTest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.Client.Test)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 8.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 39 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 7.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

/// <summary>
/// Provide logger for logging polling info & errors which is only applicable when client side evalution is enabled and analytics errors.
/// </summary>
public ILogger Logger { get; set; }

/// <summary>
/// if enabled, sends additional requests to the Flagsmith API to power flag analytics charts.
/// </summary>
Expand All @@ -89,6 +61,7 @@
/// Total http retries for every failing request before throwing the final error.
/// </summary>
public int? Retries { get; set; }

/// <summary>
/// Additional headers to add to requests made to the Flagsmith API
/// </summary>
Expand All @@ -107,17 +80,11 @@
/// <summary>
/// Handler for offline mode operations.
/// </summary>
public BaseOfflineHandler? OfflineHandler { get; set; }

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.FlagsmithClient)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.Engine)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 6.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.EngineTest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Check Build and formatting (Flagsmith.Client.Test)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 8.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 83 in Flagsmith.FlagsmithClient/FlagsmithConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test (Flagsmith.Client.Test, 7.0.x)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

/// <summary>
/// Http client used for flagsmith-API requests.
/// </summary>
public HttpClient HttpClient { get; set; } = new HttpClient();

[Obsolete("This method will be removed in a future release.")]
public bool IsValid()
{
return !string.IsNullOrEmpty(ApiUri.ToString()) && !string.IsNullOrEmpty(EnvironmentKey);
}
}
}
Loading
Loading