Exemplo n.º 1
0
        /// <summary>
        /// Invoked by a Cache instance on updating, using properties from the PollNode such as connection strings, etc.
        /// </summary>
        /// <typeparam name="T">Type of item in the cache</typeparam>
        /// <param name="description">Description of the operation, used purely for profiling</param>
        /// <param name="getData">The operation used to actually get data, e.g. <code>using (var conn = GetConnectionAsync()) { return getFromConnection(conn); }</code></param>
        /// <param name="logExceptions">Whether to log any exceptions to the log</param>
        /// <param name="addExceptionData">Optionally add exception data, e.g. <code>e => e.AddLoggedData("Server", Name)</code></param>
        /// <returns>A cache update action, used when creating a <see cref="Cache"/>.</returns>
        protected Action <Cache <T> > UpdateCacheItem <T>(string description,
                                                          Func <Task <T> > getData,
                                                          bool logExceptions = false, // TODO: Settings
                                                          Action <Exception> addExceptionData = null) where T : class
        {
            return(async cache =>
            {
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    cache.Profiler = OpserverProfileProvider.CreateContextProfiler("Poll: " + description, cache.UniqueId);
                }
                using (MiniProfiler.Current.Step(description))
                {
                    CacheItemFetching?.Invoke(this, EventArgs.Empty);
                    try
                    {
                        using (MiniProfiler.Current.Step("Data Fetch"))
                        {
                            cache.Data = await getData();
                        }
                        cache.LastSuccess = cache.LastPoll = DateTime.UtcNow;
                        cache.ErrorMessage = "";
                        PollFailsInaRow = 0;
                    }
                    catch (Exception e)
                    {
                        var deserializationException = e as DeserializationException;
                        if (deserializationException != null)
                        {
                            e.AddLoggedData("Snippet-After", deserializationException.SnippetAfterError)
                            .AddLoggedData("Position", deserializationException.Position.ToString())
                            .AddLoggedData("Ended-Unexpectedly", deserializationException.EndedUnexpectedly.ToString());
                        }
                        if (logExceptions)
                        {
                            addExceptionData?.Invoke(e);
                            Current.LogException(e);
                        }
                        cache.LastPoll = DateTime.UtcNow;
                        PollFailsInaRow++;
                        cache.ErrorMessage = "Unable to fetch from " + NodeType + ": " + e.Message;
#if DEBUG
                        cache.ErrorMessage += " @ " + e.StackTrace;
#endif

                        if (e.InnerException != null)
                        {
                            cache.ErrorMessage += "\n" + e.InnerException.Message;
                        }
                    }
                    CacheItemFetched?.Invoke(this, EventArgs.Empty);
                    CachedMonitorStatus = null;
                }
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    OpserverProfileProvider.StopContextProfiler();
                }
            });
        }
Exemplo n.º 2
0
 internal void PollComplete(Cache cache, bool success)
 {
     Interlocked.Exchange(ref _lastFetch, cache);
     if (success)
     {
         Interlocked.Increment(ref _totalCacheSuccesses);
         Interlocked.Exchange(ref PollFailsInaRow, 0);
     }
     else
     {
         Interlocked.Increment(ref PollFailsInaRow);
     }
     CachedMonitorStatus = null; // nullable type, not instruction level swappable
 }
