/// <inheritdoc/>
 public IBigSegmentStore CreateBigSegmentStore(LdClientContext context) =>
 new DynamoDBBigSegmentStoreImpl(
     MakeClient(),
     _existingClient != null,
     _tableName,
     _prefix,
     context.Basic.Logger.SubLogger("BigSegments.DynamoDB")
     );
 /// <inheritdoc/>
 public IPersistentDataStoreAsync CreatePersistentDataStore(LdClientContext context) =>
 new DynamoDBDataStoreImpl(
     MakeClient(),
     _existingClient != null,
     _tableName,
     _prefix,
     context.Basic.Logger.SubLogger("DataStore.DynamoDB")
     );
 /// <inheritdoc/>
 public LdValue DescribeConfiguration(LdClientContext context) =>
 LdValue.BuildObject()
 .WithHttpProperties(MakeHttpProperties(context.Basic))
 .Add("useReport", _useReport)
 .Set("socketTimeoutMillis", _responseStartTimeout.TotalMilliseconds)
 // WithHttpProperties normally sets socketTimeoutMillis to the ReadTimeout value,
 // which is more correct, but we can't really set ReadTimeout in this SDK
 .Build();
示例#4
0
 public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates updateSink)
 {
     if (Instance is MockDataSourceBase m)
     {
         m.UpdateSink = updateSink;
     }
     return(Instance);
 }
示例#5
0
 /// <inheritdoc/>
 public LdValue DescribeConfiguration(LdClientContext context) =>
 LdValue.BuildObject()
 .WithPollingProperties(
     StandardEndpoints.IsCustomUri(context.ServiceEndpoints, e => e.PollingBaseUri),
     _pollInterval
     )
 .Add("backgroundPollingIntervalMillis", _backgroundPollInterval.TotalMilliseconds)
 .Build();
 internal FeatureRequestor(LdClientContext context, Uri baseUri)
 {
     _httpProperties = context.Http.HttpProperties;
     _httpClient     = context.Http.NewHttpClient();
     _connectTimeout = context.Http.ConnectTimeout;
     _allUri         = baseUri.AddPath(StandardEndpoints.PollingRequestPath);
     _log            = context.Basic.Logger.SubLogger(LogNames.DataSourceSubLog);
 }
示例#7
0
 internal void SetContext(LdClientContext context)
 {
     // This is done as a separate step, called from the LdClient constructor, because
     // the DiagnosticStore object has to be created before the LdClientContext - since
     // the LdClientContext includes a reference to the DiagnosticStore (for components
     // like StreamingDataSource to use).
     _context = context;
 }
示例#8
0
        /// <summary>
        /// Called internally by the SDK to associate this test data source with an
        /// <see cref="LdClient"/> instance. You do not need to call this method.
        /// </summary>
        /// <param name="context">created internally by <c>LdClient</c></param>
        /// <param name="dataSourceUpdates">created internally by <c>LdClient</c></param>
        /// <returns>a data source instance</returns>
        public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
        {
            var instance = new DataSourceImpl(this, dataSourceUpdates, context.Basic.Logger.SubLogger("DataSource.TestData"));

            lock (_lock)
            {
                _instances.Add(instance);
            }
            return(instance);
        }
 /// <inheritdoc/>
 public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
 {
     return(new StreamProcessor(
                context,
                dataSourceUpdates,
                _baseUri ?? DefaultBaseUri,
                _initialReconnectDelay,
                _eventSourceCreator
                ));
 }
