예제 #1
0
        //===================================================================== Hub API

        public async Task <SnTask> GetTask(string machineName, string agentName, string[] capabilities)
        {
            SnTrace.TaskManagement.Write("AgentHub GetTask called. Agent: {0}, capabilities: {1}.", agentName, string.Join(", ", capabilities));

            try
            {
                var task = await _dataHandler.GetNextAndLock(machineName, agentName, capabilities, Context.ConnectionAborted)
                           .ConfigureAwait(false);

                SnTrace.TaskManagement.Write("AgentHub TaskDataHandler.GetNextAndLock returned: " + (task == null ? "null" : "task " + task.Id));

                // task details are not passed to the monitor yet
                if (task != null)
                {
                    await _monitorHub.OnTaskEvent(SnTaskEvent.CreateStartedEvent(task.Id, task.Title, null,
                                                                                 task.AppId, task.Tag, machineName, agentName)).ConfigureAwait(false);
                }

                return(task);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "AgentHub GetTask failed.", EventId.TaskManagement.General);
            }

            return(null);
        }
        /// <summary>
        /// Calls the OnTaskEvent client method when a task state event occurs (e.g. started, finished, etc.).
        /// Only clients with the appropriate app id are called.
        /// </summary>
        public static void OnTaskEvent(SnTaskEvent e)
        {
            SnTrace.TaskManagement.Write("TaskMonitorHub OnTaskEvent: {0}, taskId: {1}, agent: {2}", e.EventType, e.TaskId, e.Agent);

            var hubContext = GlobalHost.ConnectionManager.GetHubContext <TaskMonitorHub>();

            // Send events to clients with the same app id only. Monitor clients are
            // registered to the appropriate group in the OnConnected event handler.
            hubContext.Clients.Group(e.AppId).OnTaskEvent(e);
        }
예제 #3
0
        public void TaskFinished(SnTaskResult taskResult)
        {
            SnTrace.TaskManagement.Write("AgentHub TaskFinished called. Agent: {0} / {1}, taskId: {2}, code: {3}, error: {4}",
                                         taskResult.MachineName, taskResult.AgentName, taskResult.Task.Id, taskResult.ResultCode,
                                         taskResult.Error == null ? "" : taskResult.Error.Message);
            try
            {
                if (string.IsNullOrEmpty(taskResult.Task.AppId))
                {
                    SnLog.WriteWarning($"AppId is empty for task #{taskResult.Task.Id}.",
                                       EventId.TaskManagement.Lifecycle);
                    return;
                }

                var doesApplicationNeedNotification = !string.IsNullOrWhiteSpace(taskResult.Task.GetFinalizeUrl());
                // first we make sure that the app is accessible by sending a ping request
                if (doesApplicationNeedNotification && !ApplicationHandler.SendPingRequest(taskResult.Task.AppId))
                {
                    var app = ApplicationHandler.GetApplication(taskResult.Task.AppId);

                    SnLog.WriteError(string.Format("Ping request to application {0} ({1}) failed when finalizing task #{2}. Task success: {3}, error: {4}",
                                                   taskResult.Task.AppId,
                                                   app == null ? "unknown app" : app.ApplicationUrl,
                                                   taskResult.Task.Id,
                                                   taskResult.Successful,
                                                   taskResult.Error == null ? "-" : taskResult.Error.ToString()),
                                     EventId.TaskManagement.Communication);

                    doesApplicationNeedNotification = false;
                }

                // remove the task from the database first
                TaskDataHandler.FinalizeTask(taskResult);

                SnTrace.TaskManagement.Write("AgentHub TaskFinished: task {0} has been deleted.", taskResult.Task.Id);

                if (doesApplicationNeedNotification)
                {
                    // This method does not need to be awaited, because we do not want to do anything
                    // with the result, only notify the app that the task has been finished.
                    ApplicationHandler.SendFinalizeNotificationAsync(taskResult);
                }

                // notify monitors
                TaskMonitorHub.OnTaskEvent(taskResult.Successful
                    ? SnTaskEvent.CreateDoneEvent(taskResult.Task.Id, taskResult.Task.Title, taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag, taskResult.MachineName, taskResult.AgentName)
                    : SnTaskEvent.CreateFailedEvent(taskResult.Task.Id, taskResult.Task.Title, taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag, taskResult.MachineName, taskResult.AgentName));
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "AgentHub TaskFinished failed.", EventId.TaskManagement.General);
            }
        }
