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

(#6730) - fix single-sided checkpointing #6734

Merged
merged 32 commits into from
Nov 3, 2017

Conversation

alxndrsn
Copy link
Member

@alxndrsn alxndrsn commented Sep 5, 2017

No description provided.

Copy link
Member

@willholley willholley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly looking good to me - just a few things that could be improved in the tests, I think. Nicely done!

@@ -392,6 +392,9 @@ function replicate(src, target, opts, returnValue, result) {
return;
}
return checkpointer.getCheckpoint().then(function (checkpoint) {
if (typeof result.initial_checkpoint === 'undefined') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not keen on changing the result to support the tests here. I think you can test by intercepting the _changes call as in https://github.com/pouchdb/pouchdb/blob/master/tests/integration/test.replication.js#L2400

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I'll look into the suggested approach.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change and it works, although a little weird as changes() is called twice for each call to replicate(), first with the initial checkpoint value, and then with the final checkpoint value.

@@ -133,9 +133,21 @@ var comparisons = {

Checkpointer.prototype.getCheckpoint = function () {
var self = this;

if (self.opts && self.opts.writeSourceCheckpoint && !self.opts.writeTargetCheckpoint) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this should be combined with self.readOnlySource - it seems like we have two properties to express the same thing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I read it, there are four different options:

source \ target on off
on default previously broken
off previously broken no checkpointing

How would you recommend combining?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.readOnlyCheckpoint is set when we detect that we don't have write permissions on the source. It seems like, once set, we'd want the behaviour to be the same as if opts.writeSourceCheckpoint is false. Looking at it again, this line probably doesn't change, but we have 2 similar-looking flags adjusting checkpoint behaviour that look like they should be combined in general

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's that simple, though. One flag is a request for behaviour, and the other is a reaction to discovered properties of a DB. E.g.

Checkpointer.prototype.updateSource = function (checkpoint, session) {
  if (this.opts.writeSourceCheckpoint) {
    var self = this;
    if (this.readOnlySource) {
      return Promise.resolve(true);
    }

Perhaps the auto-detection could be removed and an error thrown if the source is discovered to be read only when the user has requested checkpointing on both sides? OTOH the current behaviour is quite helpful...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@willholley PR for combining the two at #6738

.on('complete', function (result) {
result.docs_read.should.equal(1);
result.docs_written.should.equal(1);
result.initial_checkpoint.should.equal(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as above, suggest capturing the since parameter sent to changes() rather than changing the schema of result

.catch(done);
});

it('Test replicate on source only resumes OK', function (done) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps 'Test replication resumes when checkpointing on source only' is more descriptive

result.initial_checkpoint.should.equal(0);
done();
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove whitespace

result.initial_checkpoint.should.equal(1);
done();
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove whitespace

.catch(done);
});

it('Test replicate on target only resumes OK', function (done) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps 'Test replication resumes when checkpointing on target only' is more descriptive


var replicateOpts = { checkpoint: 'target' };

db.bulkDocs({ docs: docs.slice(0, 1) })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of duplication here with the previous tests. Consider refactoring so that the test body can be reused, whilst injecting different replicateOpts

@alxndrsn
Copy link
Member Author

alxndrsn commented Sep 5, 2017

@willholley thanks for the feedback 🙂

@@ -2643,15 +2759,13 @@ adapters.forEach(function (adapters) {
var targetPut = target.put;
target.put = putter;

var changes = source.changes;
source.changes = function (opts) {
interceptChanges(source, function(opts) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Travis complains about this one, function(opts) vs. function (opts)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks :¬)

@alxndrsn
Copy link
Member Author

alxndrsn commented Sep 6, 2017

Ready for review again :¬)

@alxndrsn
Copy link
Member Author

alxndrsn commented Sep 6, 2017

Test failures for https://travis-ci.org/pouchdb/pouchdb/builds/272428063:

1. CLIENT=selenium:firefox:47.0.2 COMMAND=test

https://travis-ci.org/pouchdb/pouchdb/jobs/272428078:

No output has been received in the last 10m0s, this potentially indicates a stalled build or something wrong with the build itself.

2. CLIENT=node SERVER=couchdb-master COMMAND=test

https://travis-ci.org/pouchdb/pouchdb/jobs/272428087

  1) suite2 test.replication.js-http-http Test replication resumes when checkpointing is enabled:
     expected '1-g1AAAAIZeJyV0FEKgjAYwPGvDKqnjlAniM3NOZ_yJrXtm5jYeuq5blI3qZvUTWzqg0gEyuAbbPx_g5UAsMgDhJU7o6UpDeMt8YuW_mKqQK-rqiryQMHJH8wNCxNBCcLy4tBmR2fxb6w3fupdrxdExMTQYX1a9_teHybWSM2H9Ye6v_bfV4ohk4N6N_MTbn7zxL0zGJdWxmqE8WiNZ2cozamyYoTxao13ZyCjaFQ2wvi0RvMfk8aILNNRyH-r4gtSH43J' to equal 1

Looks like seq numbers on the remote DB are strings rather than integers. Can we just do something like parseInt(string.substring(0, string.indexOf('-'))) in the test?

3. CLIENT=selenium:firefox:47.0.2 SERVER=couchdb-master COMMAND=test

https://travis-ci.org/pouchdb/pouchdb/jobs/272428088

I don't really understand what's going wrong with this build.

4. COMMAND=report-coverage COVERAGE=1

https://travis-ci.org/pouchdb/pouchdb/jobs/272428095

ERROR: Coverage for lines (99.98%) does not meet global threshold (100%)

Any advice on getting these issues fixed gratefully received 🙂

@willholley
Copy link
Member

Looks like seq numbers on the remote DB are strings rather than integers.
This is correct - sequence values are not guaranteed to be incremental and so cannot be compared. Is the issue that the tests assume specific values for the checkpoints? If so, you'd need to just capture the expected checkpoint value and ensure it's passed to changes verbatim.

For the firefox tests, I'll restart them - it's probably just saucelabs being flakey.

The code coverage errors indicate that some of the new code paths aren't being exercised by the tests. This is worth looking at and, ideally, adding covering tests.

@afinne
Copy link

afinne commented Sep 18, 2017

I'm not sure if this is 100% relevant, but it seems like sequence numbers can't be trusted to be ordered on CouchDB: https://stackoverflow.com/questions/44447505/sequence-number-bug-in-couchdb-2-or-is-there-another-way-to-compare-sequence-num

Can we think of another way to check whether we get the desired since?

.then(function () {
PouchDB.replicate(db, remote)
.on('error', done)
.on('complete', function (result) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the result contain anything that could be useful, like seq_written or something?

@alxndrsn
Copy link
Member Author

alxndrsn commented Nov 1, 2017

I think I might have the tests passing. Just waiting for a full batch to complete on Travis…

@alxndrsn
Copy link
Member Author

alxndrsn commented Nov 2, 2017

The build is passing and this is now ready for review. Happy to rebase and squash beforehand if that's helpful.

Copy link
Member

@daleharvey daleharvey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome job, huge 👍 sorry for not being around more to help but good job getting this implemented, tested and all passing, will try to be a bit quicker helping out with follow ups :)

@daleharvey daleharvey merged commit c79f1c7 into pouchdb:master Nov 3, 2017
@alxndrsn
Copy link
Member Author

alxndrsn commented Nov 3, 2017

Thanks! And extra thanks for including my unedited commit message log ;¬)

@afinne
Copy link

afinne commented Nov 3, 2017

<3

@alxndrsn alxndrsn deleted the checkpoint branch November 3, 2017 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants