浏览代码

HUE-7388 [core] Include schedule job counts into the global job count widget

The running job conter is now split into individual counters: one for YARN jobs,
one for Scheduler jobs... That way each one can be updated individually and new ones
(e.g. Impala queries...) can be easily added.

The status of the integrated scheduler is also pulled on the right assist Scheduler page.
Bit more polishing there to do on the UI but the goal is to add the logic/skeleton first
and iterate.

And now we have individual calls:
        huePubSub.subscribe('check.job.browser', checkYarnBrowserStatus);
        huePubSub.subscribe('check.schedules.browser', checkScheduleBrowserStatus);
        ... queries next.

And the global counter ones:
  $.when.apply($, [lastYarnBrowserRequest, lastScheduleBrowserRequest])
Romain Rigaux 8 年之前
父节点
当前提交
67ed22b

+ 21 - 2
desktop/core/src/desktop/templates/assist.mako

@@ -2552,13 +2552,19 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
             <!-- ko if: schedulerViewModelIsLoaded() && schedulerViewModel.coordinator.isDirty() -->
             <a data-bind="click: saveScheduler" href="javascript: void(0);">${ _('Save changes') }</a>
             <!-- /ko -->
-            <!-- ko if: schedulerViewModelIsLoaded() && ! schedulerViewModel.coordinator.isDirty() && ! viewSchedulerId()-->
+            <!-- ko if: schedulerViewModelIsLoaded() && ! schedulerViewModel.coordinator.isDirty() && (! viewSchedulerId() || isSchedulerJobRunning() == false )-->
             <a data-bind="click: showSubmitPopup" href="javascript: void(0);">${ _('Start') }</a>
             <!-- /ko -->
             <!-- ko if: schedulerViewModelIsLoaded() && viewSchedulerId()-->
             <a data-bind="click: function() { huePubSub.publish('show.jobs.panel', viewSchedulerId()) }, clickBubble: false" href="javascript: void(0);">
               ${ _('View') }
             </a>
+            <!-- ko if: isSchedulerJobRunning() -->
+              ${ _("Running")}
+            <!-- /ko -->
+            <!-- ko if: isSchedulerJobRunning() == false -->
+              ${ _("Stopped")}
+            <!-- /ko -->
           <!-- /ko -->
           <!-- /ko -->
           <br>
@@ -2583,10 +2589,23 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
         var selectedNotebookSub = self.selectedNotebook.subscribe(function (notebook) { // Happening 4 times for each notebook loaded
           if (notebook && notebook.schedulerViewModel == null && notebook.isSaved() && ! notebook.isHistory()) {
             notebook.loadScheduler();
+            if (notebook.viewSchedulerId()) {
+              huePubSub.publish('check.schedules.browser');
+            }
           }
         });
         self.disposals.push(selectedNotebookSub.dispose.bind(selectedNotebookSub));
 
+        var setSelectedNotebookSub = huePubSub.subscribe('jobbrowser.schedule.data', function (jobs) {
+          if (self.selectedNotebook() && self.selectedNotebook().viewSchedulerId()) {
+            var _job = $.grep(jobs, function (job) {
+              return self.selectedNotebook().viewSchedulerId() == job.id;
+            });
+            self.selectedNotebook().isSchedulerJobRunning(_job.length > 0 && _job[0].apiStatus == 'RUNNING');
+          }
+        });
+        self.disposals.push(setSelectedNotebookSub.remove.bind(setSelectedNotebookSub));
+
         // Hue 3
         var setSelectedNotebookSub = huePubSub.subscribe('set.selected.notebook', self.selectedNotebook);
         self.disposals.push(setSelectedNotebookSub.remove.bind(setSelectedNotebookSub));
@@ -2606,7 +2625,7 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
               });
             }
           } else {
-            self.selectedNotebook(undefined);
+            self.selectedNotebook(null);
           }
         });
         self.disposals.push(currentAppSub.remove.bind(currentAppSub));

+ 47 - 13
desktop/core/src/desktop/templates/ko_components.mako

@@ -492,17 +492,19 @@ from desktop.views import _ko
           }
         });
 
-        self.jobCount = ko.observable(0);
+        self.jobCounts = ko.observable({'yarn': 0, 'schedules': 0});
+        self.jobCount = ko.pureComputed(function() {
+          var total = 0;
+          Object.keys(self.jobCounts()).forEach(function (value) {
+            total += self.jobCounts()[value];
+          });
+          return total;
+        });
         self.onePageViewModel = params.onePageViewModel;
 
