Skip to content

Conversation

jsflax
Copy link
Contributor

@jsflax jsflax commented Oct 26, 2018

See https://docs.google.com/document/d/1lvd02JFNI9Aa7Zely3xMJEct_N-HMn84tKIIhMq7Zes/ for more detailed information on the agreed design.

  • Add additional logic for creating v2 rules for MongoDB. Make setting rules easier, which is handy for integration tests.

@coveralls
Copy link

coveralls commented Oct 26, 2018

Coverage Status

Coverage increased (+0.09%) to 64.072% when pulling ef35d6a on jsflax:STITCH-1970 into 98f2641 on mongodb:master.

@jsflax jsflax requested review from edaniels and adamchel October 26, 2018 01:12
Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

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

Generally LGTM. Just a few source changes to make and some test recommendations. Nice job!

fun testUpdateDescriptionDiff() {
val originalJson = """
{
"shop_name": "nkd pizza",
Copy link
Contributor

Choose a reason for hiding this comment

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

where did you get this from haha

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's our local pizza shop in Dublin– I'll change it to not use real names 🍕

}

@Test
fun testUpdateDescriptionToUpdateDoc() {
Copy link
Contributor

Choose a reason for hiding this comment

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

[request] Can you make a more involved test that hits more than just 1 field per updated and removed? I would add some nesting as well. It's nice to have a test where we have a literal string saying exactly what the diff should be.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

return newDocument
}

fun testUpdatedDocumentMatchesExpectation(
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like you can pull this out to a function outside of here so it can be reused. It would make it easier to see what this test is doing if it was just the tests were performing as succinctly as possible.

collection.aggregate(
listOf(
BsonDocument(
"\$project",
Copy link
Contributor

Choose a reason for hiding this comment

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

[q] Why is this projecting instead of just doing a find?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The projection was to eliminate the id fields in the subdocuments.

expectedDocumentAfterUpdate: BsonDocument
) {
// create an update description via diff'ing the two documents.
val updateDescription = diff(withoutId(originalDocument), withoutId(expectedDocumentAfterUpdate))
Copy link
Contributor

Choose a reason for hiding this comment

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

[test] It would be better to write an actual update and not use expectedDocumentAfterUpdate. That will prove that we can update something with whatever operators and still produce an update description.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

event = changeEventForLocalUpdate(
namespace,
documentId,
ChangeEvent.UpdateDescription.diff(remoteEvent.getFullDocument(), document),
Copy link
Contributor

Choose a reason for hiding this comment

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

[q] I think we can still use documentAfterUpdate here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, we should be able to.


if (beforeResult != null) {
emitEvent(documentId,
changeEventForLocalUpdate(
Copy link
Contributor

Choose a reason for hiding this comment

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

[minor] When we replace from remote, it is really a replacement so you should be able to keep this code the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

/**
* Find the diff between two documents.
*
* NOTE: This does not do a full diff on [BsonArray]. If there is
Copy link
Contributor

Choose a reason for hiding this comment

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

[q] Why [] for [BsonArray]?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I copied this over from the kotlin PoC code. Will replace with {@link BsonArray}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

* @return a description of the updated fields and removed keys between
* the documents
*/
private static UpdateDescription diff(final BsonDocument thisDocument,
Copy link
Contributor

Choose a reason for hiding this comment

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

[test] I would make several more unit tests for this for various edge cases. Empty doc vs non empty doc, rray vs non array field, Deeply nested docs, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These were covered in the main unit test, but I should break it up into multiple tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Broken up in the same test, but with numbering.

* @return a description of the updated fields and removed keys between
* the documents
*/
private static UpdateDescription diff(final BsonDocument thisDocument,
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of this and that, how about before and after?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could do– in the PoC, it was more general use case diffing. Since this is attached to UpdateDesc, I agree.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@adamchel adamchel left a comment

Choose a reason for hiding this comment

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

looking pretty good. had some nits and q's but I think this will be LGTM once you address Eric's comments

// because they require more permissive Stitch rules.
final BsonDocument update,
final UpdateDescription update,
final BsonDocument document,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit/not your code] this argument should be renamed to fullDocumentAfterUpdate to make it clear that's what it is

} else {
// ii. Otherwise, replace the local document with the resolved document locally, mark that
// there are pending writes for this document, and emit a REPLACE change event.
// there are pending writes for this document, and emit an UPDATE change event, or a
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] any changes you make to the comments with the the lettering/numbering should also be made to the spec document. we should try to keep the spec in sync with what the code is actually doing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted.

logicalT,
atVersion,
event);
event = changeEventForLocalUpdate(
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] I guess the proper name for this method would now be updateOrUpsertOneFromResolution

ctx.namespace,
ctx.testDocumentId,
ctx.updateDocument,
ChangeEvent.UpdateDescription(BsonDocument("count", BsonInt32(2)), listOf()),
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] you reuse this exact update in a lot of places so maybe just set a testUpdateDescription constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could, though for the purpose of test code, I think it's better to write in line. Though it's reused, it's fairly arbitrary, and throughout the test, the count can increase.

))
ctx.verifyConflictHandlerCalledForActiveDoc(1, expectedLocalEvent,
ChangeEvent.changeEventForLocalUpdate(ctx.namespace, ctx.testDocumentId, ctx.updateDocument, ctx.testDocument, false))
ChangeEvent.changeEventForLocalUpdate(ctx.namespace, ctx.testDocumentId, null, ctx.testDocument, false))
Copy link
Contributor

Choose a reason for hiding this comment

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

[q] what does a change event for a local update with a null UpdateDescription mean? is it a noop update? seems a little odd that this is something our code is producing

Copy link
Contributor

Choose a reason for hiding this comment

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

ah I see now that this is produced by our mock, but I think we should just have the mock produce a real update, because a local update change event with no actual things being updated seems like something that shouldn't actually exist

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think this is due to coalescence. I can add a note here that that is what this is testing.

ChangeEvent.changeEventForLocalDelete(ctx.namespace, ctx.testDocumentId, true),
ChangeEvent.changeEventForLocalUpdate(
ctx.namespace, ctx.testDocumentId, ctx.updateDocument, ctx.testDocument, false
ctx.namespace, ctx.testDocumentId, null, ctx.testDocument, false
Copy link
Contributor

Choose a reason for hiding this comment

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

[ditto q] noop update

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above

override fun queueConsumableRemoteUpdateEvent() {
`when`(dataSynchronizer.getEventsForNamespace(any())).thenReturn(
mapOf(testDocument to ChangeEvent.changeEventForLocalUpdate(namespace, testDocumentId, updateDocument, testDocument, false)),
mapOf(testDocument to ChangeEvent.changeEventForLocalUpdate(namespace, testDocumentId, null, testDocument, false)),
Copy link
Contributor

Choose a reason for hiding this comment

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

[ditto q] noop update

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

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

LGTM

@jsflax jsflax merged commit 1679a78 into mongodb:master Oct 28, 2018
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.

4 participants