-
Notifications
You must be signed in to change notification settings - Fork 0
/
Push.cs
229 lines (194 loc) · 5.97 KB
/
Push.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
namespace Phoenix
{
public class Push
{
private class ReceiveHook
{
internal string Status { get; set; }
internal Action<JObject> Callback { get; set; }
}
//// Initializes the Push
////
//// channel - The Channel
//// event - The event, for example `"phx_join"`
//// payload - The payload, for example `{user_id: 123}`
//// timeout - The push timeout in milliseconds
////
//constructor(channel, event, payload, timeout){
// this.channel = channel
// this.event = event
// this.payload = payload || { }
// this.receivedResp = null
// this.timeout = timeout
// this.timeoutTimer = null
// this.recHooks = []
// this.sent = false
//}
private Channel _channel;
private string _event;
private JObject _payload;
private int _timeout;
private Timer _timeoutTimer;
private IList<ReceiveHook> _recHooks;
//private bool _sent; //FIX phoenix doesnt actually use this var
private JObject _receivedResp;
private string _ref;
private string _refEvent;
public Push(Channel channel, string event_, JObject payload, int timeout)
{ //jfis - things seem too tied together. do pushes really need to know which channel they belong to? do channels need to know socket?
_channel = channel;
_event = event_;
_payload = payload ?? Phoenix.EMPTY_JS_OBJECT;
_receivedResp = null;
_timeout = timeout;
_timeoutTimer = new Timer()
{
AutoReset = false,
Interval = _timeout
};
_timeoutTimer.Elapsed += (o, e) => Trigger("timeout", Phoenix.EMPTY_JS_OBJECT);
_recHooks = new List<ReceiveHook>();
//_sent = false;
}
//resend(timeout){
// this.timeout = timeout
// this.cancelRefEvent()
// this.ref = null
// this.refEvent = null
// this.receivedResp = null
// this.sent = false
// this.send()
//}
public void Resend(int timeout)
{
_channel.Socket.Log("push resend", _ref);
_timeout = timeout;
CancelRefEvent();
_ref = null;
_refEvent = null;
_receivedResp = null;
//_sent = false;
Send();
}
//send(){
// if(this.hasReceived("timeout")){ return }
// this.startTimeout()
// this.sent = true
// this.channel.socket.push({
// topic: this.channel.topic,
// event: this.event,
// payload: this.payload,
// ref: this.ref
// })
//}
public void Send()
{
_channel.Socket.Log("push send", _ref);
if (HasReceived("timeout")) return;
StartTimeout();
//_sent = true;
_channel.Socket.Log("push send", _ref);
var data = new JObject();
data["topic"] = _channel.Topic;
data["event"] = _event;
data["payload"] = _payload;
data["ref"] = _ref;
_channel.Socket.Push(data);
}
//receive(status, callback){
// if(this.hasReceived(status)){
// callback(this.receivedResp.response)
// }
// this.recHooks.push({status, callback})
// return this
//}
public Push Receive(string status, Action<JObject> callback)
{
if (HasReceived(status)) callback((JObject)_receivedResp["response"]);
_recHooks.Add(new ReceiveHook() { Status = status, Callback = callback });
return this;
}
//// private
//matchReceive({status, response, ref}){
// this.recHooks.filter( h => h.status === status )
// .forEach( h => h.callback(response) )
//}
private void MatchReceive(JObject json)
{
var status = (string)json["status"];
var response = (JObject)json["response"];
//var ref_ = json["ref"].ToString();
_recHooks
.Where((h) => h.Status == status)
.ToList()
.ForEach((h) => h.Callback(response));
}
//cancelRefEvent(){ if(!this.refEvent){ return }
// this.channel.off(this.refEvent)
//}
private void CancelRefEvent()
{
if (_refEvent == null) return;
_channel.Off(_refEvent);
}
//cancelTimeout(){
// clearTimeout(this.timeoutTimer)
// this.timeoutTimer = null
//}
private void CancelTimeout()
{
_timeoutTimer.Stop();
}
//startTimeout(){ if(this.timeoutTimer){ return }
// this.ref = this.channel.socket.makeRef()
// this.refEvent = this.channel.replyEventName(this.ref)
// this.channel.on(this.refEvent, payload => {
// this.cancelRefEvent()
// this.cancelTimeout()
// this.receivedResp = payload
// this.matchReceive(payload)
// })
// this.timeoutTimer = setTimeout(() => {
// this.trigger("timeout", {})
// }, this.timeout)
//}
internal void StartTimeout()
{
if (_timeoutTimer.Enabled) return; //jfis - dont do if timer running
_ref = _channel.Socket.MakeRef(); //jfis - get new ref
_refEvent = _channel.ReplyEventName(_ref); //jfis - ref as string
_channel.On(_refEvent, (payload, _) => //make binding for refEvent
{
CancelRefEvent();
CancelTimeout();
var json = (JObject)payload;
_receivedResp = json;
MatchReceive(json);
});
_timeoutTimer.Interval = _timeout;
_timeoutTimer.Start(); //start timeout timer, which triggers "timeout"
}
//hasReceived(status){
// return this.receivedResp && this.receivedResp.status === status
//}
private bool HasReceived(string status)
{
return (_receivedResp != null) && (string)_receivedResp["status"] == status;
}
//trigger(status, response){
// this.channel.trigger(this.refEvent, {status, response})
//}
internal void Trigger(string status, JObject response)
{
var data = new JObject();
data["status"] = status;
data["response"] = response;
_channel.Trigger(_refEvent, data);
}
}
}