예제 #4
0
 public void FinishSubtask(string machineName, string agentName, SnSubtask subtask, SnTask task)
 {
     SnTrace.TaskManagement.Write("AgentHub FinishSubtask. Task id:{0}, agent:{1}, title:{2}", task.Id, agentName, subtask.Title);
     try
     {
         TaskDataHandler.FinishSubtask(machineName, agentName, subtask, task);
         TaskMonitorHub.OnTaskEvent(SnTaskEvent.CreateSubtaskFinishedEvent(task.Id, subtask.Title, subtask.Details, task.AppId, task.Tag, machineName, agentName, subtask.Id));
     }
     catch (Exception ex)
     {
         SnLog.WriteException(ex, "AgentHub FinishSubtask failed.", EventId.TaskManagement.General);
     }
 }
예제 #5
0
        public async Task FinishSubtask(string machineName, string agentName, SnSubtask subtask, SnTask task)
        {
            SnTrace.TaskManagement.Write("AgentHub FinishSubtask. Task id:{0}, agent:{1}, title:{2}", task.Id, agentName, subtask.Title);
            try
            {
                await _dataHandler.FinishSubtask(machineName, agentName, subtask, task, Context.ConnectionAborted).ConfigureAwait(false);

                await _monitorHub.OnTaskEvent(SnTaskEvent.CreateSubtaskFinishedEvent(task.Id, subtask.Title, subtask.Details,
                                                                                     task.AppId, task.Tag, machineName, agentName, subtask.Id)).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "AgentHub FinishSubtask failed.", EventId.TaskManagement.General);
            }
        }
예제 #6
0
        //===================================================================== Hub API

        public SnTask GetTask(string machineName, string agentName, string[] capabilities)
        {
            SnTrace.TaskManagement.Write("AgentHub GetTask called. Agent: {0}, capabilities: {1}.", agentName, string.Join(", ", capabilities));

            try
            {
                var task = TaskDataHandler.GetNextAndLock(machineName, agentName, capabilities);
                SnTrace.TaskManagement.Write("AgentHub TaskDataHandler.GetNextAndLock returned with: " + (task == null ? "null" : "task " + task.Id.ToString()));

                // task details are not passed to the monitor yet
                if (task != null)
                {
                    TaskMonitorHub.OnTaskEvent(SnTaskEvent.CreateStartedEvent(task.Id, task.Title, null, task.AppId, task.Tag, machineName, agentName));
                }

                return(task);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "AgentHub GetTask failed.", EventId.TaskManagement.General);
            }

            return(null);
        }
예제 #7
0
 /// <summary>
 /// Calls the onTaskEvent client method when a task state event occurs (e.g. started, finished, etc.).
 /// Only clients with the appropriate app id are called.
 /// </summary>
 public static async Task OnTaskEvent(this IHubContext <TaskMonitorHub> hubContext, SnTaskEvent taskEvent)
 {
     try
     {
         // Send events to clients with the same app id only. Monitor clients are
         // registered to the appropriate group in the OnConnected event handler.
         await hubContext.Clients.Group(taskEvent.AppId).SendAsync("onTaskEvent", taskEvent)
         .ConfigureAwait(false);
     }
     catch (Exception ex)
     {
         SnLog.WriteException(ex, "TaskMonitorHub OnTaskEvent failed.", EventId.TaskManagement.General);
     }
 }
예제 #8
0
        public RegisterTaskResult RegisterTask(RegisterTaskRequest taskRequest)
        {
            Application app = null;

            try
            {
                // load the corresponding application to make sure the appid is valid
                app = ApplicationHandler.GetApplication(taskRequest.AppId);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "Error loading app for id " + taskRequest.AppId, EventId.TaskManagement.General);
            }

            // If we do not know the appid, we must not register the task. Client applications
            // must observe this response and try to re-register the application, before
            // trying to register the task again (this can happen if the TaskManagement Web
            // was unreachable when the client application tried to register the appid before).
            if (app == null)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, RegisterTaskRequest.ERROR_UNKNOWN_APPID));
            }

            RegisterTaskResult result = null;

            try
            {
                // calculate hash with the default algrithm if not given
                var hash = taskRequest.Hash == 0
                    ? ComputeTaskHash(taskRequest.Type + taskRequest.AppId + taskRequest.Tag + taskRequest.TaskData)
                    : taskRequest.Hash;

                result = TaskDataHandler.RegisterTask(
                    taskRequest.Type,
                    taskRequest.Title,
                    taskRequest.Priority,
                    taskRequest.AppId,
                    taskRequest.Tag,
                    taskRequest.FinalizeUrl,
                    hash,
                    taskRequest.TaskData,
                    taskRequest.MachineName);
            }
            catch (Exception ex)
            {
                // the client app needs to be notified
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, ex));
            }

            try
            {
                // notify agents
                AgentHub.BroadcastMessage(result.Task);

                // notify monitor clients
                TaskMonitorHub.OnTaskEvent(SnTaskEvent.CreateRegisteredEvent(
                                               result.Task.Id, result.Task.Title, string.Empty, result.Task.AppId,
                                               result.Task.Tag, null, result.Task.Type, result.Task.Order,
                                               result.Task.Hash, result.Task.TaskData));
            }
            catch (Exception ex)
            {
                // The task has been created successfully, this error is only about
                // notification, so client applications should not be notified.
                SnLog.WriteException(ex, "Error during agent or monitor notification after a task was registered.", EventId.TaskManagement.Communication);
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Calls the OnTaskEvent client method when a task state event occurs (e.g. started, finished, etc.).
        /// Only clients with the appropriate app id are called.
        /// </summary>
        public void OnTaskEvent(SnTaskEvent e)
        {
            SnTrace.System.Write("SNTaskMonitorHub OnTaskEvent: {0}, taskId: {1}, agent: {2}", e.EventType, e.TaskId, e.Agent);

            Clients.Group(e.AppId).OnTaskEvent(e);
        }
예제 #10
0
        public async Task TaskFinished(SnTaskResult taskResult)
        {
            SnTrace.TaskManagement.Write("AgentHub TaskFinished called. Agent: {0} / {1}, taskId: {2}, code: {3}, error: {4}",
                                         taskResult.MachineName, taskResult.AgentName, taskResult.Task.Id, taskResult.ResultCode,
                                         taskResult.Error == null ? "" : taskResult.Error.Message);
            try
            {
                if (string.IsNullOrEmpty(taskResult.Task.AppId))
                {
                    SnLog.WriteWarning($"AppId is empty for task #{taskResult.Task.Id}.",
                                       EventId.TaskManagement.Lifecycle);
                    return;
                }

                var app = _applicationHandler.GetApplication(taskResult.Task.AppId);
                var doesApplicationNeedNotification = !string.IsNullOrWhiteSpace(taskResult.Task.GetFinalizeUrl(app));

                // first we make sure that the app is accessible by sending a ping request
                if (doesApplicationNeedNotification && !(await _applicationHandler.SendPingRequestAsync(taskResult.Task.AppId, Context.ConnectionAborted)
                                                         .ConfigureAwait(false)))
                {
                    SnLog.WriteError($"Ping request to application {taskResult.Task.AppId} " +
                                     $"({(app == null ? "unknown app" : app.ApplicationUrl)}) " +
                                     $"failed when finalizing task #{taskResult.Task.Id}. " +
                                     $"Task success: {taskResult.Successful}, " +
                                     $"error: {(taskResult.Error == null ? "-" : taskResult.Error.ToString())}",
                                     EventId.TaskManagement.Communication);

                    doesApplicationNeedNotification = false;
                }

                // remove the task from the database first
                await _dataHandler.FinalizeTaskAsync(taskResult, Context.ConnectionAborted).ConfigureAwait(false);

                SnTrace.TaskManagement.Write("AgentHub TaskFinished: task {0} has been deleted.", taskResult.Task.Id);

                if (doesApplicationNeedNotification)
                {
                    // This method does not need to be awaited, because we do not want to do anything
                    // with the result, only notify the app that the task has been finished.
#pragma warning disable 4014
                    _applicationHandler.SendFinalizeNotificationAsync(taskResult, CancellationToken.None);
#pragma warning restore 4014
                }

                // notify monitors
                var te = taskResult.Successful
                    ? SnTaskEvent.CreateDoneEvent(taskResult.Task.Id, taskResult.Task.Title,
                                                  taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag,
                                                  taskResult.MachineName, taskResult.AgentName)
                    : SnTaskEvent.CreateFailedEvent(taskResult.Task.Id, taskResult.Task.Title,
                                                    taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag,
                                                    taskResult.MachineName, taskResult.AgentName);

                await _monitorHub.OnTaskEvent(te).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "AgentHub TaskFinished failed.", EventId.TaskManagement.General);
            }
        }
