@@ -14,7 +14,10 @@ import (
1414const Name = "proto"
1515
1616func init () {
17- encoding .RegisterCodecV2 (& cortexCodec {})
17+ encoding .RegisterCodecV2 (& cortexCodec {
18+ noOpBufferPool : mem.NopBufferPool {},
19+ defaultBufferPool : mem .DefaultBufferPool (),
20+ })
1821}
1922
2023type ReleasableMessage interface {
@@ -25,7 +28,10 @@ type GogoProtoMessage interface {
2528 MarshalToSizedBuffer (dAtA []byte ) (int , error )
2629}
2730
28- type cortexCodec struct {}
31+ type cortexCodec struct {
32+ noOpBufferPool mem.BufferPool
33+ defaultBufferPool mem.BufferPool
34+ }
2935
3036func (c cortexCodec ) Name () string {
3137 return Name
@@ -64,7 +70,7 @@ func (c *cortexCodec) Marshal(v any) (data mem.BufferSlice, err error) {
6470
6571 data = append (data , buf )
6672 } else {
67- pool := mem . DefaultBufferPool ()
73+ pool := c . defaultBufferPool
6874 buf := pool .Get (size )
6975
7076 // If v implements MarshalToSizedBuffer we should use it as it is more optimized
@@ -94,10 +100,17 @@ func (c *cortexCodec) Unmarshal(data mem.BufferSlice, v any) error {
94100 return fmt .Errorf ("failed to unmarshal, message is %T, want proto.Message" , v )
95101 }
96102
97- // To be in the safe side, we will never automatically release the buffer used to Unmarshal the message automatically.
98- // This should simulate the same behavior of grpc v1.65.0 and before.
99- buf := data .MaterializeToBuffer (mem .DefaultBufferPool ())
103+ // To be safe, we avoid automatically releasing the buffer used to unmarshal the message.
104+ // Additionally, we avoid using a pooled byte slice unless the message implements ReleasableMessage.
105+ // This mimics the behavior of gRPC versions 1.65.0 and earlier.
106+ rm , ok := v .(ReleasableMessage )
107+ bufferPool := c .defaultBufferPool
108+
109+ if ! ok {
110+ bufferPool = c .noOpBufferPool
111+ }
100112
113+ buf := data .MaterializeToBuffer (bufferPool )
101114 err := proto .Unmarshal (buf .ReadOnlyData (), vv )
102115
103116 if err != nil {
@@ -106,8 +119,8 @@ func (c *cortexCodec) Unmarshal(data mem.BufferSlice, v any) error {
106119 }
107120
108121 // If v implements ReleasableMessage interface, we add the buff to be freed later when the request is no longer being used
109- if fm , ok := v .( ReleasableMessage ); ok {
110- fm .RegisterBuffer (buf )
122+ if rm != nil {
123+ rm .RegisterBuffer (buf )
111124 }
112125
113126 return err
0 commit comments