示例#10
0
 internal FeatureRequestor(LdClientContext context, Uri baseUri)
 {
     _httpProperties = context.Http.HttpProperties;
     _httpClient     = context.Http.NewHttpClient();
     _connectTimeout = context.Http.ConnectTimeout;
     _allUri         = new Uri(baseUri.AbsoluteUri + "sdk/latest-all");
     _flagsUri       = new Uri(baseUri.AbsoluteUri + "sdk/latest-flags/");
     _segmentsUri    = new Uri(baseUri.AbsoluteUri + "sdk/latest-segments/");
     _log            = context.Basic.Logger.SubLogger(LogNames.DataSourceSubLog);
 }
        private IDataSource MakeDataSourceWithDiagnostics(Uri baseUri, User user, IDiagnosticStore diagnosticStore)
        {
            var config = BasicConfig()
                         .ServiceEndpoints(Components.ServiceEndpoints().Streaming(baseUri).Polling(baseUri))
                         .Build();
            var context = new LdClientContext(config, null, diagnosticStore, null);

            return(Components.StreamingDataSource().InitialReconnectDelay(BriefReconnectDelay)
                   .CreateDataSource(context, _updateSink, user, false));
        }
        /// <inheritdoc/>
        public BigSegmentsConfiguration CreateBigSegmentsConfiguration(LdClientContext context)
        {
            var store = _storeFactory is null ? null : _storeFactory.CreateBigSegmentStore(context);

            return(new BigSegmentsConfiguration(
                       store,
                       _userCacheSize,
                       _userCacheTime,
                       _statusPollInterval,
                       _staleAfter
                       ));
        }
示例#13
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
        {
            context.Basic.Logger.Warn("You should only disable the streaming API if instructed to do so by LaunchDarkly support");
            FeatureRequestor requestor = new FeatureRequestor(context, _baseUri ?? DefaultBaseUri);

            return(new PollingProcessor(
                       context,
                       requestor,
                       dataSourceUpdates,
                       _pollInterval
                       ));
        }
示例#14
0
        public PollingProcessorTest(ITestOutputHelper testOutput) : base(testOutput)
        {
            _mockFeatureRequestor = new Mock <IFeatureRequestor>();
            _featureRequestor     = _mockFeatureRequestor.Object;
            _dataStore            = new InMemoryDataStore();
            var dataSourceUpdatesImpl = TestUtils.BasicDataSourceUpdates(_dataStore, testLogger);

            _dataSourceUpdates        = dataSourceUpdatesImpl;
            _dataSourceStatusProvider = new DataSourceStatusProviderImpl(dataSourceUpdatesImpl);
            _config  = Configuration.Default(sdkKey);
            _context = new LdClientContext(new BasicConfiguration(sdkKey, false, testLogger), _config);
        }
示例#15
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
        {
            var configuredBaseUri = _baseUri ??
                                    StandardEndpoints.SelectBaseUri(context.Basic.ServiceEndpoints, e => e.StreamingBaseUri, "Streaming", context.Basic.Logger);

            return(new StreamProcessor(
                       context,
                       dataSourceUpdates,
                       configuredBaseUri,
                       _initialReconnectDelay,
                       _eventSourceCreator
                       ));
        }
示例#16
0
 internal PollingProcessor(
     LdClientContext context,
     IFeatureRequestor featureRequestor,
     IDataSourceUpdates dataSourceUpdates,
     TimeSpan pollInterval
     )
 {
     _featureRequestor  = featureRequestor;
     _dataSourceUpdates = dataSourceUpdates;
     _taskExecutor      = context.TaskExecutor;
     _pollInterval      = pollInterval;
     _initTask          = new TaskCompletionSource <bool>();
     _log = context.Basic.Logger.SubLogger(LogNames.DataSourceSubLog);
 }
 public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
 {
     if (context.Basic.Offline)
     {
         // If they have explicitly called Offline(true) to disable everything, we'll log this slightly
         // more specific message.
         context.Basic.Logger.Info("Starting LaunchDarkly client in offline mode");
     }
     else
     {
         context.Basic.Logger.Info("LaunchDarkly client will not connect to LaunchDarkly for feature flag data");
     }
     return(NullDataSource.Instance);
 }
