using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Aurora.Proto.Events; namespace Aurora.Services.EventManager { public class EventManager : BaseService<EventManager> { #region Fields private Dictionary<string, List<EventType>> _subscriptionList; private Dictionary<string, Action<BaseEvent>> _actionList; #endregion Fields public EventManager() { _subscriptionList = new Dictionary<string, List<EventType>>(); _actionList = new Dictionary<string, Action<BaseEvent>>(); } #region Private Methods #endregion Private Methods #region Public Methods /// <summary> /// Get the list of event type subscriptions for a given session id. /// </summary> /// <param name="session">Session Id</param> /// <returns></returns> public List<EventType> GetSubscriptionList(string session) { List<EventType> eventList = new List<EventType>(); if (_subscriptionList.ContainsKey(session)) { _subscriptionList.TryGetValue(session, out eventList); } return eventList; } /// <summary> /// Get the number of event subscriptions for a given session /// </summary> /// <param name="session">Session Id</param> /// <returns></returns> public int GetSubscriptionCount(string session) { List<EventType> eventList = new List<EventType>(); if (_subscriptionList.ContainsKey(session)) { _subscriptionList.TryGetValue(session, out eventList); } return eventList.Count(); } /// <summary> /// Add a new subscription /// </summary> /// <param name="session"></param> /// <param name="type"></param> public bool AddSubscription(string session, EventType type) { bool success = false; lock (_subscriptionList) { if (!_subscriptionList.ContainsKey(session)) { //Add session to subscription list List<EventType> eventList = new List<EventType>(); eventList.Add(type); _subscriptionList.Add(session, eventList); success = true; } else { _subscriptionList.TryGetValue(session, out List<EventType> eventList); if (eventList != null) { eventList.Add(type); success = true; } } } return success; } /// <summary> /// Add a list of subscriptions. This unsubscribes from unused events. /// </summary> /// <param name="session">The browser session id.</param> /// <param name="types">The list of event types to subscribe to.</param> public void AddSubscriptionList(string session, List<EventType> types) { RemoveAllSubscriptions(session); foreach (EventType e in types) { AddSubscription(session, e); } } /// <summary> /// Unsubscribe from a given event type. /// </summary> /// <param name="session">Session Id</param> /// <param name="type">Event Type to be removed</param> public void RemoveSubscription(string session, EventType type) { lock (_subscriptionList) { if (_subscriptionList.ContainsKey(session)) { List<EventType> eventTypeList; _subscriptionList.TryGetValue(session, out eventTypeList); if (eventTypeList != null && eventTypeList.Contains(type)) { eventTypeList.Remove(type); //base.LogInformation(string.Format("Subscription removed for event type {0} subscription on session {1}", type.ToString(), session)); } } } } public void RemoveSubscriptionList(string session, List<EventType> types) { foreach (EventType e in types) { RemoveSubscription(session, e); } } /// <summary> /// Remove all subscriptons for a given session. /// </summary> /// <param name="session">Session Id</param> public void RemoveAllSubscriptions(string session) { if (_subscriptionList.ContainsKey(session)) { _subscriptionList.Remove(session); } } public void AddEventHandler(Action<BaseEvent> action, string sessionId) { lock (_actionList) { _actionList.Add(sessionId, action); } } public void RemoveEventHandler(string sessionId) { _actionList.Remove(sessionId); } public void FireEvent(BaseEvent bEvent) { Dictionary<string, Action<BaseEvent>> actionsCopy = new Dictionary<string, Action<BaseEvent>>(); //Copy actions list lock (_actionList) { foreach (KeyValuePair<string, Action<BaseEvent>> pair in _actionList) { actionsCopy.Add(pair.Key, pair.Value); } } lock (_subscriptionList) { foreach (KeyValuePair<string, List<EventType>> pair in _subscriptionList) { Task.Delay(1000); //If action list contains an action for id, invoke if (actionsCopy.ContainsKey(pair.Key)) { actionsCopy.TryGetValue(pair.Key, out Action<BaseEvent> action); Task executionTask = new Task(() => action(bEvent)); //Execute task with exception handler executionTask.ContinueWith((Task task) => { var exception = executionTask.Exception; System.Diagnostics.Debug.WriteLine(string.Format("SERVER --- Exception occurred firing event")); this._actionList.Remove(pair.Key); }, TaskContinuationOptions.OnlyOnFaulted); executionTask.Start(); } } } } #endregion Public Methods } }