using Disco.Services.Web.Signalling; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using System; using System.Collections.Generic; using System.Reactive.Linq; using System.Linq; namespace Disco.Services.Tasks { using System.Reactive.Subjects; using ChangedItem = KeyValuePair; [HubName("scheduledTaskNotifications"), DiscoHubAuthorize()] public class ScheduledTaskNotificationsHub : Hub { private const string NotificationsPrefix = "Logging_"; private static Subject>> taskUpdatesStream = new Subject>>(); private static IDisposable taskUpdatesStreamSubscription; static ScheduledTaskNotificationsHub() { taskUpdatesStreamSubscription = taskUpdatesStream .DelayBuffer(TimeSpan.FromMilliseconds(200)) .Subscribe(BroadcastBufferedEvents); } internal static void PublishEvent(string TaskSessionId, IEnumerable ChangedItems) { taskUpdatesStream.OnNext(Tuple.Create(TaskSessionId, ChangedItems)); } public override System.Threading.Tasks.Task OnConnected() { var taskSessionId = Context.QueryString["TaskSessionId"]; // Send Status: var currentStatus = GetScheduledTaskLiveStatus(taskSessionId); Clients.Caller.initializeTaskStatus(currentStatus); // Add to Group var groupName = NotificationsPrefix + taskSessionId; Groups.Add(Context.ConnectionId, groupName); return base.OnConnected(); } private static void BroadcastBufferedEvents(IEnumerable>> Events) { var connectionManager = GlobalHost.ConnectionManager; var context = connectionManager.GetHubContext(); var taskStatusEvents = Events.GroupBy(e => e.Item1).Select(taskEventsGroup => { Dictionary changes = new Dictionary(); foreach (var changeEvents in taskEventsGroup.Select(taskEvents => taskEvents.Item2)) foreach (var changeEvent in changeEvents) changes[changeEvent.Key] = changeEvent.Value; return Tuple.Create(taskEventsGroup.Key, changes); }); foreach (var taskStatusEvent in taskStatusEvents) { var groupName = NotificationsPrefix + taskStatusEvent.Item1; context.Clients.Group(groupName).updateTaskStatus(taskStatusEvent.Item2); } } private ScheduledTaskStatusLive GetScheduledTaskLiveStatus(string TaskSessionId) { if (string.IsNullOrEmpty(TaskSessionId)) throw new ArgumentNullException("TaskSessionId"); var status = ScheduledTasks.GetTaskStatus(TaskSessionId); if (status == null) throw new ArgumentException("Invalid ScheduledTask SessionId", "TaskSessionId"); // Send Status: return ScheduledTaskStatusLive.FromScheduledTaskStatus(status, null); } public ScheduledTaskStatusLive GetStatus() { var taskSessionId = Context.QueryString["TaskSessionId"]; return GetScheduledTaskLiveStatus(taskSessionId); } } }