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);
        }
示例#2
0
        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;
 }
示例#4
0
        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;
 }
示例#6
0
        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));
        }
示例#7
0
        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);
        }
示例#8
0
 public FetchFeatureTogglesTask(IJsonClientProvider jsonClientProvider, ThreadSafeToggleCollection toggleCollection)
 {
     this.jsonClientProvider = jsonClientProvider;
     this.toggleCollection   = toggleCollection;
 }