Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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.

72 changes: 36 additions & 36 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>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>

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8</LangVersion>
<DefaultItemExcludes>$(DefaultItemExcludes);example/**;</DefaultItemExcludes>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<PackageId>Flagsmith</PackageId>
<Title>Flagsmith</Title>
<Version>7.1.1</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 / Test (Flagsmith.Client.Test, 7.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, 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 / Check Build and formatting (Flagsmith.Client.Test)

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 / Test (Flagsmith.Client.Test, 7.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, 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 / Check Build and formatting (Flagsmith.Client.Test)

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