Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add smart retries to table.mutate #17

Merged
merged 5 commits into from
Dec 13, 2017

Conversation

kolodny
Copy link
Contributor

@kolodny kolodny commented Dec 8, 2017

  • Tests and linter pass
  • Code coverage does not decrease (if any source code was changed)

A couple of things to note about this PR:

  • There's a bug where faketimers don't play nicely streams. I filed a bug on process-nextick-args which causes an issue of readable-streams, so that's the deal with the patch files. Node v4 has a nested node_modules structure while >= v6 is flat.
  • patch-package doesn't handle possible missing packages so that's why the git commands are run manually

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Dec 8, 2017
@ghost ghost assigned kolodny Dec 8, 2017
@codecov-io
Copy link

codecov-io commented Dec 8, 2017

Codecov Report

Merging #17 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master    #17   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           8      8           
  Lines         792    811   +19     
=====================================
+ Hits          792    811   +19
Impacted Files Coverage Δ
src/table.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b85679b...e4c03fa. Read the comment docs.

@kolodny kolodny force-pushed the smart-mutate-retries branch 4 times, most recently from f3e988f to c675798 Compare December 8, 2017 18:22
@kolodny
Copy link
Contributor Author

kolodny commented Dec 8, 2017

I can get coverage for unit tests back to 100% with the following patch, although I'm not sure it's the right thing to do

diff --git a/test/table.js b/test/table.js
index f348120..9173788 100644
--- a/test/table.js
+++ b/test/table.js
@@ -999,8 +999,10 @@ describe('Bigtable/Table', function() {
     describe('error', function() {
       describe('API errors', function() {
         var error = new Error('err');
+        var setTimeoutStub;

         beforeEach(function() {
+          setTimeoutStub = sinon.stub(global, 'setTimeout').callsFake(setImmediate);
           table.requestStream = function() {
             var stream = new Stream({
               objectMode: true,
@@ -1015,6 +1017,10 @@ describe('Bigtable/Table', function() {
           };
         });

+        afterEach(function() {
+          setTimeoutStub.restore();
+        });
+
         it('should return the error to the callback', function(done) {
           table.maxRetries = 0;
           table.mutate(entries, function(err) {
@@ -1022,6 +1028,17 @@ describe('Bigtable/Table', function() {
             done();
           });
         });
+
+        it('attempts to retry the mutation', function(done) {
+          table.maxRetries = 1;
+          table.mutate(entries, function(err) {
+            assert.strictEqual(err, error);
+            assert.strictEqual(setTimeoutStub.callCount, 1);
+            assert(setTimeoutStub.getCall(0).args[1] > 2000);
+            assert(setTimeoutStub.getCall(0).args[1] < 3000);
+            done();
+          });
+        });
       });

       describe('mutation errors', function() {

@stephenplusplus
Copy link
Contributor

This PR introduces an "integration" test command, but we already have system tests that are supposed to be the same thing: "Does our code work when integrated with the system?" (Using the name "system tests" was a decision that involved more languages than just us). I also see a reference to "acceptance" testing. I think we should keep everything under one roof, "system tests", since that's our pattern across all of the API libraries. It should only be one command for a contributor/maintainer to determine if their changes introduce any issues with the upstream API, and that's historically been "npm run system-test".

Regarding the patching, I would prefer to wait for calvinmetcalf/process-nextick-args#10 to be merged and released.

package.json Outdated
@@ -78,6 +81,7 @@
"eslint-config-prettier": "^2.6.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-prettier": "^2.3.1",
"grpc": "^1.7.2",

This comment was marked as spam.

This comment was marked as spam.

src/table.js Outdated
if (pendingEntryIndices.size !== 0 && requestsMade <= maxRetries) {
setTimeout(
makeNextRequestBatch,
retryRequest.getNextRetryDelay(requestsMade)

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

@kolodny
Copy link
Contributor Author

kolodny commented Dec 11, 2017

Regarding patching, after calvinmetcalf/process-nextick-args#10 is merged (it already was), nodejs/readable-stream#317 needs to be merged, publish a release (note this module is basically part of node core), and then wait for through2 to publish a release with that updated readable-stream dependency. I figured this was a good enough workaround in the meantime

@stephenplusplus
Copy link
Contributor

I see, thanks for the rundown. Yeah, I suppose the patching will have to do for now.

kolodny added a commit to kolodny/google-cloud-node that referenced this pull request Dec 12, 2017
This is to enable not needing to call setTimeout when making a followup request. See googleapis/nodejs-bigtable#17 (comment) for more details
stephenplusplus pushed a commit to googleapis/google-cloud-node that referenced this pull request Dec 12, 2017
This is to enable not needing to call setTimeout when making a followup request. See googleapis/nodejs-bigtable#17 (comment) for more details
@stephenplusplus
Copy link
Contributor

stephenplusplus commented Dec 12, 2017

Thanks for splitting that out. I believe there might be some work for the code coverage still.

https://codecov.io/gh/googleapis/nodejs-bigtable/pull/17/src/src/table.js?before=src/table.js#L942

@kolodny
Copy link
Contributor Author

kolodny commented Dec 12, 2017

I can add the following test to the unit tests to get it back to 100%. Is that something you'd be ok with?

    describe('retries', function() {
      var fakeStatuses = [
        [
          {
            status: {
              code: 0,
            },
          },
          {
            status: {
              code: 4,
            },
          },
        ],
        [
          {
            status: {
              code: 0,
            },
          },

        ]
      ];

      beforeEach(function() {
        FakeGrpcService.decorateStatus_ = function(status) {
          return {};
        };
        table.requestStream = function() {
          var stream = new Stream({
            objectMode: true,
          });

          setImmediate(function() {
            stream.emit('request');
            stream.end({entries: fakeStatuses.shift()});
          });

          return stream;
        };
      });

      it('should succeed after a retry', function(done) {
        table.maxRetries = 1;
        table.mutate(entries, done);
      });
    });
  });

@stephenplusplus
Copy link
Contributor

That test looks good to me. I also think we should have another unit test to confirm only the correct subset of entries from the original request is sent when a retry is made, effectively testing the new pendinEntryIndices, entryToIndex holders.

@kolodny
Copy link
Contributor Author

kolodny commented Dec 13, 2017

Done, coverage appears to be back to 100%

@ghost ghost assigned stephenplusplus Dec 13, 2017
@googlebot
Copy link

So there's good news and bad news.

👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there.

😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request.

Note to project maintainer: This is a terminal state, meaning the cla/google commit status will not change from this State. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Dec 13, 2017
@stephenplusplus
Copy link
Contributor

I made some small changes, just to conventionalize the code (stream error handling first, all caps file-wide const name, etc). Tests still pass, but please make sure these changes look harmless to you as well.

@kolodny
Copy link
Contributor Author

kolodny commented Dec 13, 2017

Look good to me!

@stephenplusplus stephenplusplus merged commit e4770e6 into googleapis:master Dec 13, 2017
@stephenplusplus stephenplusplus mentioned this pull request Dec 28, 2017
alexander-fenster pushed a commit to googleapis/nodejs-common-grpc that referenced this pull request Jan 8, 2018
This is to enable not needing to call setTimeout when making a followup request. See googleapis/nodejs-bigtable#17 (comment) for more details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: no This human has *not* signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants