예제 #1
0
        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);
        }
예제 #2
0
        // 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);
            });
        }