public UnleashServices(UnleashSettings settings, IRandom random, IUnleashApiClientFactory unleashApiClientFactory, IUnleashScheduledTaskManager scheduledTaskManager, IToggleCollectionCache toggleCollectionCache, IEnumerable <IStrategy> strategies) { this.Random = random ?? throw new ArgumentNullException(nameof(random)); this.scheduledTaskManager = scheduledTaskManager ?? throw new ArgumentNullException(nameof(scheduledTaskManager)); var settingsValidator = new UnleashSettingsValidator(); settingsValidator.Validate(settings); StrategyMap = BuildStrategyMap(strategies?.ToArray() ?? new IStrategy[0]); CancellationToken = cancellationTokenSource.Token; var cachedFilesResult = toggleCollectionCache.Load(cancellationTokenSource.Token).GetAwaiter().GetResult(); cacheMiss = cachedFilesResult.IsCacheMiss; ToggleCollection = new ThreadSafeToggleCollection { Instance = cachedFilesResult.InitialToggleCollection ?? new ToggleCollection() }; MetricsBucket = new ThreadSafeMetricsBucket(); var scheduledTasks = CreateScheduledTasks(settings, unleashApiClientFactory, toggleCollectionCache, cachedFilesResult); scheduledTaskManager.Configure(scheduledTasks, CancellationToken); }
internal async Task ExecuteAsync_WhenHttpExceptionOccurs_CompletesSuccessfully( HttpStatusCode statusCode, string responseBody, string responseContentType, [Frozen] UnleashSettings settings, [Frozen] ThreadSafeToggleCollection toggleCollection, [Frozen] Mock <IToggleCollectionCache> toggleCollectionCache, [Frozen] Mock <FakeHttpMessageHandler> httpMessageHandler, [Frozen] Mock <IUnleashApiClientFactory> apiClientFactoryMock, [Frozen] UnleashApiClientRequestHeaders requestHeaders, TaskCompletionSource <object> taskCompletionSource) { var jsonSerializerSettings = new NewtonsoftJsonSerializerSettings(); var jsonSerializer = new NewtonsoftJsonSerializer(jsonSerializerSettings); var backgroundTask = new FetchFeatureTogglesTask(apiClientFactoryMock.Object, toggleCollection, toggleCollectionCache.Object, taskCompletionSource); httpMessageHandler.SetupGetFeaturesRequestForException(requestHeaders, statusCode, responseBody, responseContentType); var httpClient = new HttpClient(httpMessageHandler.Object) { BaseAddress = settings.UnleashApi }; var apiClient = new UnleashApiClient(httpClient, jsonSerializer, requestHeaders); apiClientFactoryMock.Setup(cf => cf.CreateClient()).Returns(apiClient); await backgroundTask.ExecuteAsync(CancellationToken.None); Assert.True(taskCompletionSource.Task.IsCompletedSuccessfully); httpMessageHandler.VerifyAll(); apiClientFactoryMock.VerifyAll(); toggleCollectionCache.VerifyNoOtherCalls(); }
public FetchFeatureTogglesTask( IUnleashApiClientFactory apiClientFactory, ThreadSafeToggleCollection toggleCollection, IToggleCollectionCache toggleCollectionCache, TaskCompletionSource <object> initializationTaskCompletionSource) { this.apiClientFactory = apiClientFactory; this.toggleCollection = toggleCollection; this.toggleCollectionCache = toggleCollectionCache; this.initializationTaskCompletionSource = initializationTaskCompletionSource; }
internal async Task ExecuteAsync_WhenApiReturns200Ok_CompletesSuccessfully( [Frozen] UnleashSettings settings, [Frozen] ThreadSafeToggleCollection toggleCollection, [Frozen] Mock <IToggleCollectionCache> toggleCollectionCache, [Frozen] Mock <FakeHttpMessageHandler> httpMessageHandler, [Frozen] Mock <IUnleashApiClientFactory> apiClientFactoryMock, [Frozen] UnleashApiClientRequestHeaders requestHeaders, TaskCompletionSource <object> taskCompletionSource) { var jsonSerializerSettings = new NewtonsoftJsonSerializerSettings(); var jsonSerializer = new NewtonsoftJsonSerializer(jsonSerializerSettings); var toggleCollectionInstance = toggleCollection.Instance; toggleCollectionCache .Setup( x => x.Save( It.Is <ToggleCollection>( y => y.Version.Equals(toggleCollectionInstance.Version) && y.Features.All( z => toggleCollectionInstance.Features.Any(zz => zz.Name.Equals(z.Name)) ) ), It.IsAny <string>(), CancellationToken.None ) ) .Returns(Task.CompletedTask); var backgroundTask = new FetchFeatureTogglesTask(apiClientFactoryMock.Object, toggleCollection, toggleCollectionCache.Object, taskCompletionSource); httpMessageHandler.SetupGetFeaturesRequestForSuccess(jsonSerializer, toggleCollectionInstance, requestHeaders); var httpClient = new HttpClient(httpMessageHandler.Object) { BaseAddress = settings.UnleashApi }; var apiClient = new UnleashApiClient(httpClient, jsonSerializer, requestHeaders); apiClientFactoryMock.Setup(cf => cf.CreateClient()).Returns(apiClient); await backgroundTask.ExecuteAsync(CancellationToken.None); Assert.True(taskCompletionSource.Task.IsCompletedSuccessfully); httpMessageHandler.VerifyAll(); apiClientFactoryMock.VerifyAll(); toggleCollectionCache.VerifyAll(); }
public FetchFeatureTogglesTask( IUnleashApiClient apiClient, ThreadSafeToggleCollection toggleCollection, IJsonSerializer jsonSerializer, IFileSystem fileSystem, string toggleFile, string etagFile) { this.apiClient = apiClient; this.toggleCollection = toggleCollection; this.jsonSerializer = jsonSerializer; this.fileSystem = fileSystem; this.toggleFile = toggleFile; this.etagFile = etagFile; }
public JsonTogglerClient(IJsonFlagSerializer serializer, string path) { jsonClientProvider = JsonClientProviderFactory.GetProvider(serializer, path); toggleCollection = new ThreadSafeToggleCollection() { Instance = jsonClientProvider.FetchToggles().Result.ToggleCollection }; var fetchFeatureTogglesTask = new FetchFeatureTogglesTask(jsonClientProvider, toggleCollection); Task statisticsUploader = PeriodicAsync(async() => { try { await fetchFeatureTogglesTask.ExecuteAsync(); } catch (Exception ex) { // Log the exception } }, TimeSpan.FromSeconds(10)); }
public UnleashServices(UnleashSettings settings, Dictionary <string, IStrategy> strategyMap) { var fileSystem = settings.FileSystem ?? new FileSystem(settings.Encoding); var backupFile = settings.GetFeatureToggleFilePath(); var etagBackupFile = settings.GetFeatureToggleETagFilePath(); // Cancellation CancellationToken = cancellationTokenSource.Token; ContextProvider = settings.UnleashContextProvider; var loader = new CachedFilesLoader(settings.JsonSerializer, fileSystem, backupFile, etagBackupFile); var cachedFilesResult = loader.EnsureExistsAndLoad(); ToggleCollection = new ThreadSafeToggleCollection { Instance = cachedFilesResult.InitialToggleCollection ?? new ToggleCollection() }; MetricsBucket = new ThreadSafeMetricsBucket(); IUnleashApiClient apiClient; if (settings.UnleashApiClient == null) { var httpClient = settings.HttpClientFactory.Create(settings.UnleashApi); apiClient = new UnleashApiClient(httpClient, settings.JsonSerializer, new UnleashApiClientRequestHeaders() { AppName = settings.AppName, InstanceTag = settings.InstanceTag, CustomHttpHeaders = settings.CustomHttpHeaders }); if (settings.LoadTogglesImmediately) { var toggles = apiClient.FetchToggles("", CancellationToken.None); ToggleCollection.Instance = toggles.Result.ToggleCollection; } } else { // Mocked backend: fill instance collection apiClient = settings.UnleashApiClient; var toggles = apiClient.FetchToggles("", CancellationToken.None); ToggleCollection.Instance = toggles.Result.ToggleCollection; } scheduledTaskManager = settings.ScheduledTaskManager; IsMetricsDisabled = settings.SendMetricsInterval == null; var fetchFeatureTogglesTask = new FetchFeatureTogglesTask( apiClient, ToggleCollection, settings.JsonSerializer, fileSystem, backupFile, etagBackupFile) { ExecuteDuringStartup = true, Interval = settings.FetchTogglesInterval, Etag = cachedFilesResult.InitialETag }; var scheduledTasks = new List <IUnleashScheduledTask>() { fetchFeatureTogglesTask }; if (settings.SendMetricsInterval != null) { var clientRegistrationBackgroundTask = new ClientRegistrationBackgroundTask( apiClient, settings, strategyMap.Select(pair => pair.Key).ToList()) { Interval = TimeSpan.Zero, ExecuteDuringStartup = true }; scheduledTasks.Add(clientRegistrationBackgroundTask); var clientMetricsBackgroundTask = new ClientMetricsBackgroundTask( apiClient, settings, MetricsBucket) { ExecuteDuringStartup = false, Interval = settings.SendMetricsInterval.Value }; scheduledTasks.Add(clientMetricsBackgroundTask); } scheduledTaskManager.Configure(scheduledTasks, CancellationToken); }
public FetchFeatureTogglesTask(IJsonClientProvider jsonClientProvider, ThreadSafeToggleCollection toggleCollection) { this.jsonClientProvider = jsonClientProvider; this.toggleCollection = toggleCollection; }