Skip to content

Commit f3bd794

Browse files
luigirendeyaron2
andauthored
Mongo State: fix serialization value in the transaction method (#3576)
Signed-off-by: Luigi Rende <[email protected]> Co-authored-by: Yaron Schneider <[email protected]>
1 parent 0f09d25 commit f3bd794

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

state/mongodb/mongodb.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
"strings"
2626
"time"
2727

28+
"github.com/dapr/components-contrib/contenttype"
29+
2830
"github.com/google/uuid"
2931
"go.mongodb.org/mongo-driver/bson"
3032
"go.mongodb.org/mongo-driver/bson/bsonrw"
@@ -528,7 +530,18 @@ func (m *MongoDB) doTransaction(sessCtx mongo.SessionContext, operations []state
528530
var err error
529531
switch req := o.(type) {
530532
case state.SetRequest:
531-
err = m.setInternal(sessCtx, &req)
533+
{
534+
isJSON := (len(req.Metadata) > 0 && req.Metadata[metadata.ContentType] == contenttype.JSONContentType)
535+
if isJSON {
536+
if bytes, ok := req.Value.([]byte); ok {
537+
err = json.Unmarshal(bytes, &req.Value)
538+
if err != nil {
539+
break
540+
}
541+
}
542+
}
543+
err = m.setInternal(sessCtx, &req)
544+
}
532545
case state.DeleteRequest:
533546
err = m.deleteInternal(sessCtx, &req)
534547
}

tests/conformance/state/state.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package state
1515

1616
import (
1717
"context"
18+
"encoding/base64"
1819
"encoding/json"
1920
"fmt"
2021
"slices"
@@ -784,6 +785,70 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
784785
assert.Equal(t, v, res.Data)
785786
}
786787
})
788+
789+
t.Run("transaction-serialization-grpc-json", func(t *testing.T) {
790+
features := statestore.Features()
791+
// this check for exclude redis 7
792+
if state.FeatureQueryAPI.IsPresent(features) {
793+
json := "{\"id\":1223,\"name\":\"test\"}"
794+
keyTest1 := key + "-key-grpc"
795+
valueTest := []byte(json)
796+
keyTest2 := key + "-key-grpc-no-json"
797+
798+
metadataTest1 := map[string]string{
799+
"contentType": "application/json",
800+
}
801+
802+
operations := []state.TransactionalStateOperation{
803+
state.SetRequest{
804+
Key: keyTest1,
805+
Value: valueTest,
806+
Metadata: metadataTest1,
807+
},
808+
state.SetRequest{
809+
Key: keyTest2,
810+
Value: valueTest,
811+
},
812+
}
813+
814+
expected := map[string][]byte{
815+
keyTest1: []byte(json),
816+
keyTest2: []byte(json),
817+
}
818+
819+
expectedMetadata := map[string]map[string]string{
820+
keyTest1: metadataTest1,
821+
}
822+
823+
// Act
824+
transactionStore, ok := statestore.(state.TransactionalStore)
825+
assert.True(t, ok)
826+
err := transactionStore.Multi(context.Background(), &state.TransactionalStateRequest{
827+
Operations: operations,
828+
})
829+
require.NoError(t, err)
830+
831+
// Assert
832+
for k, v := range expected {
833+
res, err := statestore.Get(context.Background(), &state.GetRequest{
834+
Key: k,
835+
Metadata: expectedMetadata[k],
836+
})
837+
expectedValue := res.Data
838+
839+
// In redisjson when set the value with contentType = application/Json store the value in base64
840+
if strings.HasPrefix(string(expectedValue), "\"ey") {
841+
valueBase64 := strings.Trim(string(expectedValue), "\"")
842+
expectedValueDecoded, _ := base64.StdEncoding.DecodeString(valueBase64)
843+
require.NoError(t, err)
844+
assert.Equal(t, expectedValueDecoded, v)
845+
} else {
846+
require.NoError(t, err)
847+
assert.Equal(t, expectedValue, v)
848+
}
849+
}
850+
}
851+
})
787852
} else {
788853
t.Run("component does not implement TransactionalStore interface", func(t *testing.T) {
789854
_, ok := statestore.(state.TransactionalStore)

0 commit comments

Comments
 (0)