- From: Adam Bergkvist <adam.bergkvist@ericsson.com>
- Date: Thu, 20 Jun 2013 10:48:26 +0200
- To: Jan-Ivar Bruaroey <jib@mozilla.com>
- CC: "public-webrtc@w3.org" <public-webrtc@w3.org>
On 2013-06-19 18:19, Jan-Ivar Bruaroey wrote: > 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. I fully agree with your description of the classical approach with states; the transition to the "target state" happens when the operation succeeds. But "transition states", used when an async operation needs to complete before the "target state" can be set, isn't a new thing. See WebSocket's CONNECTING and CLOSING states and EventSource's CONNECTING state. >>> // 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. > The full state machine would look something like you describe. I would remove the "have" from the transition states though ("processing-have-local-offer" -> "processing-local-offer"). I don't think it gets more complicated; it gets more complete. The transition states sits nicely between our current states in the diagram. I think this discloses what really happens instead of the PeerConnection being in "stable" state and having some operations on a queue that possibly might change the state and the target state is dependent on which operations that are on the queue and the outcome of these. /Adam > [1] Our diagram > http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcpeerstate-enum
Received on Thursday, 20 June 2013 08:48:54 UTC