Browse Source

Merge branch 'cancel-in-flight-repeats' of https://github.com/stuartnelson3/grafana into stuartnelson3-cancel-in-flight-repeats

Torkel Ödegaard 9 năm trước cách đây
mục cha
commit
6d3521c240

+ 30 - 2
public/app/core/services/backend_srv.js

@@ -7,7 +7,7 @@ define([
 function (angular, _, coreModule, config) {
   'use strict';
 
-  coreModule.default.service('backendSrv', function($http, alertSrv, $timeout) {
+  coreModule.default.service('backendSrv', function($http, alertSrv, $timeout, $q) {
     var self = this;
 
     this.get = function(url, params) {
@@ -91,8 +91,25 @@ function (angular, _, coreModule, config) {
       });
     };
 
+    var datasourceInFlightRequests = {};
+    var HTTP_REQUEST_ABORTED = -1;
     this.datasourceRequest = function(options) {
       options.retry = options.retry || 0;
+
+      // A requestID is provided by the datasource as a unique identifier for a
+      // particular query. If the requestID exists, the promise it is keyed to
+      // is canceled, canceling the previous datasource request if it is still
+      // in-flight.
+      var canceler;
+      if (options.requestID) {
+        if (canceler = datasourceInFlightRequests[options.requestID]) {
+          canceler.resolve();
+        }
+        canceler = $q.defer();
+        options.timeout = canceler.promise;
+        datasourceInFlightRequests[options.requestID] = canceler;
+      }
+
       var requestIsLocal = options.url.indexOf('/') === 0;
       var firstAttempt = options.retry === 0;
 
@@ -102,10 +119,21 @@ function (angular, _, coreModule, config) {
       }
 
       return $http(options).then(null, function(err) {
+        if (err.status === HTTP_REQUEST_ABORTED) {
+          // TODO: Hitting refresh before the original request returns cancels
+          // the "loading" animation on the panes, but it should continue to be
+          // visible.
+          err.statusText = "request aborted";
+          return err;
+        }
+
         // handle unauthorized for backend requests
-        if (requestIsLocal && firstAttempt  && err.status === 401) {
+        if (requestIsLocal && firstAttempt && err.status === 401) {
           return self.loginPing().then(function() {
             options.retry = 1;
+            if (canceler) {
+              canceler.resolve();
+            }
             return self.datasourceRequest(options);
           });
         }

+ 4 - 0
public/app/features/panel/metrics_panel_ctrl.ts

@@ -182,6 +182,10 @@ class MetricsPanelCtrl extends PanelCtrl {
       cacheTimeout: this.panel.cacheTimeout
     };
 
+    metricsQuery.targets.forEach(function(target) {
+      target.exprID = target.refId + metricsQuery.panelId;
+    });
+
     return datasource.query(metricsQuery);
   }
 

+ 9 - 3
public/app/plugins/datasource/prometheus/datasource.ts

@@ -21,10 +21,11 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
   this.withCredentials = instanceSettings.withCredentials;
   this.lastErrors = {};
 
-  this._request = function(method, url) {
+  this._request = function(method, url, requestID) {
     var options: any = {
       url: this.url + url,
-      method: method
+      method: method,
+      requestID: requestID,
     };
 
     if (this.basicAuth || this.withCredentials) {
@@ -57,6 +58,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
     return escapedValues.join('|');
   };
 
+  var HTTP_REQUEST_ABORTED = -1;
   // Called once per panel (graph)
   this.query = function(options) {
     var self = this;
@@ -75,6 +77,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
 
       var query: any = {};
       query.expr = templateSrv.replace(target.expr, options.scopedVars, self.interpolateQueryExpr);
+      query.requestID = target.exprID;
 
       var interval = target.interval || options.interval;
       var intervalFactor = target.intervalFactor || 1;
@@ -105,6 +108,9 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
       var result = [];
 
       _.each(allResponse, function(response, index) {
+        if (response.status === HTTP_REQUEST_ABORTED) {
+          return;
+        }
         if (response.status === 'error') {
           self.lastErrors.query = response.error;
           throw response.error;
@@ -122,7 +128,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
 
   this.performTimeSeriesQuery = function(query, start, end) {
     var url = '/api/v1/query_range?query=' + encodeURIComponent(query.expr) + '&start=' + start + '&end=' + end + '&step=' + query.step;
-    return this._request('GET', url);
+    return this._request('GET', url, query.requestID);
   };
 
   this.performSuggestQuery = function(query) {