-
Notifications
You must be signed in to change notification settings - Fork 77
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
Retrieve the value from seenMessages once to avoid NullPointerException #129
Conversation
…on if it is dropped when we added new unseen messages.
Cool! Looks like you are solve the puzzle 👍 From my initial review I though that something could be called on another thread. And yep, if you are going to use |
Though I'm just slightly concerned regarding the style like doing other things (especially with side effects) in msgSubscribed
.mapNotNull { msg -> seenMessages[getMessageId(msg)]?.let { msg to it } }
// seen message -> validation result
.forEach { (msg, res) -> notifySeenMessage(peer, msg, res) } What do you think? |
You I wasn't all that keen on doing work in the filter either. My first thought was to just use a plain for each loop and add to an array manually. ie:
but I could easily work out what the Kotlin equivalent of that was so just went with filter. Your suggested change would also work, though it does leave open the possibility that a message will wind up being neither seen nor unseen which is a little odd, but I don't think it actually breaks anything. I'm happy to go with whatever you think is best. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's stick to your suggested code. It looks clearer imho, despite may be that way of filter()
usage
(msgSubscribed - msgUnseen).forEach { notifySeenMessage(peer, it, seenMessages[getMessageId(it)]!!) } | ||
.filter { subscribedMessage -> | ||
val messageId = getMessageId(subscribedMessage) | ||
val seenMessage = seenMessages[messageId] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just rename seenMessage
to validationResult
for clarity
In
AbstractRouter
seenMessages is an LRU map so it automatically removes items when new ones are added to stay below some maximum size. So we could wind up with a message in msgSubscribed which is present in seenMessages when we first create msgUnseen but is then evicted when we we add the unseen messages on the second line. Then when we get to the last line seenMessages[getMessageId(it)] returns null because the message has now been dropped from seenMessages.To avoid this, retrieve the value from
seenMessages
once and hold on to it while processing. This avoids the risk that the value is dropped while recording the newly seen messages.A less invasive change would be to move the line:
down below the line that calls
notifySeenMessage
which is the second place we look up the value fromseenMessages
. But that feels like a very subtle dependency on ordering.fixes Consensys/teku#2452