Skip to content
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

deprecate stream, move documentation to client|server stream #2198

Merged
merged 13 commits into from
Jul 9, 2018

Conversation

jeanbza
Copy link
Member

@jeanbza jeanbza commented Jul 3, 2018

Deprecate Stream, and move the methods and documention to ServerStream
and ClientStream. This is due to the fact that there are different
semantics for SendMsg, and it's quite confusing to document one method
for two things. Furthermore, Stream is not actually used in any way
other than to be inherited by ClientStream and ServerStream.

Relevant issue: #2159

jeanbza added 2 commits July 3, 2018 13:29
Deprecate Stream, and move the methods and documention to ServerStream
and ClientStream. This is due to the fact that there are different
semantics for SendMsg, and it's quite confusing to document one method
for two things. Furthermore, Stream is not actually used in any way
other than to be inherited by ClientStream and ServerStream.

Relevant issue: grpc#2159
@jeanbza jeanbza requested a review from dfawley July 3, 2018 20:30
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this, I think it will be a big help!

stream.go Outdated
// But it is not safe to call RecvMsg on the same stream in different goroutines.
RecvMsg(m interface{}) error
}
// DEPRECATED: See ClientStream and ServerStream documentation instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "Deprecated" (case) - it actually matters to tools like staticcheck.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

stream.go Outdated

// ClientStream defines the interface a client stream has to satisfy.
// All errors returned from ClientStream are compatible with the status package.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "from ClientStream methods"

(and ServerStream)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and applied similar change to ServerStream.

stream.go Outdated
RecvMsg(m interface{}) error
}
// DEPRECATED: See ClientStream and ServerStream documentation instead.
type Stream interface {}

// ClientStream defines the interface a client stream has to satisfy.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ClientStream defines the client-side behavior of a streaming RPC."?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and applied a similar change to ServerStream.

stream.go Outdated
// Context returns the context for this stream.
Context() context.Context
// SendMsg is generally called by generated code. On error, SendMsg aborts
// the stream and returns an io.EOF; the status may be determined by
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"On error, SendMsg aborts the stream. If the error was generated by the client, the status is returned directly; otherwise, io.EOF is returned and the status of the stream may be discovered using RecvMsg."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

stream.go Outdated
// inspecting the error returned by calling RecvMsg.
//
// SendMsg blocks until:
// - It schedules m with the transport, or
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about: "- There is sufficient flow control to schedule m with the transport, or"

...or something to indicate that we aren't just letting people queue up a billion messages.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

stream.go Outdated
// SendMsg does not wait for an ack. An untimely stream closure can result
// in any buffered messages along the way (including those in the
// client-side buffer that comes with gRPC by default) being lost. To
// ensure delivery, users must call RecvMsg until receiving an EOF before
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is painfully explicit IMO. How about:

"SendMsg does not wait until the message is received by the server. An untimely stream closure may result in lost messages. To ensure delivery, users should ensure the RPC completed successfully using RecvMsg."

The idea would be to refer people to RecvMsg and make sure we document it well enough there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is really good. 👍

Done.

stream.go Outdated
Stream
// It's safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time. It is not safe
// to call SendMsg on the same stream in different goroutines.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"to call SendMsg or CloseSend"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Good call.

stream.go Outdated
// calling RecvMsg on the same stream at the same time. It is not safe
// to call SendMsg on the same stream in different goroutines.
SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message or the stream is done. On
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the client/server language:

RecvMsg blocks until it receives a message into m or the stream is done. It returns io.EOF when the stream completes successfully. On any other error, it the stream is aborted and the error contains the RPC status.

It is safe to have a goroutine calling SendMsg and another goroutine calling RecvMsg on the same stream at the same time, but it is not safe to call RecvMsg on the same stream in different goroutines.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

stream.go Outdated
// - The stream is done, or
// - The stream breaks.
//
// SendMsg does not wait for an ack. An untimely stream closure can result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

stream.go Outdated
// calling RecvMsg on the same stream at the same time. It is not safe
// to call SendMsg on the same stream in different goroutines.
SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message or the stream is done. On
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove client/server language here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (copy paste from above).

