6
6
7
7
#include < atomic>
8
8
#include < chrono>
9
+ #include < condition_variable>
9
10
#include < ixcobra/IXCobraConnection.h>
10
11
#include < spdlog/spdlog.h>
11
12
#include < sstream>
16
17
#include < statsd_client.h>
17
18
#endif
18
19
20
+ namespace
21
+ {
22
+ class QueueManager
23
+ {
24
+ public:
25
+ QueueManager (size_t maxQueueSize,
26
+ std::atomic<bool > &stop) :
27
+ _maxQueueSize (maxQueueSize),
28
+ _stop (stop) {}
29
+
30
+ Json::Value pop ();
31
+ void add (Json::Value msg);
32
+
33
+ private:
34
+ std::queue<Json::Value> _queue;
35
+ std::mutex _mutex;
36
+ std::condition_variable _condition;
37
+ size_t _maxQueueSize;
38
+ std::atomic<bool >& _stop;
39
+ };
40
+
41
+ Json::Value QueueManager::pop ()
42
+ {
43
+ std::unique_lock<std::mutex> lock (_mutex);
44
+
45
+ if (_queue.empty ())
46
+ {
47
+ Json::Value val;
48
+ return val;
49
+ }
50
+
51
+ _condition.wait (lock, [this ] { return !_stop; });
52
+
53
+ auto msg = _queue.front ();
54
+ _queue.pop ();
55
+ return msg;
56
+ }
57
+
58
+ void QueueManager::add (Json::Value msg)
59
+ {
60
+ std::unique_lock<std::mutex> lock (_mutex);
61
+
62
+ // if the sending is not fast enough there is no point
63
+ // in queuing too many events.
64
+ if (_queue.size () < _maxQueueSize)
65
+ {
66
+ _queue.push (msg);
67
+ _condition.notify_one ();
68
+ }
69
+ }
70
+ }
71
+
19
72
namespace ix
20
73
{
21
74
// fields are command line argument that can be specified multiple times
@@ -79,27 +132,72 @@ namespace ix
79
132
80
133
auto tokens = parseFields (fields);
81
134
82
- // statsd client
83
- // test with netcat as a server: `nc -ul 8125`
84
- bool statsdBatch = true ;
85
- #ifndef _WIN32
86
- statsd::StatsdClient statsdClient (host, port, prefix, statsdBatch);
135
+ Json::FastWriter jsonWriter;
136
+ std::atomic<uint64_t > sentCount (0 );
137
+ std::atomic<uint64_t > receivedCount (0 );
138
+ std::atomic<bool > stop (false );
139
+
140
+ size_t maxQueueSize = 1000 ;
141
+ QueueManager queueManager (maxQueueSize, stop);
142
+
143
+ auto timer = [&sentCount, &receivedCount] {
144
+ while (true )
145
+ {
146
+ spdlog::info (" messages received {} sent {}" , receivedCount, sentCount);
147
+
148
+ auto duration = std::chrono::seconds (1 );
149
+ std::this_thread::sleep_for (duration);
150
+ }
151
+ };
152
+
153
+ std::thread t1 (timer);
154
+
155
+ auto statsdSender = [&queueManager,
156
+ &host,
157
+ &port,
158
+ &sentCount,
159
+ &tokens,
160
+ &prefix,
161
+ &stop] {
162
+ // statsd client
163
+ // test with netcat as a server: `nc -ul 8125`
164
+ bool statsdBatch = true ;
165
+ #ifndef _WIN32
166
+ statsd::StatsdClient statsdClient (host, port, prefix, statsdBatch);
87
167
#else
88
- int statsdClient;
168
+ int statsdClient;
89
169
#endif
170
+ while (true )
171
+ {
172
+ Json::Value msg = queueManager.pop ();
90
173
91
- Json::FastWriter jsonWriter;
92
- uint64_t msgCount = 0 ;
174
+ if (msg.isNull ()) continue ;
175
+ if (stop) return ;
176
+
177
+ std::string id;
178
+ for (auto && attr : tokens)
179
+ {
180
+ id += " ." ;
181
+ id += extractAttr (attr, msg);
182
+ }
183
+
184
+ sentCount += 1 ;
185
+
186
+ #ifndef _WIN32
187
+ statsdClient.count (id, 1 );
188
+ #endif
189
+ }
190
+ };
191
+
192
+ std::thread t2 (statsdSender);
93
193
94
194
conn.setEventCallback ([&conn,
95
195
&channel,
96
196
&filter,
97
197
&jsonWriter,
98
- &statsdClient,
99
198
verbose,
100
- &tokens,
101
- &prefix,
102
- &msgCount](ix::CobraConnectionEventType eventType,
199
+ &queueManager,
200
+ &receivedCount](ix::CobraConnectionEventType eventType,
103
201
const std::string& errMsg,
104
202
const ix::WebSocketHttpHeaders& headers,
105
203
const std::string& subscriptionId,
@@ -122,25 +220,17 @@ namespace ix
122
220
spdlog::info (" Subscriber authenticated" );
123
221
conn.subscribe (channel,
124
222
filter,
125
- [&jsonWriter, &statsdClient , verbose, &tokens, &prefix, &msgCount ](
223
+ [&jsonWriter, &queueManager , verbose, &receivedCount ](
126
224
const Json::Value& msg) {
127
225
if (verbose)
128
226
{
129
227
spdlog::info (jsonWriter.write (msg));
130
228
}
131
229
132
- std::string id;
133
- for (auto && attr : tokens)
134
- {
135
- id += " ." ;
136
- id += extractAttr (attr, msg);
137
- }
138
-
139
- spdlog::info (" {} {}{}" , msgCount++, prefix, id);
230
+ receivedCount++;
140
231
141
- #ifndef _WIN32
142
- statsdClient.count (id, 1 );
143
- #endif
232
+ ++receivedCount;
233
+ queueManager.add (msg);
144
234
});
145
235
}
146
236
else if (eventType == ix::CobraConnection_EventType_Subscribed)
0 commit comments