//===================================================================== 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); }
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); } }
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); } }
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); } }
//===================================================================== 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); }
/// <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); } }
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); }
/// <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); }
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); } }
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); }