Эх сурвалжийг харах

HUE-3228 [dashboard] Offer to cancel all non finished queries

Romain Rigaux 8 жил өмнө
parent
commit
a5b282d

+ 98 - 72
apps/search/src/search/static/search/js/search.ko.js

@@ -1526,9 +1526,9 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
   };
   self.isRetrievingResults = ko.observable(false);
   self.hasRetrievedResults = ko.observable(true);
-  self.asyncSearchesCounter = ko.observable(0);
+  self.asyncSearchesCounter = ko.observableArray([]);
   self.asyncSearchesCounter.subscribe(function(newVal) {
-	if (newVal == 0) {
+	if (newVal.length == 0) {
 	  self.isRetrievingResults(false);
 	  self.hasRetrievedResults(true);
 	  $('.btn-loading').button('reset');
@@ -1629,83 +1629,109 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
     self.search();
   };
 
-  self.checkStatus = function (facet) { // common?
-      $.post("/notebook/api/check_status", {
-        notebook: ko.mapping.toJSON({type: facet.queryResult().type()}),
-        snippet: ko.mapping.toJSON(facet.queryResult().getContext())
-      }, function (data) {
-        if (facet.queryResult().status() == 'canceled') {
-          // Query was canceled in the meantime, do nothing
-        } else {
+  self.checkStatus = function (facet) { // TODO: have a common generic with Notebook
+    $.post("/notebook/api/check_status", {
+      notebook: ko.mapping.toJSON({type: facet.queryResult().type()}),
+      snippet: ko.mapping.toJSON(facet.queryResult().getContext())
+    }, function (data) {
+      if (facet.queryResult().status() == 'canceled') {
+        // Query was canceled in the meantime, do nothing
+      } else {
 
-          if (data.status == 0) {
-        	  facet.queryResult().status(data.query_status.status);
+        if (data.status == 0) {
+      	  facet.queryResult().status(data.query_status.status);
 
-            if (facet.queryResult().status() == 'running' || facet.queryResult().status() == 'starting') {
-              // if (! notebook.unloaded()) { self.checkStatusTimeout = setTimeout(self.checkStatus, 1000); };
-              setTimeout(function() { self.checkStatus(facet); }, 1000);
-            }
-            else if (facet.queryResult().status() == 'available') {
-              self.fetchResult(facet);
-              facet.queryResult().progress(100);
-            }
-            else if (facet.queryResult().status() == 'success') {
-              facet.queryResult().progress(99);
-            }
-          } else if (data.status == -3) {
-        	  facet.queryResult().status('expired');
-          } else {
-            //self._ajaxError(data); // common?
-        	$(document).trigger("error", data.message);
+          if (facet.queryResult().status() == 'running' || facet.queryResult().status() == 'starting') {
+            // if (! notebook.unloaded()) { self.checkStatusTimeout = setTimeout(self.checkStatus, 1000); };
+            setTimeout(function() { self.checkStatus(facet); }, 1000);
+          }
+          else if (facet.queryResult().status() == 'available') {
+            self.fetchResult(facet);
+            facet.queryResult().progress(100);
           }
+          else if (facet.queryResult().status() == 'success') {
+            facet.queryResult().progress(99);
+          }
+        } else if (data.status == -3) {
+      	  facet.queryResult().status('expired');
+        } else {
+          //self._ajaxError(data); // common?
+      	$(document).trigger("error", data.message);
+        }
+      }
+    }).fail(function (xhr, textStatus, errorThrown) {
+      $(document).trigger("error", xhr.responseText || textStatus);
+      facet.queryResult().status('failed');
+    });
+  };
+
+  self.isCanceling = ko.observable(false);
+
+  self.cancelAsync = function (facet) { // TODO: have a common generic with Notebook
+    self.isCanceling(true);
+    logGA('cancel');
+
+    multiQs = $.map(self.asyncSearchesCounter(), function(facet) {
+      $.post("/notebook/api/cancel_statement", {
+          notebook: ko.mapping.toJSON({type: facet.queryResult().type()}),
+          snippet: ko.mapping.toJSON(facet.queryResult().getContext())
+      }, function (data) {
+        if (data.status == 0) {
+          facet.queryResult().status('canceled');
+          self.asyncSearchesCounter.remove(facet);
+        } else {
+          //self._ajaxError(data);
         }
       }).fail(function (xhr, textStatus, errorThrown) {
-        $(document).trigger("error", xhr.responseText || textStatus);
-        facet.queryResult().status('failed');
+         $(document).trigger("error", xhr.responseText);
+         self.queryResult().status('failed');
+      }).always(function (){
+       // self.isCanceling(false);
       });
-    };
+    });
+  };
+
+  self.fetchResult = function(facet) {
+    $.post("/search/search", {
+        collection: ko.mapping.toJSON(self.collection),
+        query: ko.mapping.toJSON(self.query),
+        facet: ko.mapping.toJSON(facet),
+        fetch_result: true
+    }, function (data) {
+      if (facet.type) {
+        $.each(data.normalized_facets, function (index, facet) {
+          self._make_result_facet(facet);
+        });
+      } else {
+        self._make_grid_result(data);
+      }
+
+      self.asyncSearchesCounter.remove(facet);
 
-   self.fetchResult = function(facet) {
-     $.post("/search/search", {
-         collection: ko.mapping.toJSON(self.collection),
-         query: ko.mapping.toJSON(self.query),
-         facet: ko.mapping.toJSON(facet),
-         fetch_result: true
-     }, function (data) {
-       if (facet.type) {
-         $.each(data.normalized_facets, function (index, facet) {
-           self._make_result_facet(facet);
-         });
-       } else {
-         self._make_grid_result(data);
-       }
-
-       self.asyncSearchesCounter(self.asyncSearchesCounter() - 1);
-
-       //if (facet.queryResult().result['handle'].has_result_set()) {
-       //  self.fetchResultSize(facet);
-       //}
-     });
-   }
-
-   self.fetchResultSize = function(facet) {
-	  $.post("/notebook/api/fetch_result_size", {
-        notebook: ko.mapping.toJSON({type: facet.queryResult().type()}),
-        snippet: ko.mapping.toJSON(facet.queryResult)
-	  }, function (data) {
-	    if (data.status == 0) {
-	      if (data.result.rows != null) {
-	    	facet.response().response.numFound(data.result.rows);
-	      }
-	    } else if (data.status == 5) {
-	      // No supported yet for this snippet
-	    } else {
-	      $(document).trigger("error", data.message);
+      //if (facet.queryResult().result['handle'].has_result_set()) {
+      //  self.fetchResultSize(facet);
+      //}
+    });
+  };
+
+  self.fetchResultSize = function(facet) {
+	$.post("/notebook/api/fetch_result_size", {
+      notebook: ko.mapping.toJSON({type: facet.queryResult().type()}),
+      snippet: ko.mapping.toJSON(facet.queryResult)
+	}, function (data) {
+	  if (data.status == 0) {
+	    if (data.result.rows != null) {
+	  	facet.response().response.numFound(data.result.rows);
 	    }
-	  }).fail(function (xhr, textStatus, errorThrown) {
-	    $(document).trigger("error", xhr.responseText);
-	  });
-	};
+	  } else if (data.status == 5) {
+	    // No supported yet for this snippet
+	  } else {
+	    $(document).trigger("error", data.message);
+	  }
+	}).fail(function (xhr, textStatus, errorThrown) {
+	  $(document).trigger("error", xhr.responseText);
+	});
+  };
 
 
   self.search = function (callback) {   // self.searchAsync == self.collection.async()
@@ -1772,7 +1798,7 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
           	self.checkStatus(facet);
         });
       });
-      self.asyncSearchesCounter(multiQs.length + 1);
+      self.asyncSearchesCounter([self.collection].concat(self.collection.facets()));
     }
 
     $.each(self.fieldAnalyses(), function (index, analyse) { // Invalidate stats analysis

+ 6 - 3
apps/search/src/search/templates/common_search.mako

@@ -137,6 +137,9 @@ from desktop.views import commonheader, commonfooter, _ko
       <button type="submit" id="search-btn" class="btn btn-inverse" style="margin-left:10px; margin-right:10px">
         <i class="fa fa-search" data-bind="visible: ! isRetrievingResults()"></i>
         <!--[if !IE]> --><i class="fa fa-spinner fa-spin" data-bind="visible: isRetrievingResults()"></i><!-- <![endif]-->
+        <!-- ko if: $root.collection.async() -->
+          <i class="fa fa-stop" clas="red" data-bind="click: cancelAsync, visible: isRetrievingResults()"></i>
+        <!-- /ko -->
         <!--[if IE]><img src="${ static('desktop/art/spinner-inverted.gif') }" data-bind="visible: isRetrievingResults()"/><![endif]-->
       </button>
 
@@ -1467,11 +1470,11 @@ ${ dashboard.layout_skeleton() }
             <!-- /ko -->
           </a>
         </div>
-        
+
         <!-- ko if: $root.collection.engine() != 'solr' -->
-          <div data-bind="component: { name: 'downloadSnippetResults', params: { snippet: $data.queryResult(), notebook: {getContext: function() { return {type: $data.queryResult().type(), id: 1}; }} } }" style="display:inline-block;"></div>        
+          <div data-bind="component: { name: 'downloadSnippetResults', params: { snippet: $data.queryResult(), notebook: {getContext: function() { return {type: $data.queryResult().type(), id: 1}; }} } }" style="display:inline-block;"></div>
         <!-- /ko -->
-        
+
         <!-- ko if: $root.collection.engine() == 'solr' -->
         <form method="POST" action="${ url('search:download') }" style="display:inline">
           ${ csrf_token(request) | n,unicode }