示例#18
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(
            LdClientContext context,
            IDataSourceUpdateSink updateSink,
            User currentUser,
            bool inBackground
            )
        {
            var baseUri = StandardEndpoints.SelectBaseUri(
                context.ServiceEndpoints,
                e => e.StreamingBaseUri,
                "Streaming",
                context.BaseLogger
                );
            var pollingBaseUri = StandardEndpoints.SelectBaseUri(
                context.ServiceEndpoints,
                e => e.PollingBaseUri,
                "Polling",
                context.BaseLogger
                );

            if (inBackground)
            {
                // When in the background, always use polling instead of streaming
                return(new PollingDataSourceBuilder()
                       .BackgroundPollInterval(_backgroundPollInterval)
                       .CreateDataSource(context, updateSink, currentUser, true));
            }

            var logger    = context.BaseLogger.SubLogger(LogNames.DataSourceSubLog);
            var requestor = new FeatureFlagRequestor(
                pollingBaseUri,
                currentUser,
                context.EvaluationReasons,
                context.Http,
                logger
                );

            return(new StreamingDataSource(
                       updateSink,
                       currentUser,
                       baseUri,
                       context.EvaluationReasons,
                       _initialReconnectDelay,
                       requestor,
                       context.Http,
                       logger,
                       context.DiagnosticStore
                       ));
        }
        private IDisposable CreateStoreImpl(string prefix = null)
        {
            var context = new LdClientContext(new BasicConfiguration("sdk-key", false, Logs.None.Logger("")),
                                              LaunchDarkly.Sdk.Server.Configuration.Default("sdk-key"));

            if (Configuration.StoreFactoryFunc != null)
            {
                return(Configuration.StoreFactoryFunc(prefix).CreatePersistentDataStore(context));
            }
            if (Configuration.StoreAsyncFactoryFunc != null)
            {
                return(Configuration.StoreAsyncFactoryFunc(prefix).CreatePersistentDataStore(context));
            }
            throw new InvalidOperationException("neither StoreFactoryFunc nor StoreAsyncFactoryFunc was set");
        }
示例#20
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(LdClientContext context, IDataSourceUpdates dataSourceUpdates)
        {
            var configuredBaseUri = _baseUri ??
                                    StandardEndpoints.SelectBaseUri(context.Basic.ServiceEndpoints, e => e.PollingBaseUri, "Polling",
                                                                    context.Basic.Logger);

            context.Basic.Logger.Warn("You should only disable the streaming API if instructed to do so by LaunchDarkly support");
            FeatureRequestor requestor = new FeatureRequestor(context, configuredBaseUri);

            return(new PollingProcessor(
                       context,
                       requestor,
                       dataSourceUpdates,
                       _pollInterval
                       ));
        }
        public void LogMessageAtStartup()
        {
            var logCapture = Logs.Capture();
            var logger     = logCapture.Logger("BaseLoggerName"); // in real life, the SDK will provide its own base log name
            var context    = new LdClientContext(new BasicConfiguration("", false, logger),
                                                 LaunchDarkly.Sdk.Server.Configuration.Default(""));

            using (BaseBuilder().Prefix("my-prefix").CreatePersistentDataStore(context))
            {
                Assert.Collection(logCapture.GetMessages(),
                                  m =>
                {
                    Assert.Equal(LaunchDarkly.Logging.LogLevel.Info, m.Level);
                    Assert.Equal("BaseLoggerName.DataStore.DynamoDB", m.LoggerName);
                    Assert.Equal("Using DynamoDB data store with table name \"" + TableName +
                                 "\" and prefix \"my-prefix\"", m.Text);
                });
            }
        }
        public void LogMessageAtStartup()
        {
            var logCapture = Logs.Capture();
            var logger     = logCapture.Logger("BaseLoggerName"); // in real life, the SDK will provide its own base log name
            var context    = new LdClientContext(new BasicConfiguration("", false, logger),
                                                 LaunchDarkly.Sdk.Server.Configuration.Default(""));

            using (Consul.DataStore().Address("http://localhost:8500").Prefix("my-prefix")
                   .CreatePersistentDataStore(context))
            {
                Assert.Collection(logCapture.GetMessages(),
                                  m =>
                {
                    Assert.Equal(LaunchDarkly.Logging.LogLevel.Info, m.Level);
                    Assert.Equal("BaseLoggerName.DataStore.Consul", m.LoggerName);
                    Assert.Equal("Using Consul data store at http://localhost:8500/ with prefix \"my-prefix\"",
                                 m.Text);
                });
            }
        }
