Files
awx/awx/ui/client/src/standard-out/log/standard-out-log.controller.js
Jared Tabor e0a566cdea adding socket coverage to child states
so that child states won't unsubscribe the parent from any groups
2016-10-04 14:23:39 -07:00

216 lines
9.2 KiB
JavaScript

/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default ['$log', '$rootScope', '$scope', '$state', '$stateParams', 'ProcessErrors', 'Rest', 'Wait',
function ($log, $rootScope, $scope, $state, $stateParams, ProcessErrors, Rest, Wait) {
var api_complete = false,
current_range,
loaded_sections = [],
event_queue = 0,
auto_scroll_down=true, // programmatic scroll to bottom
live_event_processing = true,
page_size = 500,
job_id = $stateParams.id;
$scope.should_apply_live_events = true;
// Open up a socket for events depending on the type of job
function openSockets() {
if ($state.current.name === 'jobDetail') {
$log.debug("socket watching on job_events-" + job_id);
$rootScope.$on(`ws-${$state.current.name}-job_events-${job_id}`, function() {
$log.debug("socket fired on job_events-" + job_id);
if (api_complete) {
event_queue++;
}
});
// Unbind $rootScope socket event binding(s) so that they don't get triggered
// in another instance of this controller
// $scope.$on('$destroy', function() {
// $rootScope.socket.removeAllListeners("job_events-" + job_id);
// });
}
if ($state.current.name === 'adHocJobStdout') {
$log.debug("socket watching on ad_hoc_command_events-" + job_id);
$rootScope.$on(`ws-${$state.current.name}-ad_hoc_command_events-${job_id}`, function() {
$log.debug("socket fired on ad_hoc_command_events-" + job_id);
if (api_complete) {
event_queue++;
}
});
// Unbind $rootScope socket event binding(s) so that they don't get triggered
// in another instance of this controller
// $scope.$on('$destroy', function() {
// $rootScope.adhoc_event_socket.removeAllListeners("ad_hoc_command_events-" + job_id);
// });
}
}
openSockets();
// This is a trigger for loading up the standard out
if ($scope.removeLoadStdout) {
$scope.removeLoadStdout();
}
$scope.removeLoadStdout = $scope.$on('LoadStdout', function() {
if (loaded_sections.length === 0) {
loadStdout();
}
else if (live_event_processing) {
getNextSection();
}
});
// This interval checks to see whether or not we've gotten a new
// event via sockets. If so, go out and update the standard out
// log.
$rootScope.jobStdOutInterval = setInterval( function() {
if (event_queue > 0) {
// events happened since the last check
$log.debug('checking for stdout...');
if (loaded_sections.length === 0) { ////this if statement for refresh
$log.debug('calling LoadStdout');
loadStdout();
}
else if (live_event_processing) {
$log.debug('calling getNextSection');
getNextSection();
}
event_queue = 0;
}
}, 2000);
// stdoutEndpoint gets passed through in the directive declaration.
// This watcher fires off loadStdout() when the endpoint becomes
// available.
$scope.$watch('stdoutEndpoint', function(newVal, oldVal) {
if(newVal && newVal !== oldVal) {
// Fire off the server call
loadStdout();
}
});
// stdoutText optionall gets passed through in the directive declaration.
$scope.$watch('stdoutText', function(newVal, oldVal) {
if(newVal && newVal !== oldVal) {
$('#pre-container-content').html(newVal);
}
});
function loadStdout() {
if (!$scope.stdoutEndpoint) {
return;
}
Rest.setUrl($scope.stdoutEndpoint + '?format=json&start_line=0&end_line=' + page_size);
Rest.get()
.success(function(data) {
Wait('stop');
if (data.content) {
api_complete = true;
$('#pre-container-content').html(data.content);
current_range = data.range;
if (data.content !== "Waiting for results...") {
loaded_sections.push({
start: (data.range.start < 0) ? 0 : data.range.start,
end: data.range.end
});
}
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
}
else {
api_complete = true;
}
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
});
}
function getNextSection() {
if (!$scope.stdoutEndpoint) {
return;
}
// get the next range of data from the API
var start = loaded_sections[loaded_sections.length - 1].end, url;
url = $scope.stdoutEndpoint + '?format=json&start_line=' + start + '&end_line=' + (start + page_size);
$('#stdoutMoreRowsBottom').fadeIn();
Rest.setUrl(url);
Rest.get()
.success( function(data) {
if ($('#pre-container-content').html() === "Waiting for results...") {
$('#pre-container-content').html(data.content);
} else {
$('#pre-container-content').append(data.content);
}
loaded_sections.push({
start: (data.range.start < 0) ? 0 : data.range.start,
end: data.range.end
});
if ($scope.should_apply_live_events) {
// if user has not disabled live event view by scrolling upward, then scroll down to the new content
current_range = data.range;
auto_scroll_down = true; // prevent auto load from happening
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
}
$('#stdoutMoreRowsBottom').fadeOut(400);
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
});
}
// lrInfiniteScroll handler
// grabs the next stdout section
$scope.stdOutGetNextSection = function(){
if (current_range.absolute_end > current_range.end){
var url = $scope.stdoutEndpoint + '?format=json&start_line=' + current_range.end +
'&end_line=' + (current_range.end + page_size);
Rest.setUrl(url);
Rest.get()
.success(function(data){
$('#pre-container-content').append(data.content);
current_range = data.range;
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
});
}
};
// We watch for job status changes here. If the job completes we want to clear out the
// stdout interval and kill the live_event_processing flag.
if ($scope.removeJobStatusChange) {
$scope.removeJobStatusChange();
}
$scope.removeJobStatusChange = $rootScope.$on(`ws-${$state.current.name}-jobs`, function(e, data) {
if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10)) {
if (data.status === 'failed' || data.status === 'canceled' ||
data.status === 'error' || data.status === 'successful') {
if ($rootScope.jobStdOutInterval) {
window.clearInterval($rootScope.jobStdOutInterval);
}
if (live_event_processing) {
if (loaded_sections.length === 0) {
loadStdout();
}
else {
getNextSection();
}
}
live_event_processing = false;
}
}
});
}];