-
Notifications
You must be signed in to change notification settings - Fork 2
support proto serialization #509
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,13 +4,16 @@ import ( | |
| "encoding/json" | ||
| "reflect" | ||
|
|
||
| "github.com/gogo/protobuf/proto" | ||
|
|
||
| "github.com/smartcontractkit/chainlink-common/pkg/logger" | ||
| ) | ||
|
|
||
| // IsSerializable returns true if the value can be marshaled and unmarshaled without losing information, false otherwise. | ||
| // For idempotency and reporting purposes, we need to ensure that the value can be marshaled and unmarshaled | ||
| // without losing information. | ||
| // If the value implements json.Marshaler and json.Unmarshaler, it is assumed to be serializable. | ||
| // If the value is a protobuf message, it is also considered serializable. | ||
| func IsSerializable(lggr logger.Logger, v any) bool { | ||
| if !isValueSerializable(lggr, reflect.ValueOf(v)) { | ||
| return false | ||
|
|
@@ -25,11 +28,19 @@ func IsSerializable(lggr logger.Logger, v any) bool { | |
| return true | ||
| } | ||
|
|
||
| func isProtoMessage(v reflect.Value) bool { | ||
| protoMsgType := reflect.TypeOf((*proto.Message)(nil)).Elem() | ||
| return v.Type().Implements(protoMsgType) || reflect.PointerTo(v.Type()).Implements(protoMsgType) | ||
|
Comment on lines
+32
to
+33
|
||
| } | ||
|
|
||
| func isValueSerializable(lggr logger.Logger, v reflect.Value) bool { | ||
| // Handle nil values | ||
| if !v.IsValid() { | ||
| return true | ||
| } | ||
| if isProtoMessage(v) { | ||
| return true | ||
| } | ||
|
Comment on lines
+41
to
+43
|
||
|
|
||
| // Check if type implements json.Marshaler and json.Unmarshaler | ||
| fieldTypeRef := v.Type() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,12 +8,14 @@ import ( | |
|
|
||
| "github.com/Masterminds/semver/v3" | ||
| chainsel "github.com/smartcontractkit/chain-selectors" | ||
| "github.com/smartcontractkit/chainlink-common/pkg/logger" | ||
| mcmslib "github.com/smartcontractkit/mcms" | ||
| "github.com/smartcontractkit/mcms/types" | ||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/smartcontractkit/chainlink-common/pkg/logger" | ||
|
|
||
| "github.com/smartcontractkit/chainlink-deployments-framework/datastore" | ||
| pb "github.com/smartcontractkit/chainlink-protos/op-catalog/v1/datastore" | ||
| ) | ||
|
|
||
| func Test_IsSerializable(t *testing.T) { | ||
|
|
@@ -151,6 +153,26 @@ func Test_IsSerializable(t *testing.T) { | |
| v: datastore.AddressRef{}, | ||
| want: true, | ||
| }, | ||
| { | ||
| name: "should serialize proto message pointer", | ||
| // this is arbitrary proto message just to test the code path | ||
| v: &pb.AddressReferenceEditResponse{ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm i dont think this is enough, even though this serialized without error, it doesnt mean we dont have data lost. My understanding that for protos , we should at least be using |
||
| Record: &pb.AddressReference{ | ||
| Domain: "anything", | ||
| }, | ||
| }, | ||
| want: true, | ||
| }, | ||
| { | ||
| name: "should serialize proto message value", | ||
| // this is arbitrary proto message just to test the code path | ||
| v: pb.AddressReferenceEditResponse{ | ||
| Record: &pb.AddressReference{ | ||
| Domain: "anything", | ||
| }, | ||
| }, | ||
| want: true, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
|
|
||
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 function doesn't handle nil pointer values correctly. If
vrepresents a nil pointer to a proto message,v.Type()will return the pointer type but the check may fail. Consider adding a nil check and handling the case wherev.Kind() == reflect.Ptr && v.IsNil().