diff --git a/operations/validation.go b/operations/validation.go index 5a589a18..ac446c1e 100644 --- a/operations/validation.go +++ b/operations/validation.go @@ -4,6 +4,8 @@ import ( "encoding/json" "reflect" + "github.com/gogo/protobuf/proto" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -11,6 +13,7 @@ import ( // 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) +} + func isValueSerializable(lggr logger.Logger, v reflect.Value) bool { // Handle nil values if !v.IsValid() { return true } + if isProtoMessage(v) { + return true + } // Check if type implements json.Marshaler and json.Unmarshaler fieldTypeRef := v.Type() diff --git a/operations/validation_test.go b/operations/validation_test.go index acf9d83e..43d09c98 100644 --- a/operations/validation_test.go +++ b/operations/validation_test.go @@ -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{ + 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 {