Ejemplo n.º 1
0
        private void OnMessage(object sender, EventSource.MessageReceivedEventArgs e)
        {
            try
            {
                HandleMessage(e.EventName, e.Message.Data);
            }
            catch (JsonReadException ex)
            {
                _log.Error("LaunchDarkly service request failed or received invalid data: {0}",
                           LogValues.ExceptionSummary(ex));

                var errorInfo = new DataSourceStatus.ErrorInfo
                {
                    Kind    = DataSourceStatus.ErrorKind.InvalidData,
                    Message = ex.Message,
                    Time    = DateTime.Now
                };
                _updateSink.UpdateStatus(DataSourceState.Interrupted, errorInfo);

                _eventSource.Restart(false);
            }
            catch (Exception ex)
            {
                LogHelpers.LogException(_log, "Unexpected error in stream processing", ex);
            }
        }
Ejemplo n.º 2
0
        private async Task UpdateTaskAsync()
        {
            try
            {
                var response = await _featureFlagRequestor.FeatureFlagsAsync();

                if (response.statusCode == 200)
                {
                    var flagsAsJsonString = response.jsonResponse;
                    var allData           = DataModelSerialization.DeserializeV1Schema(flagsAsJsonString);
                    _updateSink.Init(_user, allData);

                    if (_initialized.GetAndSet(true) == false)
                    {
                        _startTask.SetResult(true);
                        _log.Info("Initialized LaunchDarkly Polling Processor.");
                    }
                }
            }
            catch (UnsuccessfulResponseException ex)
            {
                var errorInfo = DataSourceStatus.ErrorInfo.FromHttpError(ex.StatusCode);

                if (HttpErrors.IsRecoverable(ex.StatusCode))
                {
                    _log.Warn(HttpErrors.ErrorMessage(ex.StatusCode, "polling request", "will retry"));
                    _updateSink.UpdateStatus(DataSourceState.Interrupted, errorInfo);
                }
                else
                {
                    _log.Error(HttpErrors.ErrorMessage(ex.StatusCode, "polling request", ""));
                    _updateSink.UpdateStatus(DataSourceState.Shutdown, errorInfo);

                    // if client is initializing, make it stop waiting
                    _startTask.TrySetResult(false);

                    ((IDisposable)this).Dispose();
                }
            }
            catch (JsonReadException ex)
            {
                _log.Error("Polling request received malformed data: {0}", LogValues.ExceptionSummary(ex));
                _updateSink.UpdateStatus(DataSourceState.Interrupted,
                                         new DataSourceStatus.ErrorInfo
                {
                    Kind = DataSourceStatus.ErrorKind.InvalidData,
                    Time = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                Exception realEx = (ex is AggregateException ae) ? ae.Flatten() : ex;
                _log.Warn("Polling for feature flag updates failed: {0}", LogValues.ExceptionSummary(realEx));
                _log.Debug(LogValues.ExceptionTrace(realEx));
                _updateSink.UpdateStatus(DataSourceState.Interrupted,
                                         DataSourceStatus.ErrorInfo.FromException(realEx));
            }
        }
Ejemplo n.º 3
0
        // This method is called while _lock is being held. If we're starting up a new connection, we do
        // *not* wait for it to succeed; we return a Task that will be completed once it succeeds. In all
        // other cases we return an immediately-completed Task.

        private Task <bool> OpenOrCloseConnectionIfNecessary(bool mustReinitializeDataSource)
        {
            if (!_started)
            {
                return(Task.FromResult(false));
            }

            // Analytics event sending is enabled as long as we're allowed to do any network things.
            // (If the SDK is configured not to send events, then this is a no-op because _eventProcessor
            // will be a no-op implementation).
            _eventProcessor.SetOffline(_forceOffline || !_networkEnabled);

            // Diagnostic events are disabled if we're in the background.
            _diagnosticDisabler?.SetDisabled(_forceOffline || !_networkEnabled || _inBackground);

            if (mustReinitializeDataSource && _dataSource != null)
            {
                _dataSource?.Dispose();
                _dataSource = null;
            }

            if (_networkEnabled && !_forceOffline)
            {
                if (_inBackground && !_enableBackgroundUpdating)
                {
                    _log.Debug("Background updating is disabled");
                    _updateSink.UpdateStatus(DataSourceState.BackgroundDisabled, null);
                    return(Task.FromResult(true));
                }
                if (_dataSource is null)
                {
                    // Set the state to Initializing when there's a new data source that has not yet
                    // started. The state will then be updated as appropriate by the data source either
                    // calling UpdateStatus, or Init which implies UpdateStatus(Valid).
                    _updateSink.UpdateStatus(DataSourceState.Initializing, null);
                    _dataSource = _dataSourceFactory.CreateDataSource(_clientContext, _updateSink, _user, _inBackground);
                    return(_dataSource.Start()
                           .ContinueWith(SetInitializedIfUpdateProcessorStartedSuccessfully));
                }
            }
            else
            {
                // Either we've been explicitly set to be offline (in which case the state is always
                // SetOffline regardless of any other conditions), or we're offline because the network
                // is unavailable. If either of those things changes, we'll end up calling this method
                // again and the state will be updated if appropriate.
                _dataSource?.Dispose();
                _dataSource  = null;
                _initialized = true;
                _updateSink.UpdateStatus(
                    _forceOffline ? DataSourceState.SetOffline : DataSourceState.NetworkUnavailable,
                    null
                    );
                return(Task.FromResult(true));
            }
            return(Task.FromResult(false));
        }
Ejemplo n.º 4
0
        void Dispose(bool disposing)
        {
            if (disposing)
            {
                _log.Info("Shutting down the LaunchDarkly client");

                _dataSourceUpdateSink.UpdateStatus(DataSourceState.Shutdown, null);

                _backgroundModeManager.BackgroundModeChanged -= OnBackgroundModeChanged;
                _connectionManager.Dispose();
                _dataStore.Dispose();
                _eventProcessor.Dispose();

                // Reset the static Instance to null *if* it was referring to this instance
                DetachInstance();
            }
        }
Ejemplo n.º 5
0
 internal void DoUpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
 {
     _log.Debug("updating status to {0}{1}", newState,
                newError.HasValue ? (" (" + newError.Value + ")") : "");
     _updateSink.UpdateStatus(newState, newError);
 }