On 07/08/2015 03:49 PM, Rafael Schloming wrote:
I think what is confusing about the spec language is that it is defining
the meaning of the value in terms of the sending endpoint's state and then
not saying anything about when the sending endpoint is obligated to
communicate the value to the receiver. This is because (at least as
originally conceived) it is never directly obligated to communicate the
value to the receiver, i.e. it could just choose to grow its array
indefinitely.
By contrast the incoming-window is defined in terms of the receiver's
endpoint state and it is (relatively) clearly communicated that the
receiver is obligated to communicate a non-zero incoming-window if it
wishes to receive transfer frames.
So while I agree that the language as defined requires the outgoing window
to be increased from zero, I don't think this implies (at least without a
more careful reading) that the sender needs to communicate this fact before
sending transfers. It owns the value so it can effectively increase the
outgoing-window to 1 momentarily, send the transfer, and then decrease it
back to zero without needing to sandwich that transfer in flow frames in
order to signal the changing window values.
I think that is a bit of a stretch given the language the spec does use.
I agree it doesn't explicitly state the rule in those terms, however it
does say:
The remote-outgoing-window reflects the maximum number of
incoming transfers that MAY arrive without exceeding the
remote endpoint’s outgoing-window. This value MUST be
decremented after every incoming transfer frame is received,
and recomputed when informed of the remote session endpoint
state.
I.e. the language suggests that a compliant receiver must do some work
to keep track of the value and states that this value is tied to the
maximum number of transfers that may arrive.
Put another way, the rule that says it is illegal for the sender to send
transfers when the receiver's incoming window is zero creates an obligation
for the receiver to communicate its window, but there is no corresponding
rule for the receiver, e.g. nothing says it is illegal for the receiver to
send credit when the sender's outgoing-window is zero, nor that the
receiver must compute it's incoming-window based on the sender's
outgoing-window,
I certainly agree that nothing ties the receivers incoming window to the
senders outgoing window in any fixed way.
so there is no obligation similarly implied for the sender.
I disagree here. I think the fact that begin and flow have the
outgoing-window field defined as mandatory, and the fact that there is
specific (though bewildering) language that appears to mandate the
tracking of the senders outgoing window by the receiver, *implies*
(though does not explicitly spell out) that the sender is supposed to
keep the receiver informed of its outgoing window.
Further I think the sender should not take the lack of credit as grounds
to set a window of 0. The receiver knows it has not issued credit. (At the
link level, the sender can also indicate that it has messages awaiting link
credit).
I agree that we shouldn't do this in our implementation, however I think it
is a valid interpretation,
The flow frame describes the outgoing window field as defining:
the maximum number of outgoing transfer frames that the
endpoint could potentially currently send, if it was not
constrained by restrictions imposed by its peer’s
incoming-window.
To me that explicitly states that the value of the senders outgoing
window is not tied to the value of the receivers incoming window, i.e.
that a value of 0 for the senders outgoing window cannot reasonably be
interpreted as an expectation for the receiver to open its incoming window.
I don't see a single sentence that would tie the session outgoing window
to link level credit, which is an entirely distinct mechanism.
The one thing the spec does say of the remote-outgoing-window is that
"settling outstanding transfers can cause the window to grow". Settling
deliveries frees the sender from needing to track them which clearly
*might* enable a constrained sender to then send some more. Likewise a
received outcome might allow the sender to make room for further
transfers (though this isn't stated anywhere I can see it would seem a
reasonable interpretation).
which implies that making the incoming window
dependent on your peers outgoing window (as service-bus is doing) is
probably not a safe thing to do.
Tying the incoming window to the peers outgoing window can only make
sense if the sender is expected to keep the receiver up to date with
regards to the value of the outgoing window. If that is not the case,
then I can't see that the receiver can deduce anything from the outgoing
window except that possibly a value of 0 may be a hint that the sender
is held up pending some undefined action on the receiver part.
Even if the sender was required to keep the receiver informed of the
outgoing window, having the receivers incoming window set to the
outgoing window of the sender is not terribly sensible in my view unless
the receiver would exapnd its incoming window if/when the sender
expanded its outgoing window. But doing that would essentially negate
the whole purpose of flow control anyway (i.e. a means for the receiver
to protect itself from excessive incoming traffic).
In the case where the sender's implementation involves a fixed amount of
buffer space and requires messages to be settled before it can send more,
the receiver would not be able to know that without getting some signal. So
to my mind that is the only case for which it would make sense to send an
outgoing window of 0. (I'm not sure how useful this is in practice and I
don't believe it applies to proton at present anyway).
I think as it stands proton is violating the spec, and should be changed
to send a non-zero outgoing window.
Per above I don't believe it is violating the spec, but given that it has
been misinterpreted at least once, I certainly agree that some behavior
change is warranted. I don't think we should do the max-frame-size thing
though as this encourages the notion that the incoming-window is somehow
dependent on the outgoing-window which as I said above is I think unsafe.
I guess setting it to a large constant for now is fairly reasonable, but I
do think we should encourage service-bus to make its implementation more
robust in this regard.
Under your interpretation - i.e. where the sender can change the value
of the outgoing window without ever having to inform the receiver - the
outgoing window seems to have very little value except as a hint that
the sender may be constrained by capacity limits on the number of
deliveries/transfers it is tracking. To send an outgoing window of 0
when there have not yet even been any transfers seems to undermine even
that limited value.
If there is no required behaviour actually specified, and the intention
was to use the outgoing window as a hint of constraints on the sender
then sending 0 is the worst possible choice. Whatever the value, it is
not something the peer can rely on in anyway and using 0 when there are
no constraints seems to ignore even the apparent intent.
So yes, my advice to service-bus and anyone else would be to ignore the
value. I think the question then is simply what is the least dangerous
way to set the mandated field for an implementation that wishes to avoid
interop problems. I think some very large fixed window is the best bet.
(I'm not sure I understand what the 'max-frame-size thing' is).