示例#23
0
 internal ConnectionManager(
     LdClientContext clientContext,
     IDataSourceFactory dataSourceFactory,
     IDataSourceUpdateSink updateSink,
     IEventProcessor eventProcessor,
     DiagnosticDisablerImpl diagnosticDisabler,
     bool enableBackgroundUpdating,
     User initialUser,
     Logger log
     )
 {
     _clientContext            = clientContext;
     _dataSourceFactory        = dataSourceFactory;
     _updateSink               = updateSink;
     _eventProcessor           = eventProcessor;
     _diagnosticDisabler       = diagnosticDisabler;
     _enableBackgroundUpdating = enableBackgroundUpdating;
     _user = initialUser;
     _log  = log;
 }
示例#24
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(
            LdClientContext context,
            IDataSourceUpdateSink updateSink,
            User currentUser,
            bool inBackground
            )
        {
            var instance = new DataSourceImpl(
                this,
                updateSink,
                currentUser,
                context.BaseLogger.SubLogger("DataSource.TestData")
                );

            lock (_lock)
            {
                _instances.Add(instance);
            }
            return(instance);
        }
示例#25
0
        /// <inheritdoc/>
        public IEventProcessor CreateEventProcessor(LdClientContext context)
        {
            var eventsConfig = MakeEventsConfiguration(context.Basic, true);
            var logger       = context.Basic.Logger.SubLogger(LogNames.EventsSubLog);
            var eventSender  = _eventSender ??
                               new DefaultEventSender(
                context.Http.HttpProperties,
                eventsConfig,
                logger
                );

            return(new DefaultEventProcessorWrapper(
                       new EventProcessor(
                           eventsConfig,
                           eventSender,
                           new DefaultUserDeduplicator(_userKeysCapacity, _userKeysFlushInterval),
                           context.DiagnosticStore,
                           null,
                           logger,
                           null
                           )));
        }
示例#26
0
        public void StreamInitDiagnosticRecordedOnError()
        {
            var mockDiagnosticStore = new Mock <IDiagnosticStore>();
            var diagnosticStore     = mockDiagnosticStore.Object;
            var context             = new LdClientContext(BasicContext.Basic,
                                                          Components.HttpConfiguration().CreateHttpConfiguration(BasicContext.Basic),
                                                          diagnosticStore, BasicTaskExecutor);

            using (var sp = (StreamProcessor)Components.StreamingDataSource().EventSourceCreator(_eventSourceFactory.Create())
                            .CreateDataSource(context, _dataSourceUpdates))
            {
                sp.Start();
                Assert.True(_esStartedReady.WaitOne(TimeSpan.FromSeconds(1)));
                DateTime esStarted = sp._esStarted;
                Thread.Sleep(TimeSpan.FromMilliseconds(100));
                SimulateStreamHttpError(401);
                DateTime startFailed = sp._esStarted;

                Assert.True(esStarted != startFailed);
                mockDiagnosticStore.Verify(ds => ds.AddStreamInit(esStarted, It.Is <TimeSpan>(ts => TimeSpan.Equals(ts, startFailed - esStarted)), true));
            }
        }