Exemplo n.º 3
0
 /// <summary>
 /// Invoked by a Cache instance on updating, using properties from the PollNode such as connection strings, etc.
 /// </summary>
 /// <typeparam name="T">Type of item in the cache</typeparam>
 /// <param name="description">Description of the operation, used purely for profiling</param>
 /// <param name="getData">The operation used to actually get data, e.g. <code>using (var conn = GetConnection()) { return getFromConnection(conn); }</code></param>
 /// <param name="logExceptions">Whether to log any exceptions to the log</param>
 /// <param name="addExceptionData">Optionally add exception data, e.g. <code>e => e.AddLoggedData("Server", Name)</code></param>
 /// <returns>A cache update action, used when creating a <see cref="Cache"/>.</returns>
 protected Action <Cache <T> > UpdateCacheItem <T>(string description,
                                                   Func <T> getData,
                                                   bool logExceptions = false, // TODO: Settings
                                                   Action <Exception> addExceptionData = null) where T : class
 {
     return(cache =>
     {
         using (MiniProfiler.Current.Step(description))
         {
             if (CacheItemFetching != null)
             {
                 CacheItemFetching(this, EventArgs.Empty);
             }
             try
             {
                 cache.Data = getData();
                 cache.LastSuccess = cache.LastPoll = DateTime.UtcNow;
                 cache.ErrorMessage = "";
                 PollFailsInaRow = 0;
             }
             catch (Exception e)
             {
                 if (logExceptions)
                 {
                     if (addExceptionData != null)
                     {
                         addExceptionData(e);
                     }
                     Current.LogException(e);
                 }
                 cache.LastPoll = DateTime.UtcNow;
                 PollFailsInaRow++;
                 cache.ErrorMessage = "Unable to fetch from " + NodeType + ": " + e.Message;
                 if (e.InnerException != null)
                 {
                     cache.ErrorMessage += "\n" + e.InnerException.Message;
                 }
             }
             if (CacheItemFetched != null)
             {
                 CacheItemFetched(this, EventArgs.Empty);
             }
             CachedMonitorStatus = null;
         }
     });
 }
Exemplo n.º 4
0
        public static MonitorStatus GetWorstStatus(this IEnumerable <IMonitorStatus> ims, string cacheKey = null, int durationSeconds = 5)
        {
            MonitorStatus?result = null;

            if (cacheKey.HasValue())
            {
                result = Current.LocalCache.Get <MonitorStatus?>(cacheKey);
            }
            if (result == null)
            {
                result = GetWorstStatus(ims.Select(i => i.MonitorStatus));
                if (cacheKey.HasValue())
                {
                    Current.LocalCache.Set(cacheKey, result, durationSeconds);
                }
            }
            return(result.Value);
        }
Exemplo n.º 5
0
        public static MonitorStatus GetWorstStatus(this IEnumerable <IMonitorStatus> ims, string cacheKey = null, TimeSpan?duration = null)
        {
            duration = duration ?? 5.Seconds();
            if (ims == null)
            {
                return(MonitorStatus.Unknown);
            }
            MonitorStatus?result = null;

            if (cacheKey.HasValue())
            {
                result = Current.LocalCache.Get <MonitorStatus?>(cacheKey);
            }
            if (result == null)
            {
                result = GetWorstStatus(ims.Select(i => i.MonitorStatus));
                if (cacheKey.HasValue())
                {
                    Current.LocalCache.Set(cacheKey, result, duration);
                }
            }
            return(result.Value);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Invoked by a Cache instance on updating, using properties from the PollNode such as connection strings, etc.
        /// </summary>
        /// <typeparam name="T">Type of item in the cache</typeparam>
        /// <param name="description">Description of the operation, used purely for profiling</param>
        /// <param name="getData">The operation used to actually get data, e.g. <code>using (var conn = GetConnection()) { return getFromConnection(conn); }</code></param>
        /// <param name="logExceptions">Whether to log any exceptions to the log</param>
        /// <param name="addExceptionData">Optionally add exception data, e.g. <code>e => e.AddLoggedData("Server", Name)</code></param>
        /// <returns>A cache update action, used when creating a <see cref="Cache"/>.</returns>
        protected Action <Cache <T> > UpdateCacheItem <T>(string description,
                                                          Func <T> getData,
                                                          bool logExceptions = false, // TODO: Settings
                                                          Action <Exception> addExceptionData = null) where T : class
        {
            return(cache =>
            {
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    cache.Profiler = OpserverProfileProvider.CreateContextProfiler("Poll: " + description, cache.UniqueId);
                }
                using (MiniProfiler.Current.Step(description))
                {
                    if (CacheItemFetching != null)
                    {
                        CacheItemFetching(this, EventArgs.Empty);
                    }
                    try
                    {
                        using (MiniProfiler.Current.Step("Data Fetch"))
                        {
                            cache.Data = getData();
                        }
                        cache.LastSuccess = cache.LastPoll = DateTime.UtcNow;
                        cache.ErrorMessage = "";
                        PollFailsInaRow = 0;
                    }
                    catch (Exception e)
                    {
                        if (logExceptions)
                        {
                            if (addExceptionData != null)
                            {
                                addExceptionData(e);
                            }
                            Current.LogException(e);
                        }
                        cache.LastPoll = DateTime.UtcNow;
                        PollFailsInaRow++;
                        cache.ErrorMessage = "Unable to fetch from " + NodeType + ": " + e.Message;
#if DEBUG
                        cache.ErrorMessage += " @ " + e.StackTrace;
#endif

                        if (e.InnerException != null)
                        {
                            cache.ErrorMessage += "\n" + e.InnerException.Message;
                        }
                    }
                    if (CacheItemFetched != null)
                    {
                        CacheItemFetched(this, EventArgs.Empty);
                    }
                    CachedMonitorStatus = null;
                }
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    OpserverProfileProvider.StopContextProfiler();
                }
            });
        }