예제 #11
0
        public async Task <RegisterTaskResult> RegisterTask([FromBody] RegisterTaskRequest taskRequest)
        {
            Application app = null;

            try
            {
                // load the corresponding application to make sure the appid is valid
                app = _applicationHandler.GetApplication(taskRequest.AppId);
            }
            catch (Exception ex)
            {
                SnLog.WriteException(ex, "Error loading app for id " + taskRequest.AppId, EventId.TaskManagement.General);
            }

            // If we do not know the appid, we must not register the task. Client applications
            // must observe this response and try to re-register the application, before
            // trying to register the task again (this can happen if the TaskManagement Web
            // was unreachable when the client application tried to register the appid before).
            if (app == null)
            {
                return(new RegisterTaskResult {
                    Error = RegisterTaskRequest.ERROR_UNKNOWN_APPID
                });
            }

            RegisterTaskResult result;

            try
            {
                // calculate hash with the default algorithm if not given
                var hash = taskRequest.Hash == 0
                    ? ComputeTaskHash(taskRequest.Type + taskRequest.AppId + taskRequest.Tag + taskRequest.TaskData)
                    : taskRequest.Hash;

                result = await _dataHandler.RegisterTaskAsync(
                    taskRequest.Type,
                    taskRequest.Title,
                    taskRequest.Priority,
                    taskRequest.AppId,
                    taskRequest.Tag,
                    taskRequest.FinalizeUrl,
                    hash,
                    taskRequest.TaskData,
                    taskRequest.MachineName,
                    HttpContext.RequestAborted).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                var msg = $"Task registration failed. {ex.Message} AppId: {app.AppId}, " +
                          $"Task: {taskRequest.Type}, Title: {taskRequest.Title}";

                SnLog.WriteException(ex, msg);

                return(new RegisterTaskResult {
                    Error = RegisterTaskResult.ErrorTaskRegistrationFailed
                });
            }

            try
            {
                // notify agents
                await _agentHub.BroadcastNewTask(result.Task).ConfigureAwait(false);

                // notify monitor clients
                await _monitorHub.OnTaskEvent(SnTaskEvent.CreateRegisteredEvent(
                                                  result.Task.Id, result.Task.Title, string.Empty, result.Task.AppId,
                                                  result.Task.Tag, null, result.Task.Type, result.Task.Order,
                                                  result.Task.Hash, result.Task.TaskData)).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                // The task has been created successfully, this error is only about
                // notification, so client applications should not be notified.
                SnLog.WriteException(ex, "Error during agent or monitor notification after a task was registered.", EventId.TaskManagement.Communication);
            }

            return(result);
        }