/// <summary> /// Adds a node to the global polling list ONLY IF IT IS NEW /// If a node with the same unique key was already added, it will not be added again /// </summary> /// <param name="node">The node to add to the global polling list</param> /// <returns>Whether the node was added</returns> public static bool TryAdd(PollNode node) { lock (_addLock) { return AllPollNodes.Add(node); } }
/// <summary> /// Adds a node to the global polling list ONLY IF IT IS NEW /// If a node with the same unique key was already added, it will not be added again /// </summary> /// <param name="node">The node to add to the global polling list</param> /// <returns>Whether the node was added</returns> public static bool TryAdd(PollNode node) { lock (_addLock) { return(AllPollNodes.Add(node)); } }
public static bool TryRemove(PollNode node) { if (node == null || !node.AddedToGlobalPollers) return false; lock (_addLock) { return AllPollNodes.Remove(node); } }
public static NodeData FromNode(PollNode node, bool includeCache = false) { return(new NodeData { Name = node.UniqueKey, Type = node.NodeType, LastPolled = node.LastPoll, LastPollDurationMS = node.LastPollDuration.TotalMilliseconds, Caches = node.DataPollers.Select(c => CacheData.FromCache(c, includeCache)) }); }
public static bool TryRemove(PollNode node) { if (node == null || !node.AddedToGlobalPollers) { return(false); } lock (_addLock) { return(AllPollNodes.Remove(node)); } }
public static NodeData FromNode(PollNode node, bool includeCache = false) { return new NodeData { Name = node.UniqueKey, Type = node.NodeType, LastPolled = node.LastPoll, LastPollDurationMS = node.LastPollDuration.TotalMilliseconds, Caches = node.DataPollers.Select(c => CacheData.FromCache(c, includeCache)) }; }
/// <summary> /// Creates a cache poller /// </summary> /// <typeparam name="T">Type of item in the cache</typeparam> /// <param name="owner">The PollNode owner of this Cache</param> /// <param name="description">Description of the operation, used purely for profiling</param> /// <param name="cacheDuration">The length of time to cache data for</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="timeoutMs">The timeout in milliseconds for this poll to complete before aborting.</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="afterPoll">An optional action to run after polling has completed successfully</param> /// <param name="memberName"></param> /// <param name="sourceFilePath"></param> /// <param name="sourceLineNumber"></param> /// <returns>A cache update action, used when creating a <see cref="Cache"/>.</returns> public Cache(PollNode owner, string description, TimeSpan cacheDuration, Func <Task <T> > getData, int?timeoutMs = null, bool?logExceptions = null, Action <Exception> addExceptionData = null, Action <Cache <T> > afterPoll = null, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) : base(cacheDuration, memberName, sourceFilePath, sourceLineNumber) { MiniProfilerDescription = "Poll: " + description; // concatenate once // TODO: Settings via owner logExceptions = logExceptions ?? LogExceptions; _updateFunc = async() => { var success = true; PollStatus = "UpdateCacheItem"; if (EnableProfiling) { Profiler = _profilerOptions.StartProfiler(MiniProfilerDescription); Profiler.Id = UniqueId; } using (MiniProfiler.Current.Step(description)) { try { PollStatus = "Fetching"; using (MiniProfiler.Current.Step("Data Fetch")) { var task = getData(); if (timeoutMs.HasValue) { if (await Task.WhenAny(task, Task.Delay(timeoutMs.Value)) == task) { // Re-await for throws. Data = await task; } else { // This means the .WhenAny returned the timeout first...boom. throw new TimeoutException($"Fetch timed out after {timeoutMs} ms."); } } else { Data = await task; } } PollStatus = "Fetch Complete"; SetSuccess(); afterPoll?.Invoke(this); } catch (Exception e) { success = false; if (logExceptions.Value) { addExceptionData?.Invoke(e); e.Log(); } var errorMessage = StringBuilderCache.Get() .Append("Unable to fetch from ") .Append(owner.NodeType) .Append(": ") .Append(e.Message); #if DEBUG errorMessage.Append(" @ ").Append(e.StackTrace); #endif if (e.InnerException != null) { errorMessage.AppendLine().Append(e.InnerException.Message); } PollStatus = "Fetch Failed"; SetFail(e, errorMessage.ToStringRecycle()); } owner.PollComplete(this, success); } if (EnableProfiling) { Profiler.Stop(); } PollStatus = "UpdateCacheItem Complete"; return(Data); }; }