W3C home > Mailing lists > Public > public-webrtc@w3.org > June 2013

Re: Operations in invalid states: Exceptions don't make sense.

From: Jan-Ivar Bruaroey <jib@mozilla.com>
Date: Wed, 19 Jun 2013 12:19:06 -0400
Message-ID: <51C1D9FA.9060203@mozilla.com>
To: public-webrtc@w3.org
On 6/19/13 2:47 AM, Adam Bergkvist wrote:
> On 2013-06-18 23:02, Jan-Ivar Bruaroey wrote:
>> I can think of no cases, thankfully. My understanding is that the queue
>> is there to make the API deterministic, rather than encourage enqueuing.
>> E.g.:
>
> Thank you for clarifying this. But is this new approach any easier 
> than classical states?

We may disagree on the classifications "new" and "classical" here. We 
have a state machine affected by operations that may fail. The classical 
approach, to me, is to transition state not until operational steps 
succeed, to preserve a sane state transition diagram. [1] - This means 
that, since our operations are asynchronous, state must transition at 
the completion of our async calls, not at the beginning.

Introducing additional state(s) at the beginning (lets call it "the time 
of intention"), as you're suggesting, I would call new.

>>      // Bad code. state=have_local_offer
>>      pc.setRemoteDescription(answer1, success, mayfail);
>>      pc.setRemoteDescription(answer2, success, mayfail);
>>
>> Without a queue, the second call could succeed or fail based on whether
>> the first call has completed.  With a queue in place it becomes
>> deterministic: If call 1 succeeds, then call 2 always fails
>> (state=stable). If call 1 fails, then call 2 has the same starting point
>> (state=have_local_offer), always.
>>
>> Why care? Non-deterministic behavior would be bad for
>> documentation-reasons alone (having to mention useless edge-cases like
>> this).
>>
>
> With a processing state, the second call would always fail. That's 
> deterministic and observable from JS (compared to a queue in the 
> background).
>
>>> Wouldn't it be simpler to have a model where the PeerConnection enters
>>> a "processing" state when, for example, setLocalDescription() is
>>> called, and the state is updated in the task that fires the methods
>>> success or error callback? The "single operation at a time" rule would
>>> then be enforced by the PeerConnection signaling state.
>>
>> Yes, we could have done that. It would let you throw on bad state, but
>> at the cost of doubling the number of states in the state machine. I'm
>> not sure it is simpler.
>>
>
> A single processing state would be enough to start with, and it could 
> be expanded if developers asked for more.

You want to do this for every operation, right? Then I think you mean a 
flag, i.e. a doubling of states effectively. Otherwise, please draw me 
the new state transition diagram.

If you change state at the "time of intention", then you have to handle 
backing out to the previous state if/when the operation fails. With only 
a single "processing" state there's not enough info in the state model 
itself to know the previous state, so that's not a state. And 
signalingstatechange returning "processing" isn't very informative.

I believe you effectively have this in your suggestion:

enum RTCSignalingState {
     "processing-stable",
     "stable",
     "processing-have-local-offer",
     "have-local-offer",
     "processing-have-remote-offer",
     "have-remote-offer",
     "processing-have-local-pranswer",
     "have-local-pranswer",
     "processing-have-remote-pranswer",
     "have-remote-pranswer",
     "processing-closed",
     "closed"
};

That doesn't seem simpler to me.

[1] Our diagram 
http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcpeerstate-enum

.: Jan-Ivar :.

>
> /Adam
>
Received on Wednesday, 19 June 2013 16:19:37 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 15:19:33 UTC