Re: Design Issue: Life-cycle of a Stream

On 1 May 2013 10:03, James M Snell <jasnell@gmail.com> wrote:
> 1. Streams are initialized or opened by sending a HEADERS or
> HEADERS+PRIORITY frame that uses a previously unused stream
> identifier.
>
> 2. Only HEADERS and HEADERS+PRIORITY frames are used to open a stream.

I don't see why 1 & 2 are necessary.  It's just arbitrary.  Sending
any frame should suffice.

> 3. PUSH_PROMISE frames reserve a stream identifier but do not open the stream.

Good.

> 4. Promised streams are only opened by sending a subsequent HEADERS or
> HEADERS+PRIORITY frame that uses the reserved stream identifier.

Again, promised streams are opened by sending frames.

> 5. All streams are either fully open, half-closed by the client,
> half-closed by the server, or fully closed.

I think of this differently.  Streams aren't bi-directional
constructs, they are a loose binding of two unidirectional constructs.
 Each unidirectional component has its own state.

FINAL ends a stream in the direction that it appears on.
RST_STREAM ends a stream in the direction that it appears on and
requests the closure of the opposite direction.

> 6. All promised streams are associated with an originating "parent" stream.

That binding is a problem.  The reason for the stream association in
push promise is to obtain request headers.  That relationship is a
function of the HTTP usage of streams, not an inherent function of the
streaming layer.

> 7. A stream is half-closed by sending a frame with the FINAL bit set.

See above, FINAL ends a stream for the direction in which it appears.

> 8. A stream becomes fully-closed when either: a) both endpoints send
> frames with the FINAL bit set or b) either endpoint sends an RST_FRAME
> with that streams identifier.

RST_STREAM.

> 9*. Promised streams are automatically half-closed for the recipient.
> That is, when the server sends a PUSH_PROMISE to a client, that
> streams becomes automatically half-closed for the client. The only
> frame the client can send back to the server for that stream are
> RST_STREAM frames.
>
>   -- or --
>
> 9*. Promised streams are handled just like regular streams. The server
> opens the stream and half-closes. The stream does not fully close
> until either the client half-closes it or a RST_STREAM frame is sent
> for that stream.

Neither works particularly well for me.  If you consider independent
lifecycles for each direction of a stream, this sort of distinction is
unnecessary.

> 10*. Sending an RST_FRAME for a parent stream fully closes that stream
> as well as all associated promised streams.
>
>   -- or --
>
> 10*. Sending an RST_FRAME for a parent stream only closes that stream
> and has no affect on associated promised streams.

The latter, please.

> 11*. Fully closing a parent stream using symmetric half-closes will
> fully close all associated promised streams.
>
>   -- or --
>
> 11*. Fully closing a parent stream using symmetric half-closes has no
> affect on associated promised streams.

The latter, please.

> 12. Half or fully closing a promised stream has no impact on the
> parent stream or any associated sibling promised streams.

Of course.

> Ok, so that covers the lifecycle.. let's talk about processing.. this
> is largely a reiteration of my previous note on this but I want to
> make sure I've hit all the major points in how this is categorized.
>
> Tier 1: Includes the following...
>
> A. Reception and basic parsing of frames. "Basic parsing" here means
> looking at the header bytes to determine the frame type, making note
> of the flags, frame size and stream identifier, and performing any
> necessary header block decompression and state management.
>
> B. Handling of all session frames (stream id #0). This means that
> upgrade negotiation, SETTINGS, PING, flow control and session level
> error handling are all Tier 1 processes.

You probably need more than one dimension in your taxonomy to get this
right.  I don't see this as a function of the thing that processes
frames.

> C. Basic lifecycle handling of stream frames. This includes
> determination of whether a stream is open or closed, whether or not
> additional frames are allowed for a stream, validation of proper
> stream id use, reservation of stream id's with push_promise, and
> handling of the FINAL flag.

I'm assuming that there is a stream controller that takes all
stream-related frames and does things to the stream state.  That
controller looks at FINAL and consumes things like RST_STREAM.  But
that operates at what I consider to be Tier 2.  It also has its own
layering because flow control exists here.

> Tier 2: Includes the following...
>
> A. Frame-type specific processing. Validation and handling of frame
> payloads and frame-specific flags, not including header block
> processing (which is tier 1)
>
> B. Additional stream-level error handling not related to stream-lifecycle
>
> Tier 3: Includes all application-level handling (HTTP Semantics)
>
> So, when we say things like "an endpoint must be prepared to continue
> receiving frames on a closed stream", we mean to say that "an endpoint
> must be prepared to do tier 1 processing on all frames, even those
> sent for closed streams."
>
> Please weigh in on whatever items y'all feel are controversial. I'll
> work up proposed spec edits based on whatever feedback is received.
>
> - James
>

Received on Wednesday, 1 May 2013 17:49:51 UTC