private async Task <T> UpdateAsync(bool force) { PollStatus = "UpdateAsync"; if (!force && !IsStale) { return(Data); } Interlocked.Increment(ref PollingEngine._activePolls); PollStatus = "Awaiting Semaphore"; await _pollSemaphoreSlim.WaitAsync(); bool errored = false; try { if (!force && !IsStale) { return(Data); } if (_isPolling) { return(Data); } CurrentPollDuration = Stopwatch.StartNew(); _isPolling = true; PollStatus = "UpdateCache"; await _updateFunc(); PollStatus = "UpdateCache Complete"; Interlocked.Increment(ref _pollsTotal); if (DataTask != null) { Interlocked.Increment(ref _pollsSuccessful); } } catch (Exception e) { var errorMessage = e.Message; if (e.InnerException != null) { errorMessage += "\n" + e.InnerException.Message; } SetFail(e, errorMessage); errored = true; } finally { if (CurrentPollDuration != null) { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; } CurrentPollDuration = null; _isPolling = false; PollStatus = errored ? "Failed" : "Completed"; _pollSemaphoreSlim.Release(); Interlocked.Decrement(ref PollingEngine._activePolls); } return(Data); }
/// <summary> /// Called on a background thread for when this node is ACTUALLY polling /// This is not called if we're not due for a poll when the pass runs /// </summary> private void InnerPollImpl(bool force = false, bool sync = false) { CurrentPollDuration = Stopwatch.StartNew(); try { PollStatus = "InnerPoll Started"; if (Polling != null) { var ps = new PollStartArgs(); Polling(this, ps); if (ps.AbortPoll) { return; } } int toPoll = 0; if (sync || FirstPollRun != null) { PollStatus = "DataPollers Queueing (Sync)"; var tasks = DataPollers .Where(p => force || p.ShouldPoll) .Select(p => p.PollAsync(force)) .ToArray <Task>(); Task.WaitAll(tasks); PollStatus = "DataPollers Complete (Sync)"; } else { PollStatus = "DataPollers Queueing"; foreach (var p in DataPollers) { // Cheap checks to eliminate many uncessary task creations if (!force && !p.ShouldPoll) { continue; } // Kick off the poll and don't wait for it to continue; #pragma warning disable 4014 p.PollStatus = "Kicked off by Node"; Interlocked.Add(ref _totalCacheQueues, 1); p.PollAsync(force).ContinueWith(t => { if (t.IsFaulted) { Current.LogException(t.Exception); PollStatus = "Faulted"; } else { PollStatus = "Completed"; } Interlocked.Add(ref _totalCachePolls, t.Result); }, TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false); toPoll++; #pragma warning restore 4014 } PollStatus = toPoll.ToComma() + " DataPollers Started"; } LastPoll = DateTime.UtcNow; Polled?.Invoke(this, new PollResultArgs { Queued = toPoll }); if (FirstPollRun != null) { FirstPollRun.Set(); FirstPollRun = null; } Interlocked.Increment(ref _totalPolls); } finally { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; _isPolling = false; CurrentPollDuration = null; PollStatus = "InnerPoll Complete"; } }
public virtual async Task PollAsync(bool force = false) { using (MiniProfiler.Current.Step("Poll - " + UniqueKey)) { // If not forced, perform our "should-run" checks if (!force && !NeedsPoll) { return; } // Prevent multiple poll threads for this node from running at once if (Interlocked.CompareExchange(ref _isPolling, 1, 0) != 0) { // We're already running, abort!' // TODO: Date check for sanity and restart? return; } PollStatus = "Poll Started"; CurrentPollDuration = Stopwatch.StartNew(); try { PollStatus = "InnerPoll Started"; if (Polling != null) { var ps = new PollStartArgs(); Polling(this, ps); if (ps.AbortPoll) { return; } } PollStatus = "DataPollers Queueing"; var tasks = new List <Task>(); foreach (var p in DataPollers) { if (force || p.ShouldPoll) { tasks.Add(p.PollGenericAsync(force)); } } // Hop out early, run nothing else if (tasks.Count == 0) { PollStatus = "DataPollers Complete (None to run)"; return; } PollStatus = "DataPollers Queued (Now awaiting)"; // Await all children (this itself will be a background fire and forget if desired await Task.WhenAll(tasks).ConfigureAwait(false); PollStatus = "DataPollers Complete (Awaited)"; LastPoll = DateTime.UtcNow; Polled?.Invoke(this, new PollResultArgs()); Interlocked.Increment(ref _totalPolls); } finally { Interlocked.Exchange(ref _isPolling, 0); if (CurrentPollDuration != null) { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; } CurrentPollDuration = null; } PollStatus = "Poll Complete"; } }
private async Task <int> UpdateAsync() { PollStatus = "UpdateAsync"; if (!_needsPoll && !IsStale) { return(0); } PollStatus = "Awaiting Semaphore"; await _pollSemaphoreSlim.WaitAsync().ConfigureAwait(false); bool errored = false; try { if (!_needsPoll && !IsStale) { return(0); } if (_isPolling) { return(0); } CurrentPollDuration = Stopwatch.StartNew(); _isPolling = true; Interlocked.Increment(ref _pollsTotal); PollStatus = "UpdateCache"; await UpdateCache(this).ConfigureAwait(false); PollStatus = "UpdateCache Complete"; _needsPoll = false; if (DataBacker != null) { Interlocked.Increment(ref _pollsSuccessful); } return(DataBacker != null ? 1 : 0); } catch (Exception e) { var errorMessage = e.Message; if (e.InnerException != null) { errorMessage += "\n" + e.InnerException.Message; } SetFail(errorMessage); errored = true; return(0); } finally { if (CurrentPollDuration != null) { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; } CurrentPollDuration = null; _isPolling = false; PollStatus = errored ? "Failed" : "Completed"; _pollSemaphoreSlim.Release(); } }