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
Add disableAutoRequest method that disables all automatic inbound flow-control requests #6807
Conversation
The default behavior of requesting initial messages is applied even if disableAutoInboundFlowControl is called. ServerCalls disables all automatic flow control which is much more useful in case the user can't handle incoming messages until some time after the call has started. This change creates a new StartableListener that has an onStart method that is invoked when the call is started which makes initial requests if necessary.
Delete accidental addtion
@DRayX can you take care of CLA authorization? |
Add a new disableAutoRequest method that disables all automatic requests while disableAutoInboundFlowControl maintains existing behavior. disableAutoInboundFlowControl is also marked as Deprecated.
Update the manual flow control examples to use the new disableAutoRequest method. Note that the ManualFlowControlClient now needs to request one message after the call has been started.
Update the manual flow control client example to use a pattern that is applicable in all call arities (unary or streaming request). If the call is unary request, the StreamObserver isn't returned, so the initial request can't be started from the return value, but the initial request can't be made before the call is started, so we expose a custom "request" method on the ClinetResponseObserver implementation.
Copying this from #6806. @DRayX said:
That's an important realization. I wonder if we should allow request()s to be "queued" ("counted") during beforeStart() and then "drain" them after calling start(). The docs for that will be a bit weird, especially if we don't make it thread-safe, and making it thread safe will be a bit annoying |
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.
those documentation fixes will be nice but still LGTM
Noted the difference between client and server migration
Fix indentation
We should not encourage users to migrate before the new API is ready. The main problem is we are
It isn't clear to me which class you are talking about putting that code in. Since it says "stream" I'd assume private final AtomicInteger pendingRequest = new AtomicInteger();
@Override
public void request(int numMessages) {
checkArgument(numMessages >= 0);
int oldRequests;
while ((oldRequests = pendingRequest.get()) >= 0) {
int newRequests = oldRequests + numMessages;
if (newRequests < 0) { // overflow
newRequests = Integer.MAX_VALUE;
}
if (pendingRequest.compareAndSet(oldRequests, newRequests)) {
return;
}
}
stream.request(numMessages);
}
private void setStream(ClientStream stream) {
this.stream = stream;
stream.request(pendingRequest.getAndSet(-1));
} That said, I'm not excited about that logic being in However, taking a step back, the options I see:
(4) is my preference. I'm pretty disappointed with the options overall, but think it is the most straight-forward, causes the least problems, and fits in best with the rest of the API. I wanted to like (1), but couldn't since virtually every user of |
Fair enough, I'm good with trying to resolve this in the same PR.
Ya, that would be in
All early requests will be made on the stream. The
I'm not actually convinced. I feel like putting it in ClientCall is actually nice as it means that the semantics of
Don't really love option 4 since it adds an extra method that is used only when setting up ClientCalls without flow control. If we wanted to go that route, I think I would prefer for |
I see now that the
I really don't want
I'm not wild about it either. It just seemed least bad. Instead of adding one method we add two; unfortunate, but meh.
I'm not entirely against that. The main problem I had was that it is unclear what the
I completely agree with the sentiment. But it is also the biggest change (in semantics; not code). I feel wrong making that major of a change for this "minor" of an issue, especially since it is this API's own fault. (ClientCallStreamObserver.request is what I would change first, but that causes the skew issues between ClientCall and StreamObserver and I'd still be bothered by the thread-safety aspect.) It doesn't seem like the KISS solution; there are a lot of lurking details. That's why I'm favoring the uglier API, because it really is KISS. Easy for vast majority of users. Easy to implement. Easy to comprehend how the APIs interact. Trying to make this part of the API pretty and orthogonal seems to introduce too much cost for the gain. The root problem is that there is no start() method and beforeStart() only approximated it, and fixing that is a whole nother can of worms. |
(FWIW, I thought a long time about the list of options. I really wanted a way to "fix" request such that I could be happy with it. I made up my mind in determining my "preference" multiple times and then hated it still so went back to the drawing board. I'm serious when I say I wanted request() to work. And I do have concerns about |
The wider team discussed this yesterday and there was a consensus of going with option (4) There was not a consensus of whether we should also have Does that sound fair? |
Sounds reasonable to me. My one question is what the behavior should be if disableAutoRequestWithInitial is called more than once? My gut feeling is that it should be an illegal state exception, or it should overwrite the initial request count. |
|
Switch to a disableAutoRequestWithInitialMethod that allows for an initial number of requests to be specified. Also, change the behavior of ClientCalls.CallToStreamObserverAdapter.request to request 2 if expecting unary respone.
As I was implementing, just overwriting the value was simpler, but I'm cool with switching to |
Fix accidental deletion
@DRayX Tests are broken, would you be able to fix that? |
Searching for the bug causing test failures I realized that server-side should potentially use I'd really like this merged. I think it may be best to avoid adding |
Thanks for finding the bug, sorry I hadn't looked at it yet, I got sidetracked on another project. |
@DRayX, thank you! Sorry that was quite a process! |
@DRayX, we discussion in the api review meeting today. I posted results to #1788 (comment) . But basically we're going to have disableAutoRequest on server-side and disableAutoRequestWithInitial on client-side. I was planning on making a PR with the changes. |
The default behavior of requesting initial messages is applied even if disableAutoInboundFlowControl is called. ServerCalls disables all automatic flow control which is much more useful in case the user can't handle incoming messages until some time after the call has started. This change creates a new StartableListener that has an onStart method that is invoked when the call is started which makes initial requests if necessary.
See #6806