Skip to content

Replace legacy SendMsg/RecvMsg with type-safe Send/Recv on NodeStream#255

Draft
Copilot wants to merge 6 commits intomasterfrom
copilot/refactor-legacy-msg-usage
Draft

Replace legacy SendMsg/RecvMsg with type-safe Send/Recv on NodeStream#255
Copilot wants to merge 6 commits intomasterfrom
copilot/refactor-legacy-msg-usage

Conversation

Copy link
Contributor

Copilot AI commented Feb 7, 2026

server.go and channel.go call SendMsg/RecvMsg on BidiStreamingServer and BidiStreamingClient, which bypasses the type-safe Send/Recv methods and violates the gRPC documentation: "No other methods in the ServerStream should be called directly." This was required by the custom gRPC codec that packed Metadata + application message into a custom wire format.

Approach

Embed the application message payload directly in ordering.Metadata, eliminating the custom codec entirely. gRPC now uses the standard proto codec.

Proto changes

  • Added bytes payload = 5 and uint32 msg_type = 6 to Metadata to carry the serialized application message and direction (request/response)

Runtime changes

  • encoding.go: Replaced Codec, ContentSubtype, init() registration, and newMessage() with two conversion functions:
    • toMetadata() — serializes application message into Metadata.payload for sending
    • fromMetadata() — reconstructs Message from received Metadata using proto registry lookup
  • server.go: srv.SendMsg(msg)srv.Send(md), srv.RecvMsg(req)srv.Recv()
  • channel.go: stream.SendMsg(req.msg)stream.Send(md), stream.RecvMsg(resp)stream.Recv(); getStream() now returns typed ordering.Gorums_NodeStreamClient instead of grpc.ClientStream
  • mgr.go: Removed grpc.CallContentSubtype(ContentSubtype) from default dial options

Test cleanup

  • Removed codec registration init() blocks from server_test.go, config_test.go, rpc_test.go, mgr_test.go
  • Made TestManagerLogging assertion robust against line number changes
  • Updated channel_test.go stream comparison types
// Before (server.go)
req := newMessage(requestType)
err := srv.RecvMsg(req)
// ...
err := srv.SendMsg(msg)

// After
md, err := srv.Recv()
req, err := fromMetadata(md)
// ...
md, err := msg.toMetadata()
srv.Send(md)

Net result: -35 lines, no custom codec, type-safe stream operations throughout.

Original prompt

This section details on the original issue you should resolve

<issue_title>Legacy use of RecvMsg and SendMsg in NodeStream; should use type-safe Recv and Send instead</issue_title>
<issue_description>In server.go we do this:

func (s *orderingServer) NodeStream(srv ordering.Gorums_NodeStreamServer) error {
...

		err := srv.SendMsg(msg)

...
		req := newMessage(requestType)
		err := srv.RecvMsg(req)

And in channel.go: we do this:

func (c *channel) receiver() {
...
		resp := newMessage(responseType)
		if err := stream.RecvMsg(resp); err != nil {
...

func (c *channel) sendMsg(req request) (err error) {
...
	if err = stream.SendMsg(req.msg); err != nil {

According to the documentation of ordering.Gorums_NodeStreamServer:

type BidiStreamingServer[Req any, Res any] interface {
    // Recv receives the next request message from the client.  
    Recv() (*Req, error)

    // Send sends a response message to the client.  
    Send(*Res) error

    // ServerStream is embedded to provide Context, SetHeader, SendHeader, and
    // SetTrailer functionality.  No other methods in the ServerStream should
    // be called directly.
    ServerStream
}

Note the last comment: No other methods in the ServerStream should be called directly. However, that is exactly what we are doing by calling SendMsg and RecvMsg. We should be calling Recv and Send instead, since these are type-safe variants.

Note: It is a bit tricky to fix since we are sending our custom type with our own "extra" fields:

// Message encapsulates a protobuf message and metadata.
//
// This struct should be used by generated code only.
type Message struct {
	metadata *ordering.Metadata
	message  proto.Message
	msgType  gorumsMsgType
}

However, I think we could simplify this whole affair by extending the ordering.Metadata proto message with fields for the:

  • message (this field could be a google.protobuf.Any type, or simply a bytes field) and
  • msgType (if it is necessary to specify request/response direction).

If this works, we could probably remove the encoding.go file. However, a deeper analysis is needed to determine if we can make this work.

Regarding the google.protobuf.Any vs bytes field for the message. The Any type uses a bytes field, but also has a string type_url field that I don't think we need. The ordering.Metadata message is a Gorums internal message not intended for public exposure.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@deepsource-io
Copy link
Contributor

deepsource-io bot commented Feb 7, 2026

Here's the code health analysis summary for commits e998359..27c452b. View details on DeepSource ↗.

Analysis Summary

AnalyzerStatusSummaryLink
DeepSource Go LogoGo✅ SuccessView Check ↗
DeepSource Shell LogoShell✅ SuccessView Check ↗

💡 If you’re a repository administrator, you can configure the quality gates from the settings.

Copilot AI and others added 4 commits February 7, 2026 12:14
- Add payload and msg_type fields to ordering.Metadata proto
- Regenerate proto files
- Add toMetadata/fromMetadata conversion methods in encoding.go
- Remove custom Codec, ContentSubtype, and init() codec registration
- Update server.go to use srv.Send/srv.Recv
- Update channel.go to use stream.Send/stream.Recv
- Update channel.getStream() to return typed stream
- Remove grpc.CallContentSubtype from mgr.go
- Remove codec registration from test init() functions

Co-authored-by: meling <810999+meling@users.noreply.github.com>
…obust

Co-authored-by: meling <810999+meling@users.noreply.github.com>
Co-authored-by: meling <810999+meling@users.noreply.github.com>
Co-authored-by: meling <810999+meling@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor legacy use of RecvMsg and SendMsg in NodeStream Replace legacy SendMsg/RecvMsg with type-safe Send/Recv on NodeStream Feb 7, 2026
Copilot AI requested a review from meling February 7, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Legacy use of RecvMsg and SendMsg in NodeStream; should use type-safe Recv and Send instead

2 participants