Subject: Re: [quicwg/base-drafts] H3 GOAWAY should be symmetric and cover bidi and uni streams (#2632)

From: afrind <[email-masked]>
Date: Tue, 08 Oct 2019 15:01:02 -0700

I think it's more about challenging the assumption that stopping sending requests (or push credits) is the same as explicitly signaling your intent to close the connection.  If the endpoint knows it will shutdown, it signals the peer, and the peer can take actions in response to ensure the close is graceful.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-539722175

---

From: ianswett <[email-masked]>
Date: Wed, 09 Oct 2019 19:21:40 -0700

@afrind Can you clarify what your current proposal is?  Is it to move GOAWAY to transport or keep it in H3 and make it bidi?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-540300591

---

From: Mike Bishop <[email-masked]>
Date: Thu, 17 Oct 2019 13:49:43 -0700

Discussed in Cupertino: Clients can send GOAWAY.  Add transition considerations to talk about relaying GOAWAY from an H2 to H3 connection / vice versa.  We would like the client-sent GOAWAY to carry a Push ID.  There is still disagreement over what the precise semantics of that are.  @afrind to write a PR to provoke argument.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-543355875

---

From: Martin Thomson <[email-masked]>
Date: Mon, 21 Oct 2019 18:24:30 -0700

The semantics of an identifier in the server-to-client GOAWAY are twofold.  The identifier clearly identifies requests that were not "processed", which allows the client to retry those requests.  The identifier also identifies which of those requests can be cleaned up expeditiously.  My view is that the former is significantly more important.  Enabling clean retry is one of the best features of h2.

For pushes, the need to signal whether the data was "processed" is moot, because only safe requests can be pushed.  So most of this comes down to what optimizations are enabled by the explicit Push ID.

In h2, requests are automatically "cancelled", though the bits are still retransmitted by TCP if the connection is kept alive.  A client isn't required to reset or finalize any associated streams if the requests were not complete, but the transport will automatically repair lost segments.

In h3, the same applies, though there is an optimization that might be enabled.  The transport layer can be told not to retransmit data for "cancelled" streams if packets are lost.  This doesn't require explicit RESET_STREAM or STOP_SENDING frames, reprioritization might be enough.  Depending on the transport implementations, endpoints might need to use RESET_STREAM to ensure that transport stacks are aware of the need to suppress retransmissions.

>From that perspective, an explicit Push ID would enable new capabilities in terms of suppression of unnecessary retransmission.

For example, say that there is an open request that is receiving associated pushes for data that arrives on a fixed cadence.  Say that a client wants to move to a different connection (because it was told with Alt-Svc, for instance).  The client might initiate a request starting at a particular time on a new connection.  When the client cancels this connection, there might be a number of pushes in flight.  If the client can precisely identify the push that immediately precedes the request it initiates on the new connection, the server can identify which of these pushes need to be fully delivered, and which can be abandoned.

However, this optimization really only works if the client can make this identification precisely.  If there are multiple requests in flight on the connection, the client might not be able to identify or predict the Push ID that will be used for the next push in the sequence.  The server might avoid this by providing promises well ahead (>1RTT) of the actual pushes so that the client doesn't need to guess, but that might not be possible in the general case.

This also requires that Push IDs are used strictly sequentially with respect to the global clock.  This doesn't guarantee clean separation even if Push IDs monotonically increase for each resource.  For instance, if two resources were providing the same sort of pushes, response 0 might promise Push ID 10 for time=44, but response 4 might promise Push ID 9 that corresponds to time=45.  That makes it difficult for a client to make a clean cut with a single value.

This also doesn't interact well with a model where the answering of a request depends on receiving a set of pushes.  If you have a resource that produces a continuous set of pushes on the same connection as a resource that (ideally) produces a fixed number of pushes (see also Prefer-Push), then the cut for the continuous resource might be clean, but it might split the pushes for the resource with a fixed set of associated pushes.

Of course, all of these arguments could easily be countered by saying that this is just an optimization, but given that it's an optimization we don't have for h2 (because TCP), I think that I'd prefer not to provide the capability.

Finer-grained signals might be valuable: such as the idea that individual requests might have separate budgets for push that can be progressively expanded by clients as they are ready for more.  That seems like something worth considering for future versions of this protocol.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-544772352

---

From: Mike Bishop <[email-masked]>
Date: Wed, 23 Oct 2019 11:41:32 -0700

#3129 makes a subtle but major change to the semantics, and I think we need to carefully consider whether that's something we want.  We were conflating these two models during interim discussion, and I don't think we're clear on our direction yet.

Instead of "Clients MUST NOT send new requests on the connection after receiving GOAWAY", we now have "Endpoints MUST NOT initiate new requests or pushes on the connection **with an identifier greater than or equal to the smallest identifier received in a GOAWAY frame.**"  In other words, GOAWAY(`max_varint`) has changed from meaning "I'll service your in-flight requests, but don't make any new ones" to a no-op, since the client couldn't have initiated such a request anyway.

I understand that this might be a desirable pattern in the server-to-client direction, where certain use patterns consider the set of pushes part of the fulfillment of the client's request, and the client actively wants the server to continue initiating pushes until the request is complete.  This doesn't seem a wise semantic to bring to the client-to-server direction.

In HTTP/2, the recipient of the GOAWAY was prohibited from initiating any more activity (requests or pushes) regardless of the value in the frame.  My first preference is to preserve that, and actually have the same semantics as HTTP/2.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-545581410

---

From: ianswett <[email-masked]>
Date: Wed, 23 Oct 2019 18:45:48 +0000 (UTC)

I agree with @MikeBishop that's a useful semantic we should preserve in HTTP/3.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-545583148

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 23 Oct 2019 12:12:36 -0700

I think Mike articulated a point I was trying to make on Slack but in a much better way. +1.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-545593626

---

From: afrind <[email-masked]>
Date: Thu, 24 Oct 2019 13:06:24 -0700

Ah, I was trying to get the behavior @mt was after for pushes (eg: let the server keep pushing if it wants to), and didn't intend to allow the client to send more requests after receiving a GOAWAY -- that doesn't work.

But it sounds like we'd prefer to keep the push behavior symmetric with h2 (no more pushes after GOAWAY receipt) than introduce a new push semantic where the client can allow pushes to continue even after signaling its intent to close.  This is more along the lines that @LPardue was advocating for - where the intent to close and how pushes are wound down are completely decoupled frames.

The discussion on slack I thought was different - it was about what the *sender* of a GOAWAY should do with new incoming streams.  I intended the PR to reflect that the sender of a GOAWAY should continue allowing requests or pushes with ID's smaller than the sent GOAWAY value.  Do we agree this is the right behavior?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-546080954

---

From: Mike Bishop <[email-masked]>
Date: Tue, 29 Oct 2019 08:24:52 -0700

The sender of GOAWAY needs to continue accepting incoming streams up to the indicated ID, yes.

If we decide the other semantic is useful, it's easy enough to define another frame (SOFT_GOAWAY, IN_CONCLUSION, etc.) in-spec or as an extension that simply hints to the other side that they should start cleaning up, but doesn't fully prohibit new streams.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-547477462

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 29 Oct 2019 09:46:30 -0700

> SOFT_GOAWAY, IN_CONCLUSION
[
LAST_ORDERS](https://dictionary.cambridge.org/dictionary/english/last-orders)

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2632#issuecomment-547519562