forked from livehelpnow/CSharpPhoenixClient
/
Push.cs
149 lines (127 loc) · 3.88 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
using System;
using System.Collections.Generic;
using System.Linq;
using WebSocketSharp;
using System.Timers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace PhoenixChannels
{
public class RecHook
{
public string Status { get; set; }
public Action<JObject> Callback { get; set; }
}
public class AfterHook
{
public int Ms { get; set; }
public Action Callback { get; set; }
public Timer Timer { get; set; }
}
public class Push
{
private Channel _channel;
private string _event;
private JObject _payload;
private JObject _receivedResp;
private AfterHook _afterHook;
private List<RecHook> _recHooks;
private bool _sent;
private string _ref;
private string _refEvent;
public Push(Channel channel, string event_, JObject payload)
{
_channel = channel;
_event = event_;
_payload = payload;
_receivedResp = null;
_afterHook = null;
_recHooks = new List<RecHook>();
_sent = false;
}
public void Send()
{
_ref = _channel.Socket.MakeRef();
_refEvent = _channel.ReplyEventName(_ref);
_receivedResp = null;
_sent = false;
_channel.On(_refEvent, (payload, reference) =>
{
_receivedResp = payload;
MatchReceive(payload);
CancelRefEvent();
CancelAfter();
});
StartAfter();
_sent = true;
var env = new Envelope()
{
Topic = _channel.Topic,
Event = _event,
Payload = _payload,
Ref = _ref,
};
_channel.Socket.Push(env);
}
public Push Receive(string status, Action<JObject> callback)
{
if (_receivedResp != null && (string)_receivedResp["status"] == status)
{
callback((JObject)_receivedResp["response"]);
}
_recHooks.Add(new RecHook() { Status = status, Callback = callback });
return this;
}
public Push After(int timeoutMs, Action callback)
{
if (_afterHook != null)
{
//throw
throw new Exception("only a single after hook can be applied to a push");
}
var timer = new Timer(timeoutMs);
if (_sent)
{
timer.Elapsed += (o, e) => callback();
timer.AutoReset = false;
timer.Start();//.Enabled = true;
}
_afterHook = new AfterHook{ Ms = timeoutMs, Callback = callback, Timer = timer };
return this;
}
//// private
private void MatchReceive(JObject payload) //string status, object response, int reference)
{
foreach (var rh in _recHooks)
{
if (rh.Status == (string)payload["status"])
{
rh.Callback((JObject)payload["response"]);
}
}
}
private void CancelRefEvent()
{
_channel.Off(_refEvent);
}
private void CancelAfter()
{
if (_afterHook == null) return;
//reset timer
_afterHook.Timer.Stop();
//_afterHook.Timer.Enabled = false;
_afterHook.Timer = null;
}
private void StartAfter()
{
if (_afterHook == null) return;
Action callback = () =>
{
CancelRefEvent();
_afterHook.Callback();
};
_afterHook.Timer = new Timer(_afterHook.Ms);
_afterHook.Timer.Elapsed += (o, e) => callback();
}
}
}