-        var lastJobBrowserRequest = null;
-
-        var checkJobBrowserStatus = function() {
-          if (lastJobBrowserRequest !== null && lastJobBrowserRequest.readyState < 4) {
-            return;
-          }
-          window.clearTimeout(checkJobBrowserStatusIdx);
-          lastJobBrowserRequest = $.post("/jobbrowser/jobs/", {
+        var lastYarnBrowserRequest = null;
+        var checkYarnBrowserStatus = function() {
+          return $.post("/jobbrowser/jobs/", {
               "format": "json",
               "state": "running",
               "user": "${user.username}"
@@ -510,14 +512,45 @@ from desktop.views import _ko
             function(data) {
               if (data != null && data.jobs != null) {
                 huePubSub.publish('jobbrowser.data', data.jobs);
-                self.jobCount(data.jobs.length);
+                self.jobCounts()['yarn'] = data.jobs.length;
+                self.jobCounts.valueHasMutated();
+              }
+          })
+        };
+        var lastScheduleBrowserRequest = null;
+        var checkScheduleBrowserStatus = function() {
+          return $.post("/jobbrowser/api/jobs", {
+              interface: ko.mapping.toJSON("schedules"),
+              filters: ko.mapping.toJSON([
+                  {"text": "user:${user.username}"},
+                  {"time": {"time_value": 7, "time_unit": "days"}},
+                  {"states": ["running"]},
+                  {"pagination": {"page": 1, "offset": 1, "limit": 1}}
+              ])
+            },
+            function(data) {
+              if (data != null && data.total != null) {
+                huePubSub.publish('jobbrowser.schedule.data', data.apps);
+                self.jobCounts()['schedules'] = data.total;
+                self.jobCounts.valueHasMutated();
               }
-              checkJobBrowserStatusIdx = window.setTimeout(checkJobBrowserStatus, JB_CHECK_INTERVAL_IN_MILLIS);
-            }).fail(function () {
+          })
+        };
+
+        var checkJobBrowserStatus = function() {
+          lastYarnBrowserRequest = checkYarnBrowserStatus();
+          lastScheduleBrowserRequest = checkScheduleBrowserStatus();
+
+          $.when.apply($, [lastYarnBrowserRequest, lastScheduleBrowserRequest])
+          .done(function () {
+            checkJobBrowserStatusIdx = window.setTimeout(checkJobBrowserStatus, JB_CHECK_INTERVAL_IN_MILLIS);
+           })
+          .fail(function () {
             window.clearTimeout(checkJobBrowserStatusIdx);
           });
         };
 
+
         // Load the mini jobbrowser
         $.ajax({
           url: '/jobbrowser/apps?is_embeddable=true&is_mini=true',
@@ -533,7 +566,8 @@ from desktop.views import _ko
 
         var checkJobBrowserStatusIdx = window.setTimeout(checkJobBrowserStatus, 10);
 
-        huePubSub.subscribe('check.job.browser', checkJobBrowserStatus);
+        huePubSub.subscribe('check.job.browser', checkYarnBrowserStatus);
+        huePubSub.subscribe('check.schedules.browser', checkScheduleBrowserStatus);
       };
 
       ko.components.register('hue-job-browser-links', {

+ 1 - 0
desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js

@@ -2612,6 +2612,7 @@ var EditorViewModel = (function() {
     self.viewSchedulerId.subscribe(function(newVal) {
       self.save();
     });
+    self.isSchedulerJobRunning = ko.observable();
     self.loadingScheduler = ko.observable(false);
 
 

+ 5 - 0
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -346,6 +346,11 @@ ${ sqlSyntaxDropdown.sqlSyntaxDropdown() }
           <li data-bind="visible: isSaved() && ! isHistory() && ! parentSavedQueryUuid()" style="display: none" class="no-horiz-padding muted">
             <a title="${ _('This is a saved query') }"><i class="fa fa-fw fa-file-o"></i></a>
           </li>
+          <li data-bind="visible: isSchedulerJobRunning" style="display: none" class="no-horiz-padding muted">
+            <a title="${ _('Click to open original saved query') }" data-bind="click: function() { $root.openNotebook(parentSavedQueryUuid()) }" class="pointer inactive-action">
+              ${ _("Scheduling on") }
+            </a>
+          </li>
           <li class="query-name no-horiz-padding skip-width-calculation">
             <a href="javascript:void(0)">
               <div class="notebook-name-desc" data-bind="editable: name, editableOptions: { inputclass: 'notebook-name-input', enabled: true, placement: 'bottom', emptytext: '${_ko('Add a name...')}', tpl: '<input type=\'text\' maxlength=\'255\'>' }"></div>