Exemplo n.º 7
0
        /// <summary>
        /// Invoked by a Cache instance on updating, using properties from the PollNode such as connection strings, etc.
        /// </summary>
        /// <typeparam name="T">Type of item in the cache</typeparam>
        /// <param name="description">Description of the operation, used purely for profiling</param>
        /// <param name="getData">The operation used to actually get data, e.g. <code>using (var conn = GetConnectionAsync()) { return getFromConnection(conn); }</code></param>
        /// <param name="logExceptions">Whether to log any exceptions to the log</param>
        /// <param name="addExceptionData">Optionally add exception data, e.g. <code>e => e.AddLoggedData("Server", Name)</code></param>
        /// <param name="timeoutMs">The timeout in milliseconds for this poll to complete before aborting.</param>
        /// <param name="afterPoll">An optional action to run after polling has completed successfully</param>
        /// <returns>A cache update action, used when creating a <see cref="Cache"/>.</returns>
        protected Func <Cache <T>, Task> UpdateCacheItem <T>(string description,
                                                             Func <Task <T> > getData,
                                                             bool logExceptions = false, // TODO: Settings
                                                             Action <Exception> addExceptionData = null,
                                                             int?timeoutMs = null,
                                                             Action <Cache <T> > afterPoll = null) where T : class
        {
            return(async cache =>
            {
                cache.PollStatus = "UpdateCacheItem";
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    cache.Profiler = OpserverProfileProvider.CreateContextProfiler("Poll: " + description, cache.UniqueId, store: false);
                }
                using (MiniProfiler.Current.Step(description))
                {
                    CacheItemFetching?.Invoke(this, EventArgs.Empty);
                    try
                    {
                        cache.PollStatus = "Fetching";
                        using (MiniProfiler.Current.Step("Data Fetch"))
                        {
                            var fetch = getData();
                            if (timeoutMs.HasValue)
                            {
                                if (await Task.WhenAny(fetch, Task.Delay(timeoutMs.Value)) == fetch)
                                {
                                    // Re-await for throws.
                                    cache.SetData(await fetch.ConfigureAwait(false));
                                }
                                else
                                {
                                    throw new TimeoutException($"Fetch timed out after {timeoutMs.ToString()} ms.");
                                }
                            }
                            else
                            {
                                cache.SetData(await fetch.ConfigureAwait(false));
                            }
                        }
                        cache.PollStatus = "Fetch Complete";
                        cache.SetSuccess();
                        PollFailsInaRow = 0;
                        afterPoll?.Invoke(cache);
                    }
                    catch (Exception e)
                    {
                        if (logExceptions)
                        {
                            addExceptionData?.Invoke(e);
                            Current.LogException(e);
                        }
                        PollFailsInaRow++;
                        var errorMessage = "Unable to fetch from " + NodeType + ": " + e.Message;
#if DEBUG
                        errorMessage += " @ " + e.StackTrace;
#endif
                        if (e.InnerException != null)
                        {
                            errorMessage += "\n" + e.InnerException.Message;
                        }
                        cache.PollStatus = "Fetch Failed";
                        cache.SetFail(errorMessage);
                    }
                    CacheItemFetched?.Invoke(this, EventArgs.Empty);
                    CachedMonitorStatus = null;
                    LastFetch = cache;
                }
                if (OpserverProfileProvider.EnablePollerProfiling)
                {
                    OpserverProfileProvider.StopContextProfiler();
                }
                cache.PollStatus = "UpdateCacheItem Complete";
            });
        }