/// <summary> /// Returns a standardized string identifier for a <see cref="DataSourceState"/>. /// </summary> /// <remarks> /// These Java-style uppercase identifiers (<c>INITIALIZING</c>, <c>VALID</c>, etc.) may be used in /// logging for consistency across SDKs. /// </remarks> /// <param name="state">a state value</param> /// <returns>a string identifier</returns> public static string Identifier(this DataSourceState state) { switch (state) { case DataSourceState.Initializing: return("INITIALIZING"); case DataSourceState.Valid: return("VALID"); case DataSourceState.Interrupted: return("INTERRUPTED"); case DataSourceState.NetworkUnavailable: return("NETWORK_UNAVAILABLE"); case DataSourceState.SetOffline: return("SET_OFFLINE"); case DataSourceState.Shutdown: return("SHUTDOWN"); default: return(state.ToString()); } }
public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { DataSourceStatus?statusToBroadcast = null; lock (_stateLock) { var oldStatus = _currentStatus; if (newState == DataSourceState.Interrupted && oldStatus.State == DataSourceState.Initializing) { newState = DataSourceState.Initializing; // see comment on IDataSourceUpdates.UpdateStatus } if (newState != oldStatus.State || newError.HasValue) { _currentStatus = new DataSourceStatus { State = newState, StateSince = newState == oldStatus.State ? oldStatus.StateSince : DateTime.Now, LastError = newError.HasValue ? newError : oldStatus.LastError }; statusToBroadcast = _currentStatus; _stateChangedSignal.NotifyAll(); } } _outageTracker?.TrackDataSourceState(newState, newError); if (statusToBroadcast.HasValue) { _taskExecutor.ScheduleEvent(this, statusToBroadcast.Value, StatusChanged); } }
internal async Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout) { var newStatus = await _status.WaitForAsync( status => status.State == desiredState || status.State == DataSourceState.Off, timeout ); return(newStatus.HasValue && newStatus.Value.State == desiredState); }
public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { var updated = _status.Update(new StateAndError { State = newState, Error = newError }, out var newStatus); if (updated) { _taskExecutor.ScheduleEvent(newStatus, StatusChanged); } }
/// <summary> /// Simulates a change in the data source status. /// </summary> /// <remarks> /// Use this if you want to test the behavior of application code that uses /// <see cref="LdClient.DataSourceStatusProvider"/> to track whether the data source is having /// problems (for example, a network failure interrupting the streaming connection). It does /// not actually stop the <see cref="TestData"/> data source from working, so even if you have /// simulated an outage, calling <see cref="Update(FlagBuilder)"/> will still send updates. /// </remarks> /// <param name="newState">one of the constants defined by <see cref="DataSourceState"/></param> /// <param name="newError">an optional <see cref="DataSourceStatus.ErrorInfo"/> instance</param> /// <returns>the same <see cref="TestData"/> instance</returns> public TestData UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { DataSourceImpl[] instances; lock (_lock) { instances = _instances.ToArray(); } foreach (var instance in instances) { instance.DoUpdateStatus(newState, newError); } return(this); }
public void Resume() { State = DataSourceState.Resuming; try { OnResume(); State = DataSourceState.Running; } catch (Exception ex) { State = DataSourceState.Error; _exception = new Exception("OnResume() got a fatal error.", ex); } }
public void Pause() { State = DataSourceState.Pausing; try { OnPause(); State = DataSourceState.Paused; } catch (Exception ex) { State = DataSourceState.Error; _exception = new Exception("OnPause() got a fatal error.", ex); } }
public void Stop() { State = DataSourceState.Stopping; try { OnStop(); State = DataSourceState.Stopped; } catch (Exception ex) { State = DataSourceState.Error; _exception = new Exception("OnStop() got a fatal error.", ex); } }
public void Initialize() { State = DataSourceState.Initializing; try { OnInitialize(); State = DataSourceState.Initialized; } catch (Exception ex) { State = DataSourceState.Error; _exception = new Exception("OnInitialize() got a fatal error.", ex); } }
internal async Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout) { var deadline = DateTime.Now.Add(timeout); bool hasTimeout = timeout.CompareTo(TimeSpan.Zero) > 0; while (true) { MultiNotifierToken stateAwaiter; TimeSpan timeToWait; lock (_stateLock) { if (_currentStatus.State == desiredState) { return(true); } if (_currentStatus.State == DataSourceState.Off) { return(false); } // Here we're using a slightly roundabout mechanism to keep track of however many tasks might // be simultaneously waiting on WaitForAsync, because .NET doesn't have an async concurrency // primitive equivalent to Java's wait/notifyAll(). What we're creating here is a cancellation // token that will be cancelled (by UpdateStatus) the next time the status is changed in any // way. if (hasTimeout) { timeToWait = deadline.Subtract(DateTime.Now); if (timeToWait.CompareTo(TimeSpan.Zero) <= 0) { return(false); } } else { timeToWait = TimeSpan.FromMilliseconds(-1); // special value makes Task.Delay wait indefinitely } stateAwaiter = _stateChangedSignal.Token; } await stateAwaiter.WaitAsync(timeToWait); } }
/// <summary> /// Returns a standardized string identifier for a <see cref="DataSourceState"/>. /// </summary> /// <remarks> /// These Java-style uppercase identifiers (<c>INITIALIZING</c>, <c>VALID</c>, etc.) may be used in /// logging for consistency across SDKs. /// </remarks> /// <param name="state">a state value</param> /// <returns>a string identifier</returns> public static string Identifier(this DataSourceState state) { switch (state) { case DataSourceState.Initializing: return("INITIALIZING"); case DataSourceState.Valid: return("VALID"); case DataSourceState.Interrupted: return("INTERRUPTED"); case DataSourceState.Off: return("OFF"); default: return(state.ToString()); } }
private void SetState(Guid id, DataSourceState state) { //lock (dataStateInfoTable) //{ if (dataStateInfoTable.ContainsKey(id)) { dataStateInfoTable[id].State = state; if (state == DataSourceState.InTransfer) { dataStateInfoTable[id].StateDescription = IntransferStateDescription; } if (state == DataSourceState.Paused) { dataStateInfoTable[id].StateDescription = PausedStateDescription; } } else { //dataStateTable.Add(id, state); } //} }
internal void TrackDataSourceState(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { lock (_trackerLock) { if (newState == DataSourceState.Interrupted || newError.HasValue || (newState == DataSourceState.Initializing && _inOutage)) { // We are in a potentially recoverable outage. If that wasn't the case already, and if // we've been configured with a timeout for logging the outage at a higher level, schedule // that timeout. if (_inOutage) { // We were already in one - just record this latest error for logging later. RecordError(newError); } else { // We weren't already in one, so set the timeout and start recording errors. _inOutage = true; _errorCounts.Clear(); RecordError(newError); _outageEndedSignal = new TaskCompletionSource <bool>(); Task.Run(() => WaitForTimeout(_outageEndedSignal.Task)); } } else { if (_outageEndedSignal != null) { _outageEndedSignal.SetResult(true); _outageEndedSignal = null; } _inOutage = false; } } }
public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) => Actions.Enqueue(new ReceivedStatusUpdate { State = newState, Error = newError });
public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { State = newState; }
internal void DoUpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) { _log.Debug("updating status to {0}{1}", newState, newError.HasValue ? (" (" + newError.Value + ")") : ""); _updateSink.UpdateStatus(newState, newError); }
public bool WaitFor(DataSourceState desiredState, TimeSpan timeout) => AsyncUtils.WaitSafely(() => _dataSourceUpdates.WaitForAsync(desiredState, timeout));
public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) => StatusUpdates.Enqueue(new StatusParams { State = newState, Error = newError });
public Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout) => _dataSourceUpdates.WaitForAsync(desiredState, timeout);