digraph { /* note: this is nominally what we want from the machine that establishes the WebSocket connection (and re-establishes it when it is lost). We aren't using this yet; for now we're relying upon twisted.application.internet.ClientService, which does reconnection and random exponential backoff. The one thing it doesn't do is fail entirely when the first connection attempt fails, which I think would be good for usability. If the first attempt fails, it's probably because you don't have a network connection, or the hostname is wrong, or the service has been retired entirely. And retrying silently forever is not being honest with the user. So I'm keeping this diagram around, as a reminder of how we'd like to modify ClientService. */ /* ConnectionMachine */ C_start [label="Connection\nMachine" style="dotted"] C_start -> C_Pc1 [label="CM_start()" color="orange" fontcolor="orange"] C_Pc1 [shape="box" label="ep.connect()" color="orange"] C_Pc1 -> C_Sc1 [color="orange"] C_Sc1 [label="connecting\n(1st time)" color="orange"] C_Sc1 -> C_P_reset [label="d.callback" color="orange" fontcolor="orange"] C_P_reset [shape="box" label="reset\ntimer" color="orange"] C_P_reset -> C_S_negotiating [color="orange"] C_Sc1 -> C_P_failed [label="d.errback" color="red"] C_Sc1 -> C_P_failed [label="p.onClose" color="red"] C_Sc1 -> C_P_cancel [label="C_stop()"] C_P_cancel [shape="box" label="d.cancel()"] C_P_cancel -> C_S_cancelling C_S_cancelling [label="cancelling"] C_S_cancelling -> C_P_stopped [label="d.errback"] C_S_negotiating [label="negotiating" color="orange"] C_S_negotiating -> C_P_failed [label="p.onClose"] C_S_negotiating -> C_P_connected [label="p.onOpen" color="orange" fontcolor="orange"] C_S_negotiating -> C_P_drop2 [label="C_stop()"] C_P_drop2 [shape="box" label="p.dropConnection()"] C_P_drop2 -> C_S_disconnecting C_P_connected [shape="box" label="tx bind\nM_connected()" color="orange"] C_P_connected -> C_S_open [color="orange"] C_S_open [label="open" color="green"] C_S_open -> C_P_lost [label="p.onClose" color="blue" fontcolor="blue"] C_S_open -> C_P_drop [label="C_stop()" color="orange" fontcolor="orange"] C_P_drop [shape="box" label="p.dropConnection()\nM_lost()" color="orange"] C_P_drop -> C_S_disconnecting [color="orange"] C_S_disconnecting [label="disconnecting" color="orange"] C_S_disconnecting -> C_P_stopped [label="p.onClose" color="orange" fontcolor="orange"] C_P_lost [shape="box" label="M_lost()" color="blue"] C_P_lost -> C_P_wait [color="blue"] C_P_wait [shape="box" label="start timer" color="blue"] C_P_wait -> C_S_waiting [color="blue"] C_S_waiting [label="waiting" color="blue"] C_S_waiting -> C_Pc2 [label="expire" color="blue" fontcolor="blue"] C_S_waiting -> C_P_stop_timer [label="C_stop()"] C_P_stop_timer [shape="box" label="timer.cancel()"] C_P_stop_timer -> C_P_stopped C_Pc2 [shape="box" label="ep.connect()" color="blue"] C_Pc2 -> C_Sc2 [color="blue"] C_Sc2 [label="reconnecting" color="blue"] C_Sc2 -> C_P_reset [label="d.callback" color="blue" fontcolor="blue"] C_Sc2 -> C_P_wait [label="d.errback"] C_Sc2 -> C_P_cancel [label="C_stop()"] C_P_stopped [shape="box" label="MC_stopped()" color="orange"] C_P_stopped -> C_S_stopped [color="orange"] C_S_stopped [label="stopped" color="orange"] C_P_failed [shape="box" label="notify_fail" color="red"] C_P_failed -> C_S_failed C_S_failed [label="failed" color="red"] }