You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2015/10/20 21:25:04 UTC

fauxton commit: updated refs/heads/master to 852d6ae

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 42b9fa406 -> 852d6ae59


Improve db page error handling

This PR fixes an old bug with the databases page where if one
database query fails, the remaining responses that haven't been
returned don't get populated and the database table has a lot
of incomplete rows.

Now the individual failed database rows don't affect the others and
show a "This database failed to load" message to make it clear to
the user.

The actions.js refactor code was needed due to the following.
FauxtonAPI.when() behaves in an unexpected way: when passed an
array of promises it fires the .always() in two conditions:
1. When all promises are resolved, or,
2. When ONE fails

What was happening was that when a db request failed, it didn't
fire any of the remainder requests, which is why the table would
appear partly empty.

Closes COUCHDB-2243


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/852d6ae5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/852d6ae5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/852d6ae5

Branch: refs/heads/master
Commit: 852d6ae59b294ccc7dbbca3304ec13c479bcd9fd
Parents: 42b9fa4
Author: Ben Keen <be...@gmail.com>
Authored: Tue Sep 29 10:14:50 2015 -0700
Committer: Ben Keen <be...@gmail.com>
Committed: Tue Oct 20 10:55:51 2015 -0700

----------------------------------------------------------------------
 app/addons/databases/actions.js                 | 30 +++++++++++++-----
 app/addons/databases/assets/less/databases.less |  5 +++
 app/addons/databases/components.react.jsx       | 15 +++++++++
 app/addons/databases/resources.js               |  6 ++++
 .../databases/tests/componentsSpec.react.jsx    | 32 ++++++++++++++++++++
 5 files changed, 81 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/actions.js b/app/addons/databases/actions.js
index aa814e4..423c62a 100644
--- a/app/addons/databases/actions.js
+++ b/app/addons/databases/actions.js
@@ -26,20 +26,36 @@ function (app, FauxtonAPI, Stores, ActionTypes, Resources) {
 
       this.setStartLoading();
       FauxtonAPI.when(databases.fetch({ cache: false })).then(function () {
-        FauxtonAPI.when(databases.paginated(page, perPage).map(function (database) {
-          return database.status.fetchOnce();
-        })).always(function () {
-          //make this always so that even if a user is not allowed access to a database
-          //they will still see a list of all databases
+
+        // if there are no databases, publish the init message anyway
+        if (!databases.paginated(page, perPage).length) {
           FauxtonAPI.dispatch({
             type: ActionTypes.DATABASES_INIT,
             options: {
-              collection: databases.paginated(page, perPage),
+              collection: [],
               backboneCollection: databases,
               page: page
             }
           });
-        }.bind(this));
+        }
+
+        var numComplete = 0;
+        _.each(databases.paginated(page, perPage), function (db) {
+          db.status.fetchOnce().always(function () {
+            numComplete++;
+            if (numComplete < databases.paginated(page, perPage).length) {
+              return;
+            }
+            FauxtonAPI.dispatch({
+              type: ActionTypes.DATABASES_INIT,
+              options: {
+                collection: databases.paginated(page, perPage),
+                backboneCollection: databases,
+                page: page
+              }
+            });
+          });
+        });
       }.bind(this));
     },
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/assets/less/databases.less
----------------------------------------------------------------------
diff --git a/app/addons/databases/assets/less/databases.less b/app/addons/databases/assets/less/databases.less
index 652530b..e21b8ef 100644
--- a/app/addons/databases/assets/less/databases.less
+++ b/app/addons/databases/assets/less/databases.less
@@ -62,3 +62,8 @@
 #database-pagination {
   float: right;
 }
+
+.database-load-fail {
+  color: #999999;
+  height: 49px;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/databases/components.react.jsx b/app/addons/databases/components.react.jsx
index c3e8e7f..998c805 100644
--- a/app/addons/databases/components.react.jsx
+++ b/app/addons/databases/components.react.jsx
@@ -107,6 +107,10 @@ define([
 
   var DatabaseRow = React.createClass({
 
+    propTypes: {
+      row: React.PropTypes.object
+    },
+
     renderGraveyard: function (row) {
       if (row.status.isGraveYard()) {
         return (
@@ -127,8 +131,19 @@ define([
     render: function () {
       var row = this.props.row;
       var name = row.get("name");
+
+      // if the row status failed to load, inform the user
+      if (!row.status.loadSuccess) {
+        return (
+          <tr>
+            <td>{name}</td>
+            <td colSpan="4" className="database-load-fail">This database failed to load.</td>
+          </tr>
+        );
+      }
       var encoded = app.utils.safeURLName(name);
       var size = Helpers.formatSize(row.status.dataSize());
+
       return (
         <tr>
           <td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index 5034c84..577f3f4 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -123,6 +123,7 @@ function (app, FauxtonAPI, Documents) {
 
     initialize: function (options) {
       this.database = options.database;
+      this.loadSuccess = false;
     },
 
     numDocs: function () {
@@ -160,6 +161,11 @@ function (app, FauxtonAPI, Documents) {
       }
     },
 
+    parse: function (resp) {
+      this.loadSuccess = true;
+      return resp;
+    },
+
     // a sure-fire way to know when the DB size info is actually available; dataSize() may return 0 before or after
     // the data has been loaded
     hasDataSize: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/tests/componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/componentsSpec.react.jsx b/app/addons/databases/tests/componentsSpec.react.jsx
index 099ab91..2669b46 100644
--- a/app/addons/databases/tests/componentsSpec.react.jsx
+++ b/app/addons/databases/tests/componentsSpec.react.jsx
@@ -40,6 +40,7 @@ define([
               }
             },
             "status": {
+              "loadSuccess": true,
               "dataSize": function () {
                 return 2 * 1024 * 1024;
               },
@@ -63,6 +64,7 @@ define([
               }
             },
             "status": {
+              "loadSuccess": true,
               "dataSize": function () {
                 return 1024;
               },
@@ -270,6 +272,7 @@ define([
 
       var row = new Backbone.Model({ name: 'db name' });
       row.status = {
+        loadSuccess: true,
         dataSize: function () { return 0; },
         numDocs: function () { return 0; },
         updateSeq: function () { return 0; },
@@ -287,6 +290,35 @@ define([
       Stores.databasesStore.reset();
     });
 
+    it('shows error message if row marked as failed to load', function () {
+      var row = new Backbone.Model({ name: 'db name' });
+      row.status = {
+        loadSuccess: false,
+        dataSize: function () { return 0; },
+        numDocs: function () { return 0; },
+        updateSeq: function () { return 0; },
+        isGraveYard: function () { return false; }
+      };
+
+      var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container);
+      assert.equal($(databaseRow.getDOMNode()).find('.database-load-fail').length, 1);
+    });
+
+    it('shows no error if row marked as loaded', function () {
+      var row = new Backbone.Model({ name: 'db name' });
+      row.status = {
+        loadSuccess: true,
+        dataSize: function () { return 0; },
+        numDocs: function () { return 0; },
+        updateSeq: function () { return 0; },
+        isGraveYard: function () { return false; }
+      };
+
+      var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container);
+
+      assert.equal($(databaseRow.getDOMNode()).find('.database-load-fail').length, 0);
+    });
+
   });
 
 });