// 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);
});
}