diff --git a/src/ConfigCat.Client.Tests/BasicConfigCatClientIntegrationTests.cs b/src/ConfigCat.Client.Tests/BasicConfigCatClientIntegrationTests.cs index 2cc2f85a..b0b7ecfe 100644 --- a/src/ConfigCat.Client.Tests/BasicConfigCatClientIntegrationTests.cs +++ b/src/ConfigCat.Client.Tests/BasicConfigCatClientIntegrationTests.cs @@ -12,16 +12,8 @@ public class BasicConfigCatClientIntegrationTests { private const string SDKKEY = "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A"; - private static readonly IConfigCatClient client = new ConfigCatClient(SDKKEY); - private static readonly ILogger consoleLogger = new ConsoleLogger(LogLevel.Debug); - [ClassCleanup()] - public static void ClassCleanup() - { - client?.Dispose(); - } - [TestMethod] public void ManualPollGetValue() { diff --git a/src/ConfigCat.Client.Tests/ConfigServiceTests.cs b/src/ConfigCat.Client.Tests/ConfigServiceTests.cs index 14f471b4..c2343cc3 100644 --- a/src/ConfigCat.Client.Tests/ConfigServiceTests.cs +++ b/src/ConfigCat.Client.Tests/ConfigServiceTests.cs @@ -210,7 +210,7 @@ public async Task AutoPollConfigService_GetConfigAsync_WithTimer_ShouldInvokeFet } [TestMethod] - public async Task AutoPollConfigService_RefreshConfigAsync_ShouldNotInvokeCacheGetAndFetchAndCacheSet() + public async Task AutoPollConfigService_RefreshConfigAsync_ShouldOnceInvokeCacheGetAndFetchAndCacheSet() { // Arrange @@ -279,7 +279,6 @@ public async Task AutoPollConfigService_RefreshConfigAsync_ConfigCahged_ShouldRa // Assert Assert.AreEqual(1, eventChanged); - } [TestMethod] @@ -405,7 +404,7 @@ public void ConfigService_WithNonDisposableConfigFetcher_DisposeShouldWork() // Act configService.Dispose(); - } + } } } diff --git a/src/ConfigCat.Client.Tests/ExceptionThrowerHttpClientHandler.cs b/src/ConfigCat.Client.Tests/ExceptionThrowerHttpClientHandler.cs new file mode 100644 index 00000000..62d729ac --- /dev/null +++ b/src/ConfigCat.Client.Tests/ExceptionThrowerHttpClientHandler.cs @@ -0,0 +1,22 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace ConfigCat.Client.Tests +{ + internal sealed class ExceptionThrowerHttpClientHandler : HttpClientHandler + { + private readonly Exception exception; + + public ExceptionThrowerHttpClientHandler(Exception ex = null) + { + this.exception = ex ?? new NotImplementedException(); + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + throw exception; + } + } +} diff --git a/src/ConfigCat.Client.Tests/HttpConfigFetcherTests.cs b/src/ConfigCat.Client.Tests/HttpConfigFetcherTests.cs index 0196648a..a13eea58 100644 --- a/src/ConfigCat.Client.Tests/HttpConfigFetcherTests.cs +++ b/src/ConfigCat.Client.Tests/HttpConfigFetcherTests.cs @@ -1,9 +1,6 @@ -using ConfigCat.Client.ConfigService; -using ConfigCat.Client.Evaluate; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using Newtonsoft.Json; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System; +using System.Net; using System.Threading.Tasks; namespace ConfigCat.Client.Tests @@ -46,5 +43,25 @@ public void HttpConfigFetcher_WithCustomHttpClientHandler_HandlersDisposeShouldN Assert.IsFalse(myHandler.Disposed); } + + [TestMethod] + public async Task HttpConfigFetcher_ThrowAnException_ShouldReturPassedConfig() + { + // Arrange + + var myHandler = new ExceptionThrowerHttpClientHandler(new WebException()); + + var instance = new HttpConfigFetcher(new Uri("http://example.com"), "1.0", new MyCounterLogger(), myHandler); + + var lastConfig = new ProjectConfig("{ }", DateTime.UtcNow, "\"ETAG\""); + + // Act + + var actual = await instance.Fetch(lastConfig); + + // Assert + + Assert.AreEqual(lastConfig, actual); + } } } diff --git a/src/ConfigCat.Client.Tests/MyHttpClientHandler.cs b/src/ConfigCat.Client.Tests/MyHttpClientHandler.cs index 3f529c48..ccdb374a 100644 --- a/src/ConfigCat.Client.Tests/MyHttpClientHandler.cs +++ b/src/ConfigCat.Client.Tests/MyHttpClientHandler.cs @@ -6,15 +6,15 @@ namespace ConfigCat.Client.Tests { internal sealed class MyHttpClientHandler : HttpClientHandler { - public byte SendAsyncInvokeCount { get; private set; } = 0; + public byte SendAsyncInvokeCount { get; private set; } = 0; protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { SendAsyncInvokeCount++; return base.SendAsync(request, cancellationToken); - } - + } + public void Reset() { SendAsyncInvokeCount = 0; diff --git a/src/ConfigCatClient/ConfigCatClient.csproj b/src/ConfigCatClient/ConfigCatClient.csproj index f09d1012..7bde854c 100644 --- a/src/ConfigCatClient/ConfigCatClient.csproj +++ b/src/ConfigCatClient/ConfigCatClient.csproj @@ -15,7 +15,9 @@ https://github.com/ConfigCat/.net-sdk https://github.com/ConfigCat/.net-sdk git - Version 5.1.0 + Version 5.2.0 + * Bugfix (config fetch, caching) +Version 5.1.0 * Remove semver nuget packages Version 5.0.0 * Breaking change: Renamed `API Key` to `SDK Key`. diff --git a/src/ConfigCatClient/ConfigService/AutoPollConfigService.cs b/src/ConfigCatClient/ConfigService/AutoPollConfigService.cs index 8308600f..008c3ffa 100644 --- a/src/ConfigCatClient/ConfigService/AutoPollConfigService.cs +++ b/src/ConfigCatClient/ConfigService/AutoPollConfigService.cs @@ -78,7 +78,7 @@ private async Task RefreshLogicAsync(object sender) var newConfig = await this.configFetcher.Fetch(latestConfig); - if (!latestConfig.Equals(newConfig)) + if (!latestConfig.Equals(newConfig) && !newConfig.Equals(ProjectConfig.Empty)) { this.log.Debug("config changed"); diff --git a/src/ConfigCatClient/HttpConfigFetcher.cs b/src/ConfigCatClient/HttpConfigFetcher.cs index 397cd7ef..0d65fb4c 100644 --- a/src/ConfigCatClient/HttpConfigFetcher.cs +++ b/src/ConfigCatClient/HttpConfigFetcher.cs @@ -18,7 +18,7 @@ internal sealed class HttpConfigFetcher : IConfigFetcher, IDisposable private HttpClient httpClient; private readonly Uri requestUri; - + public HttpConfigFetcher(Uri requestUri, string productVersion, ILogger logger, HttpClientHandler httpClientHandler) { this.requestUri = requestUri; @@ -42,20 +42,18 @@ public async Task Fetch(ProjectConfig lastConfig) RequestUri = this.requestUri }; - if (lastConfig.HttpETag != null) - { - request.Headers.IfNoneMatch.Add(new EntityTagHeaderValue(lastConfig.HttpETag)); - } - try { - var response = await this.httpClient.SendAsync(request).ConfigureAwait(false); - - if (response.StatusCode == System.Net.HttpStatusCode.NotModified) + if (lastConfig.HttpETag != null) { - newConfig = lastConfig; + request.Headers.IfNoneMatch.Add(new EntityTagHeaderValue(lastConfig.HttpETag)); } - else if (response.IsSuccessStatusCode) + + newConfig = lastConfig; + + var response = await this.httpClient.SendAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) { newConfig.HttpETag = response.Headers.ETag.Tag; @@ -63,8 +61,6 @@ public async Task Fetch(ProjectConfig lastConfig) } else if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { - newConfig = lastConfig; - this.log.Error("Double-check your SDK Key at https://app.configcat.com/sdkkey"); } else @@ -97,7 +93,7 @@ private void ReInitializeHttpClient() } else { - this.httpClient = new HttpClient(this.httpClientHandler, false); + this.httpClient = new HttpClient(this.httpClientHandler, false); } this.httpClient.Timeout = TimeSpan.FromSeconds(30); @@ -114,6 +110,4 @@ public void Dispose() } } } - - internal sealed class WrapClientHandler : DelegatingHandler { } } \ No newline at end of file