示例#27
0
        public void StreamInitDiagnosticRecordedOnOpen()
        {
            var mockDiagnosticStore = new Mock <IDiagnosticStore>();
            var diagnosticStore     = mockDiagnosticStore.Object;
            var basicConfig         = new BasicConfiguration(SDK_KEY, false, testLogger);
            var context             = new LdClientContext(basicConfig, Components.HttpConfiguration().CreateHttpConfiguration(basicConfig),
                                                          diagnosticStore, new TaskExecutor(testLogger));

            using (var sp = (StreamProcessor)Components.StreamingDataSource().EventSourceCreator(_eventSourceFactory.Create())
                            .CreateDataSource(context, _dataSourceUpdates))
            {
                sp.Start();
                Assert.True(_esStartedReady.WaitOne(TimeSpan.FromSeconds(1)));
                DateTime esStarted = sp._esStarted;
                Thread.Sleep(TimeSpan.FromMilliseconds(100));
                _mockEventSource.Raise(es => es.Opened += null, new EventSource.StateChangedEventArgs(ReadyState.Open));
                DateTime startCompleted = sp._esStarted;

                Assert.True(esStarted != startCompleted);
                mockDiagnosticStore.Verify(ds => ds.AddStreamInit(esStarted,
                                                                  It.Is <TimeSpan>(ts => TimeSpan.Equals(ts, startCompleted - esStarted)), false));
            }
        }
示例#28
0
        /// <inheritdoc/>
        public IDataSource CreateDataSource(
            LdClientContext context,
            IDataSourceUpdateSink updateSink,
            User currentUser,
            bool inBackground
            )
        {
            if (!inBackground)
            {
                context.BaseLogger.Warn("You should only disable the streaming API if instructed to do so by LaunchDarkly support");
            }
            var baseUri = StandardEndpoints.SelectBaseUri(
                context.ServiceEndpoints,
                e => e.PollingBaseUri,
                "Polling",
                context.BaseLogger
                );

            var logger    = context.BaseLogger.SubLogger(LogNames.DataSourceSubLog);
            var requestor = new FeatureFlagRequestor(
                baseUri,
                currentUser,
                context.EvaluationReasons,
                context.Http,
                logger
                );

            return(new PollingDataSource(
                       updateSink,
                       currentUser,
                       requestor,
                       _pollInterval,
                       TimeSpan.Zero,
                       context.TaskExecutor,
                       logger
                       ));
        }
        public async void DataStoreSkipsAndLogsTooLargeItemOnUpsert(string flagOrSegment)
        {
            var goodData = MakeGoodData();

            GetTooLargeItemParams(flagOrSegment, out var dataKind, out var collIndex, out SerializedItemDescriptor item);

            var logCapture = Logs.Capture();
            var context    = new LdClientContext(new BasicConfiguration("sdk-key", false, logCapture.Logger("")),
                                                 LaunchDarkly.Sdk.Server.Configuration.Default("sdk-key"));

            using (var store = BaseBuilder().CreatePersistentDataStore(context))
            {
                await store.InitAsync(goodData);

                AssertDataSetsEqual(MakeGoodData(), await GetAllData(store));

                await store.UpsertAsync(dataKind, BadItemKey, item);

                Assert.True(logCapture.HasMessageWithRegex(LogLevel.Error,
                                                           @"""" + BadItemKey + @""".*was too large to store in DynamoDB and was dropped"));

                AssertDataSetsEqual(MakeGoodData(), await GetAllData(store));
            }
        }
 /// <inheritdoc/>
 public IDataStore CreateDataStore(LdClientContext context, IDataStoreUpdates dataStoreUpdates)
 {
     if (_coreFactory != null)
     {
         return(new PersistentStoreWrapper(
                    _coreFactory.CreatePersistentDataStore(context),
                    _cacheConfig,
                    dataStoreUpdates,
                    context.TaskExecutor,
                    context.Basic.Logger
                    ));
     }
     else if (_coreAsyncFactory != null)
     {
         return(new PersistentStoreWrapper(
                    _coreAsyncFactory.CreatePersistentDataStore(context),
                    _cacheConfig,
                    dataStoreUpdates,
                    context.TaskExecutor,
                    context.Basic.Logger
                    ));
     }
     return(null);
 }