private void TriggerClose() { socket.Log(LogLevel.Debug, "channel", string.Format("close {0}", topic)); state = State.Closed; socket.Remove(this); }
//constructor(topic, params, socket) { // this.state = CHANNEL_STATES.closed // this.topic = topic // this.params = params || {} // this.socket = socket // this.bindings = [] // this.timeout = this.socket.timeout // this.joinedOnce = false // this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout) // this.pushBuffer = [] // this.rejoinTimer = new Timer( // () => this.rejoinUntilConnected(), // this.socket.reconnectAfterMs // ) // this.joinPush.receive("ok", () => { // this.state = CHANNEL_STATES.joined // this.rejoinTimer.reset() // this.pushBuffer.forEach( pushEvent => pushEvent.send() ) // this.pushBuffer = [] // }) // this.onClose( () => { // this.socket.log("channel", `close ${this.topic}`) // this.state = CHANNEL_STATES.closed // this.socket.remove(this) // }) // this.onError( reason => { // this.socket.log("channel", `error ${this.topic}`, reason) // this.state = CHANNEL_STATES.errored // this.rejoinTimer.setTimeout() // }) // this.joinPush.receive("timeout", () => { // if(this.state !== CHANNEL_STATES.joining){ return } // this.socket.log("channel", `timeout ${this.topic}`, this.joinPush.timeout) // this.state = CHANNEL_STATES.errored // this.rejoinTimer.setTimeout() // }) // this.on(CHANNEL_EVENTS.reply, (payload, ref) => { // this.trigger(this.replyEventName(ref), payload) // }) //} public Channel(string topic, JObject params_, Socket socket) { _state = ChannelState.Closed; _topic = topic; _params = params_ ?? Phoenix.EMPTY_JS_OBJECT; _socket = socket; _bindings = new List<Binding>(); _timeout = _socket.Timeout; _joinedOnce = false; _joinPush = new Push(this, Phoenix.CHANNEL_EVENT_JOIN, _params, _timeout); _pushBuffer = new List<Push>(); _rejoinTimer = new RetryTimer(RejoinUntilConnected, _socket.ReconnectAfterMs); //jfis - why another timer instead of waiting for socket event? _joinPush.Receive("ok", (_) => { _socket.Log("JP REC OK", ""); _state = ChannelState.Joined; _rejoinTimer.Reset(); foreach (var p in _pushBuffer) p.Send(); _pushBuffer.Clear(); } ); OnClose(() => { _socket.Log("channel", $"close {_topic}"); _state = ChannelState.Closed; _socket.Remove(this); }); OnError( () => //reason only used for logging { _socket.Log("channel", $"error {_topic}"); //, reason); _state = ChannelState.Errored; _rejoinTimer.SetTimeout(); } ); _joinPush.Receive("timeout", (_) => { if (_state == ChannelState.Joining) return; _socket.Log("channel", $"timeout {_topic}");//, _joinPush.timeout) _state = ChannelState.Errored; _rejoinTimer.SetTimeout(); } ); On(Phoenix.CHANNEL_EVENT_REPLY, OnReply); }
// TODO: possibly support lazy instantiation of payload (same as Phoenix js) public Channel(string topic, ParamsType @params, Socket socket) { Topic = topic; Socket = socket; _timeout = socket.Opts.Timeout; _joinPush = new Push( this, Message.OutBoundEvent.Join.Serialized(), () => @params, _timeout ); if (socket.Opts.RejoinAfter != null) { _rejoinTimer = new Scheduler( () => { if (socket.IsConnected()) { Rejoin(); } }, socket.Opts.RejoinAfter, socket.Opts.DelayedExecutor ); } socket.OnError += SocketOnError; socket.OnOpen += SocketOnOpen; _joinPush.Receive(ReplyStatus.Ok, message => { State = ChannelState.Joined; _rejoinTimer?.Reset(); _pushBuffer.ForEach(push => push.Send()); _pushBuffer.Clear(); }); _joinPush.Receive(ReplyStatus.Error, message => { State = ChannelState.Errored; if (socket.IsConnected()) { _rejoinTimer?.ScheduleTimeout(); } }); OnClose(message => { _rejoinTimer?.Reset(); if (socket.HasLogger()) { socket.Log(LogLevel.Debug, "channel", $"close {topic}"); } State = ChannelState.Closed; // PhoenixJS: See note in socket regarding this // basically, we unregister delegates directly in c# instead of offing an array // this.off(channel.stateChangeRefs) socket.OnError -= SocketOnError; socket.OnOpen -= SocketOnOpen; socket.Remove(this); }); OnError(message => { if (socket.HasLogger()) { socket.Log(LogLevel.Debug, "channel", $"error {topic}"); } if (IsJoining()) { _joinPush.Reset(); } State = ChannelState.Errored; if (socket.IsConnected()) { _rejoinTimer?.ScheduleTimeout(); } }); _joinPush.Receive(ReplyStatus.Timeout, message => { if (socket.HasLogger()) { socket.Log(LogLevel.Debug, "channel", $"timeout {topic} ({JoinRef})"); } var leaveEvent = Message.OutBoundEvent.Leave.Serialized(); var leavePush = new Push(this, leaveEvent, null, _timeout); leavePush.Send(); State = ChannelState.Errored; _joinPush.Reset(); if (socket.IsConnected()) { _rejoinTimer?.ScheduleTimeout(); } }); // on phx_reply, also trigger a message for the push using replyEventName On(Message.InBoundEvent.Reply.Serialized(), message => { message.Event = ReplyEventName(message.Ref); Trigger(message); }); }
//constructor(topic, params, socket) { // this.state = CHANNEL_STATES.closed // this.topic = topic // this.params = params || {} // this.socket = socket // this.bindings = [] // this.timeout = this.socket.timeout // this.joinedOnce = false // this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout) // this.pushBuffer = [] // this.rejoinTimer = new Timer( // () => this.rejoinUntilConnected(), // this.socket.reconnectAfterMs // ) // this.joinPush.receive("ok", () => { // this.state = CHANNEL_STATES.joined // this.rejoinTimer.reset() // this.pushBuffer.forEach( pushEvent => pushEvent.send() ) // this.pushBuffer = [] // }) // this.onClose( () => { // this.socket.log("channel", `close ${this.topic}`) // this.state = CHANNEL_STATES.closed // this.socket.remove(this) // }) // this.onError( reason => { // this.socket.log("channel", `error ${this.topic}`, reason) // this.state = CHANNEL_STATES.errored // this.rejoinTimer.setTimeout() // }) // this.joinPush.receive("timeout", () => { // if(this.state !== CHANNEL_STATES.joining){ return } // this.socket.log("channel", `timeout ${this.topic}`, this.joinPush.timeout) // this.state = CHANNEL_STATES.errored // this.rejoinTimer.setTimeout() // }) // this.on(CHANNEL_EVENTS.reply, (payload, ref) => { // this.trigger(this.replyEventName(ref), payload) // }) //} public Channel(string topic, JObject params_, Socket socket) { _state = ChannelState.Closed; _topic = topic; _params = params_ ?? Phoenix.EMPTY_JS_OBJECT; _socket = socket; _bindings = new List <Binding>(); _timeout = _socket.Timeout; _joinedOnce = false; _joinPush = new Push(this, Phoenix.CHANNEL_EVENT_JOIN, _params, _timeout); _pushBuffer = new List <Push>(); _rejoinTimer = new RetryTimer(RejoinUntilConnected, _socket.ReconnectAfterMs); //jfis - why another timer instead of waiting for socket event? _joinPush.Receive("ok", (_) => { _socket.Log("JP REC OK", ""); _state = ChannelState.Joined; _rejoinTimer.Reset(); foreach (var p in _pushBuffer) { p.Send(); } _pushBuffer.Clear(); } ); OnClose(() => { _socket.Log("channel", $"close {_topic}"); _state = ChannelState.Closed; _socket.Remove(this); }); OnError( () => //reason only used for logging { _socket.Log("channel", $"error {_topic}"); //, reason); _state = ChannelState.Errored; _rejoinTimer.SetTimeout(); } ); _joinPush.Receive("timeout", (_) => { if (_state == ChannelState.Joining) { return; } _socket.Log("channel", $"timeout {_topic}");//, _joinPush.timeout) _state = ChannelState.Errored; _rejoinTimer.SetTimeout(); } ); On(Phoenix.CHANNEL_EVENT_REPLY, OnReply); }