/// <summary> /// Initi Rx streams /// </summary> private void InitRx() { expireds = new ConcurrentDictionary <string, IObservable <Heartbeat> >(); subscriptions = new ConcurrentDictionary <string, IDisposable>(); foreach (var stream in streamNames) { TimeSpan timer = GetTimespanForStream(stream); var clients = new Subject <Heartbeat>(); ObservedClients.TryAdd(stream, clients); // LINQ against the clients Observable // group clients by the Stream name + throttling the following events in each group // by the predefined timer value (after the first event in a certain group all following events will // be ignored). After the timeout has been reached the group will be recreated when a new element with // the same group Id arrives. var expired = clients.Synchronize().GroupByUntil(beat => beat.CustomerId, group => group.Throttle(timer)) .SelectMany(group => group.TakeLast(1)); expireds.TryAdd(stream, expired); var subscription = expired.Subscribe <Heartbeat>(OnClientDisconnect, ex => AdvaricsHelper.Log("Error: " + ex.Message, "Warning"), () => AdvaricsHelper.Log("Completed.")); subscriptions.TryAdd(stream, subscription); AdvaricsHelper.Log(string.Format("Initialized subscription for stream {0}", stream)); } }
/// <summary> /// This method will be called each time a client misses to send a heartbeat within the predefined time frame /// Technically this means when a new client has been inserted into the expireds-Observable collection /// </summary> /// <param name="beat"></param> private void OnClientDisconnect(Heartbeat beat) { AdvaricsHelper.Log( string.Format("Disconnected Client {0} in {1} at {2}", beat.InstanceId.ToString(), beat.StreamName, beat.CustomerName)); string subject = string.Format("Disconnect at customer: {0}", beat.CustomerName); string message = string.Format("Client Id: {0}\r\nCustomer: {1}\r\nStream: {2}", beat.InstanceId, beat.CustomerName, beat.StreamName); AdvaricsHelper.SendEmail(subject, message); }
public static void OnHeartBeat(object sender, HeartbeatEventArgs e) { Heartbeat beat = new Heartbeat { AppName = e.AppName, AppVersion = e.AppVersion, CreatedAt = e.CreatedAt, CustomerId = e.CustomerId, CustomerName = e.CustomerName, StreamName = e.StreamName, Id = e.HeartbeatId, InstanceId = e.InstanceId }; WebRole.RxHelper.ObservedClients[e.StreamName].OnNext(beat); AdvaricsHelper.Log( string.Format("Heartbeat from Client {0} in {1} at {2}", beat.InstanceId.ToString(), beat.StreamName, beat.CustomerName)); }
/// <summary> /// Get timer values from config /// </summary> private void LoadTimerSettings() { streamTimers = new ConcurrentDictionary <string, TimeSpan>(); int defaultTimeToHold = int.Parse(AdvaricsHelper.GetConfigurationSettingValue("RxStreamTimerDefault")); foreach (var streamName in streamNames) { string value = null; try { value = AdvaricsHelper.GetConfigurationSettingValue(rxStreamTimerPrefix + streamName); streamTimers.TryAdd(streamName, TimeSpan.FromSeconds(int.Parse(value))); } catch { streamTimers.TryAdd(streamName, TimeSpan.FromSeconds(defaultTimeToHold)); } AdvaricsHelper.Log(string.Format( "Setting {0} timer to {1} seconds", streamName, streamTimers[streamName].Seconds.ToString())); } }
/// <summary> /// Get Rx stream names from config /// </summary> private void LoadStreamSettings() { streamNames = AdvaricsHelper.GetConfigurationSettingValue("RxStreams").Split(new[] { ',' }); }