private async Task UpdateTaskAsync() { try { var response = await _featureFlagRequestor.FeatureFlagsAsync(); if (response.statusCode == 200) { var flagsAsJsonString = response.jsonResponse; var flagsDictionary = JsonUtil.DecodeJson <ImmutableDictionary <string, FeatureFlag> >(flagsAsJsonString); _flagCacheManager.CacheFlagsFromService(flagsDictionary, _user); // We can't use bool in CompareExchange because it is not a reference type. if (Interlocked.CompareExchange(ref _initialized, INITIALIZED, UNINITIALIZED) == UNINITIALIZED) { _startTask.SetResult(true); Log.Info("Initialized LaunchDarkly Polling Processor."); } } } catch (UnsuccessfulResponseException ex) when(ex.StatusCode == 401) { Log.ErrorFormat("Error Updating features: '{0}'", Util.ExceptionMessage(ex)); Log.Error("Received 401 error, no further polling requests will be made since SDK key is invalid"); if (_initialized == UNINITIALIZED) { _startTask.SetException(ex); } ((IDisposable)this).Dispose(); } catch (Exception ex) { Log.ErrorFormat("Error Updating features: '{0}'", Util.ExceptionMessage(PlatformSpecific.Http.TranslateHttpException(ex))); } }
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)); } }
void HandleMessage(string messageType, string messageData) { _log.Debug("Event '{0}': {1}", messageType, messageData); switch (messageType) { case Constants.PUT: { var allData = DataModelSerialization.DeserializeV1Schema(messageData); _updateSink.Init(_user, allData); if (!_initialized.GetAndSet(true)) { _initTask.SetResult(true); } break; } case Constants.PATCH: { try { var parsed = LdValue.Parse(messageData); var flagkey = parsed.Get(Constants.KEY).AsString; var featureFlag = DataModelSerialization.DeserializeFlag(messageData); _updateSink.Upsert(_user, flagkey, featureFlag.ToItemDescriptor()); } catch (Exception ex) { LogHelpers.LogException(_log, "Error parsing PATCH message", ex); _log.Debug("Message data follows: {0}", messageData); } break; } case Constants.DELETE: { try { var parsed = LdValue.Parse(messageData); int version = parsed.Get(Constants.VERSION).AsInt; string flagKey = parsed.Get(Constants.KEY).AsString; var deletedItem = new ItemDescriptor(version, null); _updateSink.Upsert(_user, flagKey, deletedItem); } catch (Exception ex) { LogHelpers.LogException(_log, "Error parsing DELETE message", ex); _log.Debug("Message data follows: {0}", messageData); } break; } case Constants.PING: { Task.Run(async() => { try { var response = await _requestor.FeatureFlagsAsync(); var flagsAsJsonString = response.jsonResponse; var allData = DataModelSerialization.DeserializeV1Schema(flagsAsJsonString); _updateSink.Init(_user, allData); if (!_initialized.GetAndSet(true)) { _initTask.SetResult(true); } } catch (Exception ex) { LogHelpers.LogException(_log, "Error in handling PING message", ex); } }); break; } default: break; } }