public Push Leave(TimeSpan?timeout = null) { _rejoinTimer?.Reset(); _joinPush.CancelTimeout(); State = ChannelState.Leaving; void TriggerClose() { if (Socket.HasLogger()) { Socket.Log(LogLevel.Debug, "channel", $"leave {Topic}"); } Trigger(Message.InBoundEvent.Close); } var leaveEvent = Message.OutBoundEvent.Leave.Serialized(); var leavePush = new Push(this, leaveEvent, null, timeout ?? _timeout); leavePush .Receive(ReplyStatus.Ok, _ => TriggerClose()) .Receive(ReplyStatus.Timeout, _ => TriggerClose()); leavePush.Send(); if (!CanPush()) { leavePush.Trigger(ReplyStatus.Ok); } return(leavePush); }
// 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); }); }