Skip to content

Conversation

jsflax
Copy link
Contributor

@jsflax jsflax commented Oct 9, 2018

Notes: I've handled the possible null case here in what I felt was best for usability, however, it may need to be agreed upon.

Description:
Configuration for sync happens at collection.sync().configure() where configure is: configure(, , ). See spec for more info.

This configure should be the signal to the data synchronizer to start synchronzing if it hasn't already. Subsequent configurations just update handlers and listeners. The signal is to prevent an error condition where we were to sync but do not know how to handle conflcits since a handler has not been set up yet. Most app code will always be calling configure first.

@jsflax jsflax requested a review from edaniels October 9, 2018 20:46
@jsflax
Copy link
Contributor Author

jsflax commented Oct 9, 2018

Seems like some formatting got included in this PR. I can remove it, or we can keep it if we want.

@jsflax jsflax removed the request for review from edaniels October 9, 2018 21:08
@jsflax jsflax requested review from edaniels and adamchel October 10, 2018 12:06
@jsflax
Copy link
Contributor Author

jsflax commented Oct 10, 2018

Evg is being flakey. Otherwise this is ready for review. The driveby tab changes are valid, however, I can move them to another PR if we feel that it's here inappropriately.

"mongodb",
"mongodb1",
ServiceConfigs.Mongo(getMongoDbUri()))
app.second,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's remove the reformats to avoid conflicts

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.

Done with first pass

);
this.triggerListeningToNamespace(namespace);

if (!this.isConfigured) {
Copy link
Contributor

Choose a reason for hiding this comment

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

[minor] We should grab the lock first before checking configured otherwise this can be a torn read or write.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

(remoteEvent.getFullDocument() == null && resolvedDocument == null)
|| (remoteEvent.getFullDocument() != null
&& transformedRemoteEvent.getFullDocument().equals(resolvedDocument));
&& remoteEvent.getFullDocument().equals(resolvedDocument));
Copy link
Contributor

Choose a reason for hiding this comment

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

[major] This is reintroducing a bug. Please undo any reformats or changes unrelated to this ticket in this PR.

val docToInsert = Document("hello", "world")
testSync.insertOneAndSync(docToInsert)

assertFalse((mongoClient as RemoteMongoClientImpl).dataSynchronizer.isRunning)
Copy link
Contributor

Choose a reason for hiding this comment

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

[test] Instead of needing an isRunning as var and exposed, you can instead just add a semaphore to watch a change stream come in.

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 true if configured, false if not
*/
boolean isConfigured() {
Copy link
Contributor

Choose a reason for hiding this comment

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

[minor] must be synchronized

fun testConfigure() {
val testSync = getTestSync()

(mongoClient as RemoteMongoClientImpl).dataSynchronizer.enableSyncThread()
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not quite positive, but it seems like the expose and implementation of .enableSyncThread() is not strictly necessary. You can use manual sync passes if you need to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright. This makes more sense. It will slightly change the tests, but yes, if we address your comment below, we can remove the enableSyncThread method.

}
}

public void enableSyncThread() {
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] Think this can be deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Having this here allows us to check that the thread is started from within our tests.

),
"mongodblocal",
ServerEmbeddedMongoClientFactory.getInstance()
StitchAppClientInfo(
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this file can be reverted.

val bsonCodec = BsonDocumentCodec()

// fetch a new namespace, creating a new config
val nsConfig: NamespaceSynchronizationConfig = dataSynchronizer.getNamespaceConfig(namespace)
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 think you can get rid of dataSynchronizer.getNamespaceConfig and getNamespaceConfig as being exposed. Instead you should be able to utilize the top level public methods on the data synchronizer instead to act as a normal consumer which would make this a stronger test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Might it make more sense to do that in an integration test?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think so. The unit test here is aiming to check what happens if you are to configure twice. The first configuration should end up starting the listener. We don't need to reach that far into the implementation details. It ends up making the test brittle and not covering the actual aspect you want to test via the public API.

@coveralls
Copy link

Coverage Status

Coverage decreased (-26.6%) to 26.408% when pulling 17ae642 on jsflax:STITCH-1950 into 5a6a921 on mongodb:master.

@coveralls
Copy link

coveralls commented Oct 10, 2018

Coverage Status

Coverage increased (+2.4%) to 55.365% when pulling 6842550 on jsflax:STITCH-1950 into 5a6a921 on mongodb:master.

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.

just one nit (that affects a bunch of places), but otherwise looks I good I think once you make Eric's changes

*/
void configure(final ConflictHandler<DocumentT> conflictHandler,
void configure(@NonNull final ConflictHandler<DocumentT> conflictHandler,
final ChangeEventListener<DocumentT> changeEventListener,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] if we're labeling the conflict handler @NonNull, I guess we should explicitly mark the rest as @Nullable?


@Override
public void configure(final ConflictHandler<DocumentT> conflictHandler,
public void configure(@NonNull final ConflictHandler<DocumentT> conflictHandler,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto

* @param errorListener the error listener to invoke when an irrecoverable error occurs
*/
void configure(final ConflictHandler<DocumentT> conflictResolver,
void configure(@Nonnull final ConflictHandler<DocumentT> conflictHandler,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto


@Override
public void configure(final ConflictHandler<DocumentT> conflictResolver,
public void configure(@Nonnull final ConflictHandler<DocumentT> conflictHandler,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto

public <T> void configure(final MongoNamespace namespace,
final ConflictHandler<T> conflictHandler,
public <T> void configure(@Nonnull final MongoNamespace namespace,
@Nonnull final ConflictHandler<T> conflictHandler,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto

* during data synchronization
*/
void configure(final ConflictHandler<DocumentT> conflictResolver,
void configure(@Nonnull final ConflictHandler<DocumentT> conflictResolver,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto


@Override
public void configure(final ConflictHandler<DocumentT> conflictResolver,
public void configure(@Nonnull final ConflictHandler<DocumentT> conflictResolver,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] ditto

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.

One comment and one offline comment. Other than that LGTM

@jsflax jsflax merged commit a28ddad into mongodb:master Oct 10, 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