/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var App = require('app'); App.BackgroundOperationsController = Em.Controller.extend({ name: 'backgroundOperationsController', /** * Whether we need to refresh background operations or not */ isWorking : false, allOperations: [], allOperationsCount : 0, executeTasks: [], /** * Task life time after finishing */ taskLifeTime: 5*60*1000, getOperationsForRequestId: function(requestId){ return this.get('allOperations').filterProperty('request_id', requestId); }, /** * Start polling, when isWorking become true */ startPolling: function(){ if(this.get('isWorking')){ App.updater.run(this, 'loadOperations', 'isWorking', App.bgOperationsUpdateInterval); } }.observes('isWorking'), /** * Reload operations * @param callback on done Callback. Look art App.updater.run for more information * @return jquery ajax object */ loadOperations : function(callback){ if(!App.get('clusterName')){ callback(); return null; } return App.ajax.send({ 'name': 'background_operations', 'sender': this, 'success': 'updateBackgroundOperations', //todo provide interfaces for strings and functions 'callback': callback }); }, /** * Callback for update finished task request. * @param data Json answer */ updateFinishedTask: function(data){ var executeTasks = this.get('executeTasks'); if (data) { var _oldTask = executeTasks.findProperty('id', data.Tasks.id); if(_oldTask){ data.Tasks.finishedTime = new Date().getTime(); $.extend(_oldTask, data.Tasks); } } }, /** * Update info about background operations * Put all tasks with command 'EXECUTE' into executeTasks, other tasks with it they are still running put into runningTasks * Put all task that should be shown in popup modal window into this.allOperations * @param data json loaded from server */ updateBackgroundOperations: function (data) { var runningTasks = []; var executeTasks = this.get('executeTasks'); data.items.forEach(function (item) { item.tasks.forEach(function (task) { task.Tasks.display_exit_code = (task.Tasks.exit_code !== 999); if (task.Tasks.command == 'EXECUTE') { var _oldTask = executeTasks.findProperty('id', task.Tasks.id); if (!_oldTask) { executeTasks.push(task.Tasks); } else { $.extend(_oldTask, task.Tasks); } } else if(['QUEUED', 'PENDING', 'IN_PROGRESS'].contains(task.Tasks.status)){ runningTasks.push(task.Tasks); } }); }); var time = new Date().getTime() - this.get('taskLifeTime'); var tasksToRemove = []; executeTasks.forEach(function(_task, index){ if(['FAILED', 'COMPLETED', 'TIMEDOUT', 'ABORTED'].contains(_task.status) && _task.finishedTime && _task.finishedTime < time){ tasksToRemove.push(index); } if(['QUEUED', 'PENDING', 'IN_PROGRESS'].contains(_task.status)){ App.ajax.send({ name: 'background_operations.update_task', data: { requestId: _task.request_id, taskId: _task.id }, 'sender': this, 'success': 'updateFinishedTask' }); } }, this); tasksToRemove.reverse().forEach(function(index){ executeTasks.removeAt(index); }); var currentTasks; currentTasks = runningTasks.concat(executeTasks); currentTasks = currentTasks.sort(function (a, b) { return a.id - b.id; }); this.get('allOperations').filterProperty('isOpen').forEach(function(task){ var _task = currentTasks.findProperty('id', task.id); if (_task) { _task.isOpen = true; } }); this.set('allOperations', currentTasks); this.set('allOperationsCount', runningTasks.length + executeTasks.filterProperty('status', 'PENDING').length + executeTasks.filterProperty('status', 'QUEUED').length + executeTasks.filterProperty('status', 'IN_PROGRESS').length); var eventsArray = this.get('eventsArray'); if (eventsArray.length) { var itemsToRemove = []; eventsArray.forEach(function(item){ //if when returns true if(item.when(this)){ //fire do method item.do(); //and remove it itemsToRemove.push(item); } }, this); itemsToRemove.forEach(function(item){ eventsArray.splice(eventsArray.indexOf(item), 1); }); } }, /** * Onclick handler for background operations number located right to logo * @return PopupObject For testing purposes */ showPopup: function(){ this.set('executeTasks', []); App.updater.immediateRun('loadOperations'); return App.ModalPopup.show({ headerClass: Ember.View.extend({ controller: this, template:Ember.Handlebars.compile('{{allOperationsCount}} Background Operations Running') }), bodyClass: Ember.View.extend({ controller: this, templateName: require('templates/main/background_operations_popup') }), onPrimary: function() { this.hide(); }, secondary : null }); }, /** * Example of data inside: * { * when : function(backgroundOperationsController){ * return backgroundOperationsController.getOperationsForRequestId(requestId).length == 0; * }, * do : function(){ * component.set('status', 'cool'); * } * } * * Function do will be fired once, when when returns true. * Example, how to use it, you can see in app\controllers\main\host\details.js */ eventsArray : [] });