-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Terminate stream with error on null values returned by RedisElementReader for top-level elements
#2672
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
Conversation
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 think all these changes and Javadoc edits look completely fine to me.
I'd be curious what @christophstrobl would have to say about this, though.
|
I'm a bit torn on this one, since the |
|
So what do we want to do here? Our serializer clearly allow for |
null values from top-level Flux and Mono responsesnull values returned by RedisElementReader for top-level elements
null values returned by RedisElementReader for top-level elementsnull values returned by RedisElementReader for top-level elements
…tReader` for top-level elements. We now emit InvalidDataAccessApiUsageException when a RedisElementReader returns null in the context of a top-level stream to indicate invalid API usage although RedisElementReader.read can generally return null values if these are being collected in a container or value wrapper or parent complex object.
Consistent operations documentation wording.
23c6ecf to
0b123d2
Compare
|
I rewrote this pull request to document the behavior in the context of top-level stream values. We also now terminate the stream in a controlled manner by emitting |
|
I am reviewing this PR now and I generally like the direction the changes took. However, I don't necessarily agree with this:
I think this is a significant change in the contract and behavior of SD Redis that will potentially and adversely affect the older GA'd branches in the Honestly, with regard to #2655, I really think this is a user problem and application concern more than it is a framework issue that needs to be addressed and handled by the framework. While these changes are an improvement overall (i.e. failing fast when Reactive streams are misused as the user has done in #2655, along with employing the Spring Framework DAO Exception Hierarchy (Javadoc)), it is also a clear change in the contract and behavior that diverges from the Reactive Streams specification, which is very clear on the matter (Rule 2.13) of I also agree with and reiterate @christophstrobl comments above, earlier. |
| return createMono( | ||
| connection -> connection.bRPopLPush(rawKey(sourceKey), rawKey(destinationKey), timeout).map(this::readValue)); | ||
| connection -> connection.bRPopLPush(rawKey(sourceKey), rawKey(destinationKey), timeout) | ||
| .map(this::readRequiredValue)); |
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.
Shouldn't this be .mapNotNull(..) in this case given the Duration parameter?
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.
The previous variant was mapNotNull that effectively filters null values turning RedisElementReader into something that has an ability of filtering. That's why we chose to use readRequiredValue throwing a proper exception.
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.
This previous variant was .map(this::readValue), line 288.
I was thinking more along the lines of the rightPop(key, :Duration) overloaded method above on line 262.
But, perhaps the choice of simply .map(this:readRequiredValue) vs. .mapNotNull(this:readRequiredValue) is due to the right pop followed by left push compound operation??
See spring-projects#2655 Original pull request: spring-projects#2672
See spring-projects#2655 Original pull request: spring-projects#2672
| import org.springframework.data.redis.serializer.RedisSerializationContext; | ||
| import org.springframework.lang.Nullable; | ||
| import org.springframework.util.Assert; | ||
|
|
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.
It seems to me the geoDist(..) methods in ReactiveGeoOperations for the GEODIST command variations should be protected in the case of returning null.
While the arguments passed to the ReactiveGeoOperations.distance(..) methods used in the computation of the geo distance calculation may not be null, the member argument may also not have been geocoded in Redis with the geoAdd(..) command properly (which I think is a prerequisite based on the docs).
Therefore, in the case of a "missing" member (or element) the GEODIST command returns null as documented.
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 think, perhaps, ReactiveGeoOperations needs further refinements down the road, particularly with guards around possible null values.
| return createMono( | ||
| connection -> connection.bRPopLPush(rawKey(sourceKey), rawKey(destinationKey), timeout).map(this::readValue)); | ||
| connection -> connection.bRPopLPush(rawKey(sourceKey), rawKey(destinationKey), timeout) | ||
| .map(this::readRequiredValue)); |
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.
This previous variant was .map(this::readValue), line 288.
I was thinking more along the lines of the rightPop(key, :Duration) overloaded method above on line 262.
But, perhaps the choice of simply .map(this:readRequiredValue) vs. .mapNotNull(this:readRequiredValue) is due to the right pop followed by left push compound operation??
| import org.springframework.data.redis.connection.stream.PendingMessages; | ||
| import org.springframework.data.redis.connection.stream.PendingMessagesSummary; | ||
| import org.springframework.data.redis.connection.stream.ReadOffset; | ||
| import org.springframework.data.redis.connection.stream.*; |
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.
We should avoid star imports.
See spring-projects#2655 Original pull request: spring-projects#2672
See spring-projects#2655 Original pull request: spring-projects#2672
|
The changes have been merged to |
|
Please close pull requests and remove their branches after merge. |
We now use
mapNotNullto map Redis response values to avoidNullPointerExceptionscaused byRedisElementReaderreturningnull.This effectively turns
RedisElementReaderinto a filter function that can suppress elements from being emitted.Closes #2655
If merged, we should bring these changes to all maintained 3.x branches.