@dfawley dfawley added the Type: Documentation Documentation or examples label Jul 3, 2018
@dfawley dfawley added this to the 1.14 Release milestone Jul 3, 2018
@jeanbza
Copy link
Member Author

jeanbza commented Jul 4, 2018

All comments addressed; PTAL at your convenience.

@jeanbza
Copy link
Member Author

jeanbza commented Jul 4, 2018

Wait, ignore that, github was hiding ones from me. Fixing the outstanding ones!

stream.go Outdated
// It's safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time. It is not safe
// to call SendMsg on the same stream in different goroutines.
// RecvMsg blocks until it receives a message into m or the stream is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You deleted SendMsg by mistake.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who needs it! :)

Jk, added back in.

stream.go Outdated
@@ -145,7 +144,7 @@ func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method st

// NewClientStream is a wrapper for ClientConn.NewStream.
//
// DEPRECATED: Use ClientConn.NewStream instead.
// Deprecated: Use ClientConn.NewStream instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not change this just yet...generated code still uses this (so vet fails).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Ditto for ServerStream and Stream?

// Stream.SendMsg() may return a non-nil error when something wrong happens sending
// the request. The returned error indicates the status of this sending, not the final
// status of the RPC.
// Context returns the context for this stream.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry...can you add this, too (only for ClientStream):

It should not be called until after Header or RecvMsg has returned. Once called, subsequent client-side retries are disabled.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Good note - that's unexpected (to me).

// - The stream is done, or
// - The stream breaks.
//
// SendMsg does not wait until the message is received by the server. An
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/server/client/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Good find.

// - The stream breaks.
//
// SendMsg does not wait until the message is received by the server. An
// untimely stream closure may result in lost messages. To ensure delivery,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server can never know whether the client received the message without something in the user's protocol.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right - this line alludes to that. I could more strongly state that by adjusting the line to:

"SendMsg does not wait until the message is received by the client. Users who need per-message acknowledgement are expected to implement it on top of gRPC."

Though, I don't know how much value there is in that. I kind of think the brevity of just saying, "we don't wait" is enough of a warning. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will you update this? The bit about "ensure the RPC completed successfully using RecvMsg" is misleading/wrong on the server-side.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this comment..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shoot, sorry to have missed this. Hm, good point - that just means the client has finished sending their messages. Bad copy paste. I'm not sure it's worth saying, but is it correct to say that once the server returns in the handler, all messages will have been sent successfully? Or is the promise still only that messages have been scheduled? In short, is there any way to ensure all server messages have arrived? (I think not, but want to make sure I ask)

In the meantime, I've simply removed the line about RecvMsg. I neglected to include the line about per-message acks, since it doesn't seem to add too much more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's worth saying, but is it correct to say that once the server returns in the handler, all messages will have been sent successfully?

No, the server never knows whether a message is received by the client unless the user builds their own acks into their protocol. I think what you were proposing before was fine: "SendMsg does not wait until the message is received by the client."

stream.go Outdated
// to call SendMsg or CloseSend on the same stream in different goroutines.
SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message into m or the stream is
// done. It returns io.EOF when the stream completes successfully. On
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the server, io.EOF should not be returned.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nil, I assume?

(changed it as such on that assumption)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait...did I write that?

RecvMsg does return io.EOF, but it's when the client does CloseSend, not when the stream completes. Sorry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - added back in io.EOF documentation.

Heh no prob :)

stream.go Outdated
//
// It is safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time, but it is not safe
// to call SendMsg or CloseSend on the same stream in different goroutines.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "or CloseSend" only applies to the client, not the server. The server doesn't have a CloseSend. Sorry if I put my comment in the wrong place earlier.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. (that make sense)

stream.go Outdated
// to call SendMsg on the same stream in different goroutines.
SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message into m or the stream is done.
// It returns io.EOF when the stream completes successfully. On any non-EOF
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"It returns io.EOF when the client has performed a CloseSend."?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member Author

@jeanbza jeanbza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@jeanbza jeanbza merged commit 50de898 into grpc:master Jul 9, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Jan 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: Documentation Documentation or examples
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants