diff --git a/Splitio.Redis/Splitio.Redis.csproj b/Splitio.Redis/Splitio.Redis.csproj index 1c497f98..b33d5191 100644 --- a/Splitio.Redis/Splitio.Redis.csproj +++ b/Splitio.Redis/Splitio.Redis.csproj @@ -7,7 +7,7 @@ false false false - 7.11.0 + 7.11.1 true SplitioRedis.snk Apache-2.0 diff --git a/appveyor.yml b/appveyor.yml index 22b85a40..e16e1129 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ image: nuget: account_feed: true -version: 7.11.0 +version: 7.11.1-rc.{build} dotnet_csproj: patch: true file: '**\*.csproj' diff --git a/src/Splitio/Constants/Constants.cs b/src/Splitio/Constants/Constants.cs index 4ca6990b..c6fa3888 100644 --- a/src/Splitio/Constants/Constants.cs +++ b/src/Splitio/Constants/Constants.cs @@ -32,6 +32,7 @@ public static class Gral public static int DestroyTimeount => 30000; public static int IntervalToClearLongTermCache => 3600000; public static string Control => "control"; + public static string SdkVersion => "7.11.1"; } public static class Urls diff --git a/src/Splitio/Services/Cache/Classes/InMemoryRuleBasedSegmentCache.cs b/src/Splitio/Services/Cache/Classes/InMemoryRuleBasedSegmentCache.cs index 55f21ffa..554e2035 100644 --- a/src/Splitio/Services/Cache/Classes/InMemoryRuleBasedSegmentCache.cs +++ b/src/Splitio/Services/Cache/Classes/InMemoryRuleBasedSegmentCache.cs @@ -7,7 +7,7 @@ namespace Splitio.Services.Cache.Classes { public class InMemoryRuleBasedSegmentCache : IRuleBasedSegmentCache - { + { private readonly ConcurrentDictionary _cache; private long _changeNumber; diff --git a/src/Splitio/Services/Cache/Classes/InMemorySplitCache.cs b/src/Splitio/Services/Cache/Classes/InMemorySplitCache.cs index 541523bf..8bbf3529 100644 --- a/src/Splitio/Services/Cache/Classes/InMemorySplitCache.cs +++ b/src/Splitio/Services/Cache/Classes/InMemorySplitCache.cs @@ -63,13 +63,11 @@ public void Update(List toAdd, List toRemove, long till) foreach (var featureFlagName in toRemove) { - if (!_featureFlags.TryGetValue(featureFlagName, out ParsedSplit cached)) - continue; - - _featureFlags.TryRemove(featureFlagName, out ParsedSplit removedSplit); - - DecreaseTrafficTypeCount(removedSplit); - RemoveFromFlagSets(removedSplit.name, removedSplit.Sets); + if (_featureFlags.TryRemove(featureFlagName, out ParsedSplit removedSplit)) + { + DecreaseTrafficTypeCount(removedSplit); + RemoveFromFlagSets(removedSplit.name, removedSplit.Sets); + } } SetChangeNumber(till); diff --git a/src/Splitio/Services/SegmentFetcher/Classes/SegmentSdkApiClient.cs b/src/Splitio/Services/SegmentFetcher/Classes/SegmentSdkApiClient.cs index d2ce2103..9e4aa8ac 100644 --- a/src/Splitio/Services/SegmentFetcher/Classes/SegmentSdkApiClient.cs +++ b/src/Splitio/Services/SegmentFetcher/Classes/SegmentSdkApiClient.cs @@ -67,10 +67,10 @@ public async Task FetchSegmentChangesAsync(string name, long since, Fetc private string GetRequestUri(string name, long since, long? till = null) { - var uri = $"{_baseUrl}/api/segmentChanges/{name}?since={Uri.EscapeDataString(since.ToString())}"; + var uri = $"{_baseUrl}/api/segmentChanges/{name}?since={since}"; if (till.HasValue) - return $"{uri}&till={Uri.EscapeDataString(till.Value.ToString())}"; + uri = $"{uri}&till={till.Value}"; return uri; } diff --git a/src/Splitio/Services/Shared/Classes/WrapperAdapter.cs b/src/Splitio/Services/Shared/Classes/WrapperAdapter.cs index be8a4f19..9d313214 100644 --- a/src/Splitio/Services/Shared/Classes/WrapperAdapter.cs +++ b/src/Splitio/Services/Shared/Classes/WrapperAdapter.cs @@ -44,9 +44,9 @@ public SdkMetadata BuildSdkMetadata(ConfigurationOptions config, ISplitLogger lo var ipAddressesEnabled = config.IPAddressesEnabled ?? true; #if NET_LATEST - metadata.Version = ".NET_CORE-" + SplitSdkVersion(); + metadata.Version = ".NET_CORE-" + SplitSdkVersion(log); #else - metadata.Version = ".NET-" + SplitSdkVersion(); + metadata.Version = ".NET-" + SplitSdkVersion(log); #endif metadata.MachineName = GetSdkMachineName(config, ipAddressesEnabled, log); metadata.MachineIP = GetSdkMachineIP(config, ipAddressesEnabled, log); @@ -59,13 +59,22 @@ public Task WhenAnyAsync(params Task[] tasks) return Task.WhenAny(tasks); } - private static string SplitSdkVersion() + private static string SplitSdkVersion(ISplitLogger log) { + try + { #if NET_LATEST - return typeof(Split).GetTypeInfo().Assembly.GetCustomAttribute().InformationalVersion; + return typeof(Split).GetTypeInfo().Assembly.GetCustomAttribute().InformationalVersion; #else - return FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion; + return FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion; #endif + } + catch (Exception ex) + { + log.Warn("Exception retrieving sdk version", ex); + } + + return Constants.Gral.SdkVersion; } public void SetCustomerLogger(ISplitLogger splitLogger) diff --git a/src/Splitio/Services/SplitFetcher/Classes/SplitSdkApiClient.cs b/src/Splitio/Services/SplitFetcher/Classes/SplitSdkApiClient.cs index 265972e9..75e04d32 100644 --- a/src/Splitio/Services/SplitFetcher/Classes/SplitSdkApiClient.cs +++ b/src/Splitio/Services/SplitFetcher/Classes/SplitSdkApiClient.cs @@ -56,7 +56,7 @@ public async Task FetchSplitChangesAsync(FetchOptions fetchOptio if (ShouldSwitchToLatestFlagsSpec) { _flagSpec = ApiVersions.LatestFlagsSpec; - _log.Info($"Switching to new Feature flag spec {_flagSpec} and fetching."); + _log.Warn($"Switching to new Feature flag spec {_flagSpec} and fetching."); requestUri = GetRequestUri(-1, -1, fetchOptions.Till); } @@ -70,16 +70,22 @@ public async Task FetchSplitChangesAsync(FetchOptions fetchOptio var result = new ApiFetchResult { Success = true, - ClearCache = _lastProxyCheckTimestamp != null, Spec = _flagSpec, - Content = response.Content + Content = response.Content, + ClearCache = false }; - _lastProxyCheckTimestamp = null; + if (_flagSpec != ApiVersions.Spec1_1) + { + result.ClearCache = _lastProxyCheckTimestamp != null; + _lastProxyCheckTimestamp = null; + } return result; } + _log.Warn($"FetchSplitChange fail request: {response.StatusCode}: {requestUri} - {response.Content}"); + if (response.StatusCode == System.Net.HttpStatusCode.BadRequest && _flagSpec.Equals(ApiVersions.LatestFlagsSpec) && _proxy) { _flagSpec = ApiVersions.Spec1_1; @@ -102,27 +108,27 @@ public async Task FetchSplitChangesAsync(FetchOptions fetchOptio return new ApiFetchResult { Success = false, - Content = string.Empty + Content = string.Empty, + Spec = _flagSpec, + ClearCache = false }; } } private string GetRequestUri(long since, long rbSinceTarget, long? till) { - var ffSince = Uri.EscapeDataString(since.ToString()); - var uri = $"{_baseUrl}/api/splitChanges?s={_flagSpec}&since={ffSince}"; + var uri = $"{_baseUrl}/api/splitChanges?s={_flagSpec}&since={since}"; if (_flagSpec.Equals(ApiVersions.LatestFlagsSpec)) { - var rbSince = Uri.EscapeDataString(rbSinceTarget.ToString()); - uri = $"{uri}&rbSince={rbSince}"; + uri = $"{uri}&rbSince={rbSinceTarget}"; } if (!string.IsNullOrEmpty(_flagSets)) uri = $"{uri}&sets={_flagSets}"; if (till.HasValue) - uri = $"{uri}&till={Uri.EscapeDataString(till.Value.ToString())}"; + uri = $"{uri}&till={till.Value}"; return uri; } diff --git a/src/Splitio/Services/SplitFetcher/Classes/TargetingRulesFetcher.cs b/src/Splitio/Services/SplitFetcher/Classes/TargetingRulesFetcher.cs index 48194fa4..37f5ef0a 100644 --- a/src/Splitio/Services/SplitFetcher/Classes/TargetingRulesFetcher.cs +++ b/src/Splitio/Services/SplitFetcher/Classes/TargetingRulesFetcher.cs @@ -90,6 +90,8 @@ public async Task FetchSplitsAsync(FetchOptions fetchOptions) if (result.ClearCache) { + _log.Warn($"Forcing a cache cleanup because a different Spec Version was detected."); + _featureFlagCache.Clear(); _ruleBasedSegmentCache.Clear(); } diff --git a/src/Splitio/Splitio.csproj b/src/Splitio/Splitio.csproj index d368d8e0..cd79f22b 100644 --- a/src/Splitio/Splitio.csproj +++ b/src/Splitio/Splitio.csproj @@ -7,7 +7,7 @@ false false false - 7.11.0 + 7.11.1 Splitio true Splitio.snk diff --git a/tests/Splitio-tests/Unit Tests/SplitFetcher/SplitSdkApiClientTests.cs b/tests/Splitio-tests/Unit Tests/SplitFetcher/SplitSdkApiClientTests.cs index cfb51378..89d23b53 100644 --- a/tests/Splitio-tests/Unit Tests/SplitFetcher/SplitSdkApiClientTests.cs +++ b/tests/Splitio-tests/Unit Tests/SplitFetcher/SplitSdkApiClientTests.cs @@ -7,6 +7,8 @@ using Splitio.Services.SplitFetcher.Classes; using Splitio.Telemetry.Storages; using System.Collections.Generic; +using System.Net.Http; +using System.Threading; using System.Threading.Tasks; namespace Splitio_Tests.Unit_Tests.SplitFetcher @@ -238,11 +240,12 @@ public async Task FetchSplitChangesAsync_SwitchFlagSpecAndBack_Ok() // Arrange. var baseUrl = "https://app.split-testing.io"; var flagSetsFilter = new FlagSetsFilter(new HashSet()); - var splitSdkApiClient = new SplitSdkApiClient(_httpClient.Object, _telemetryRuntimeProducer.Object, baseUrl, flagSetsFilter, true, 0); - var expectedUrl = $"{baseUrl}/api/splitChanges?s=1.3&since=-1&rbSince=-1"; + var splitSdkApiClient = new SplitSdkApiClient(_httpClient.Object, _telemetryRuntimeProducer.Object, baseUrl, flagSetsFilter, true, 100); + var expectedUrl1_3 = $"{baseUrl}/api/splitChanges?s=1.3&since=-1&rbSince=-1"; + var expectedUrl1_1 = $"{baseUrl}/api/splitChanges?s=1.1&since=-1"; _httpClient - .SetupSequence(mock => mock.GetAsync(expectedUrl, false)) + .SetupSequence(mock => mock.GetAsync(expectedUrl1_3, false)) .ReturnsAsync(new HTTPResult { StatusCode = System.Net.HttpStatusCode.BadRequest, @@ -256,17 +259,39 @@ public async Task FetchSplitChangesAsync_SwitchFlagSpecAndBack_Ok() IsSuccessStatusCode = true }); - // Act. + _httpClient + .Setup(mock => mock.GetAsync(expectedUrl1_1, false)) + .ReturnsAsync(new HTTPResult + { + StatusCode = System.Net.HttpStatusCode.OK, + Content = "ok", + IsSuccessStatusCode = true + }); + + // Act and Assert. var result = await splitSdkApiClient.FetchSplitChangesAsync(new FetchOptions { FeatureFlagsSince = -1, RuleBasedSegmentsSince = -1 }); - // Assert. Assert.AreEqual("ok", result.Content); Assert.IsTrue(result.Success); - _httpClient.Verify(mock => mock.GetAsync(expectedUrl, false), Times.Exactly(2)); + _httpClient.Verify(mock => mock.GetAsync(expectedUrl1_1, false), Times.Once); + _httpClient.Verify(mock => mock.GetAsync(expectedUrl1_3, false), Times.Once); + + + Thread.Sleep(150); + result = await splitSdkApiClient.FetchSplitChangesAsync(new FetchOptions + { + FeatureFlagsSince = -1, + RuleBasedSegmentsSince = -1 + }); + + Assert.AreEqual("ok", result.Content); + Assert.IsTrue(result.Success); + _httpClient.Verify(mock => mock.GetAsync(expectedUrl1_1, false), Times.Once); + _httpClient.Verify(mock => mock.GetAsync(expectedUrl1_3, false), Times.Exactly(2)); } } }