Skip to content

JAVA-3485: Suppress firing of duplicate cluster events #566

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

Closed
wants to merge 6 commits into from

Conversation

jyemin
Copy link
Collaborator

@jyemin jyemin commented Aug 29, 2020

The design problem presented by this requirement is that currently we combine the ServerListener registered by Cluster implementations to be informed of server changes with any ServerListeners registered by an application. This turns out to be incorrect, because different rules apply. The Cluster needs to be informed of all changes to server descriptions, e.g. including changes to RTT. But the spec requires that server events are only delivered to applications under certain rules of equality. So to implement this, in the first commit I refactored Server and Cluster implementations to separate the two types of listeners (adding a new private interface for the former). In the second commit I implemented the event suppression rules required by the specification.

https://spruce.mongodb.com/version/5f4ab0a92a60ed0c9dcaac25/tasks

jyemin added 3 commits August 29, 2020 15:49
The monitoring specification requires that duplicate server
events are not sent.  This refactoring separates server listeners
registered by the application, to which this rule applies, from
the one registered by Cluster implementation, to which this rule
does not apply.

JAVA-3485
Don't fire server or cluster description changed events when the description hasn't changed
from the previously fired event.

JAVA-3485
@jyemin jyemin self-assigned this Aug 29, 2020
@jyemin jyemin requested review from rozza and durran August 29, 2020 19:59
@durran
Copy link
Member

durran commented Aug 31, 2020

LGTM

Copy link
Contributor

@bdeleonardis1 bdeleonardis1 left a comment

Choose a reason for hiding this comment

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

This was interesting (and tough) to read through. I left a few questions I had on mostly style things whenever you get a chance to explain them.

Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

Looks good - one method name is wrong and a nit.

return true;
}

static boolean equivalentEvent(final ServerDescription current, final ServerDescription previous) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: Naming not comparing events, so the function name creates some unnecessary cognitive load.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, the naming choice was deliberate, but I see why it's confusing. I didn't want to call it equivalentDescriptions, since that would beg the question of why we're not just using ServerDescription#equals. It's really more like 'wouldDescriptionsGenerateEquivalentEvents'. Would that be better? Or perhaps just a comment explaining it? Both?

Copy link
Member

Choose a reason for hiding this comment

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

I think both would be good - it looks like a typo now and future Ross would probably wonder why we're not using equals!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

if (current.getServerDescriptions().size() != previous.getServerDescriptions().size()) {
return false;
}
for (ServerDescription curNew: current.getServerDescriptions()) {
Copy link
Member

Choose a reason for hiding this comment

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

Observation: I had a look at doing this with streams, to see if there was any nice patterns to for this / if it would be easier to read:

        return !current.getServerDescriptions().stream().anyMatch(c ->  
          !previous.getServerDescriptions().stream()
                    .filter(p -> p.getAddress().equals(c.getAddress()))
                    .findFirst()
                    .map(p -> equivalentEvent(c, p))
                    .orElse(false)
        );

I suppose it depends on preference as to which is more readable and I have no idea about comparative performance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I find it more natural with the loop, which might just be my lack of familiarity with streams. OK to keep it as is?

Copy link
Member

Choose a reason for hiding this comment

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

Yeap - that was just for my learning


import com.mongodb.event.ServerDescriptionChangedEvent;

// internal interface that Cluster implementations register with Server implementations in order be notified of changes in server state.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Use java doc / block comment pattern - even if javadocs arent produced for internal packages it keeps things normalized.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, I was using this style to make it less confusing, so readers wouldn't think the interface was public.

Done

@jyemin jyemin requested a review from rozza September 2, 2020 13:26
Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

LGTM

@jyemin
Copy link
Collaborator Author

jyemin commented Sep 8, 2020

Merged on command line

@jyemin jyemin closed this Sep 8, 2020
@jyemin jyemin deleted the j3485 branch December 22, 2020 20:42
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