-
Notifications
You must be signed in to change notification settings - Fork 228
Use Mono.empty() instead of a State with null value #525
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
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Well, it depends on the scenario. Having null here can mean the value exists, is null, has an etag and (why not) metadata. The value being null is not the same as "record not found".
I am not sure if we should return empty mono even for "record not found". This probably goes all the way into how each component handles key not found. Can we guarantee that no "relevant" metadata is returned when "key not found" in the component implementation? This new behavior would drop any extra information. I think it is responsibility of the app to check if "value is null" is enough to consider "record not found" for their scenario.
Uh oh!
There was an error while loading. Please reload this page.
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.
Most state store implementations (e.g. redis) cannot distinguish between "record not found" and null value.
Even if a state with null value is actually needed, "record not found" and value "null" should not be the same when properly serialized by JSON.
I've updated the PR to reflect this.
Note: because fields in protobuf is not nullable, the sensible value to indicate "record not found" (with current GetStateResponse spec) is an empty byte[].
If differentiation between "record not found" and null value is needed, it's the responsibility of the API designer. If the API can not differentiate, the user certainly can not as well.
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 agree that handling "record not found" in a unique way belongs to the API design. Now, we need to design the SDK based on the actual API we have. This is where my comments are coming from. We can discuss changes to the dapr API but that should be in another issue IMO.
I am not worried about string with "null" content. I am concerned about the case where the value is null (not "null") in the database and contains an etag. With this change, the etag is dropped and user will assume it is the case for key not found.
Checking for null payload or empty payload is not enough.
This is why I think the app should understand what is the behavior for the state store he is using and do the check. If I am using state stores that have etag, for example, the right thing to do is check for null etag on the response and not the payload. Our redis state store actually implements etag.
On the other hand, not every state store supports etag, so for those the check will be different.
This is why I am saying that (with the current Dapr API), the app must know how the state store being used handles "record not found". This change would create limitations.
Uh oh!
There was an error while loading. Please reload this page.
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 it comes down to different opinions about what's more important.
protobuf and golang (which means current Dapr API) do not support null values. They are specifically designed to not permit null values. Being null-safe is more important to them.
I do not think Java SDK somehow can "support" null values (when current Dapr API does not).
In my opinion, current Java SDK implementation is not "supporting" null values. It's treating an empty byte[] as null, which is misinterpreting values.
When null is serialized to byte[], it's not null. It's usually a byte array indicating a null value. For JSON, it's a 4 bytes array - "null".getBytes().
In short:
Current Java SDK implementation interprets both "null".getBytes() and empty byte[] as null. It's losing the differentiation.
I do not think My PR breaks the support of null values since they are not supported in the first place. My RP is suggesting a sensible convention of treating empty byte[] as "record not found".
I do not suggest that Dapr API be updated to support null values.
Uh oh!
There was an error while loading. Please reload this page.
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 agree with this statement. It all goes down to what it means to be null-safe. In this API, it means that users will get a State object that is never null. A state with null value is a legit possibility (semantically, since it is byte[] in Dapr API), returning empty Mono does not allow scenarios where app wants to save value as null because the response for "key not found" and "null value" would be the same. I've written a new test to showcase this and is in this PR (I've confirmed in the gRPC client that value is an empty byte array for "key not found" and "null value" scenarios): #528
I agree. I am not advocating for "null value" to be what is actually saved in the database. What I am saying is the value semantically mapping to null (empty byte[]) is returned in both cases: "key not found" and "value is null".
I see this differently. The interpretation of empty byte[] to an object type is a key functionality in the SDK. How do you deserialize empty byte[] to MyClass? Our default serializer chose to convert it to null. Again, the custom serializer comes handy here: the app decides how to solve this per domain class.
This is done by the serializer. We expect apps to use their own deserializer to solve the ambiguity. We cannot expect the convention proposed above to be true for every possible serializer. It can be true for JSON serializer but we are designing to support other serializers too.
We cannot adopt this convention because empty byte[] is also what is saved when user saves "null object". This behavior is beyond just the SDK like I said in the comment above.
I agree. But I think Dapr API should handle "key not found" in a way that is not ambiguous with "null value" - maybe some sort of error code? Anyway, this is something to be discussed in dapr/dapr repo.
I really appreciate this PR and the healthy discussion here. These types of discussions is what will help shape the SDKs but (more importantly) the Dapr runtime APIs.