You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is same described dapr/dapr#2016 for Redis State store
Expected Behavior
When a state is saved via the the executeTransaction method via GRPC, Multi method implementation for mongodb state store, and the state is again read in via the getState API, there is a deserialization issue.
In the collection the value field is always stored as string also if the contentType=application/json is present.
Actual Behavior
State saved via transactional API should be read correctly via the Get State API and save the value as bson.D and not as string if the contentType is equals to application/json
Steps to Reproduce the Problem
Install Dapr 1.14.4
Create a GRPC server implementing the Execute Transaction call
Save State via the transaction API GRPC and set in the metadata contentType=application/json
Get State and deserialize
Potential Issue
In the runtime, in the ExecuteStateTransaction method defined in grpc.go file the req.Value parameter of the SetRequest is always set as byte[]
setReq := state.SetRequest{
Key: key,
// Limitation:
// components that cannot handle byte array need to deserialize/serialize in
// component specific way in components-contrib repo.
Value: req.GetValue(),
Metadata: req.GetMetadata(),
}
because the req.GetValue is bytes in the proto request.
// StateItem represents state key, value, and additional options to save state.
message StateItem {
// Required. The state key
string key = 1;
// Required. The state data for key
bytes value = 2;
// The entity tag which represents the specific version of data.
// The exact ETag format is defined by the corresponding data store.
Etag etag = 3;
// The metadata which will be passed to state store component.
map<string,string> metadata = 4;
// Options for concurrency and consistency to save the state.
StateOptions options = 5;
}
At the end of ExecuteStateTransaction method the Multi interface is called.
Specifically in mongo component mongodb.go, the byte[] value is marshaled as string, in fact the steps are Multi function call doTransaction and this call setInternal where the value as byte[] are casted to string.
var v interface{}
switch obj := req.Value.(type) {
case []byte:
v = string(obj)
case string:
v = fmt.Sprintf("%q", obj)
default:
v = req.Value
}
My proposal to fix this bug is to check in the doTransaction function if the contentType is present and equals to application/json and the value is byte[] and do the json Unmarshal of the value, like this.
case state.SetRequest:
{
isJson := (len(req.Metadata) > 0 && req.Metadata[metadata.ContentType] == contenttype.JSONContentType)
if isJson {
if bytes, ok := req.Value.([]byte); ok {
err = json.Unmarshal(bytes, &req.Value)
}
}
err = m.setInternal(sessCtx, &req)
}
The text was updated successfully, but these errors were encountered:
This issue is same described dapr/dapr#2016 for Redis State store
Expected Behavior
When a state is saved via the the executeTransaction method via GRPC,
Multi
method implementation for mongodb state store, and the state is again read in via the getState API, there is a deserialization issue.In the collection the value field is always stored as string also if the
contentType=application/json
is present.Actual Behavior
State saved via transactional API should be read correctly via the Get State API and save the value as bson.D and not as string if the contentType is equals to
application/json
Steps to Reproduce the Problem
contentType=application/json
Potential Issue
In the runtime, in the
ExecuteStateTransaction
method defined ingrpc.go
file thereq.Value
parameter of theSetRequest
is always set asbyte[]
because the
req.GetValue
is bytes in the proto request.At the end of
ExecuteStateTransaction
method theMulti
interface is called.Specifically in mongo component
mongodb.go
, thebyte[]
value is marshaled as string, in fact the steps are Multi function call doTransaction and this call setInternal where the value asbyte[]
are casted to string.My proposal to fix this bug is to check in the doTransaction function if the
contentType
is present and equals toapplication/json
and the value isbyte[]
and do the json Unmarshal of the value, like this.The text was updated successfully, but these errors were encountered: