(cobra bots) do not use a queue to store messages pending processing, let the bot handle queuing
This commit is contained in:
@ -6,7 +6,6 @@
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
|
||||
#include "IXQueueManager.h"
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
|
||||
@ -23,8 +22,6 @@ namespace ix
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool useQueue,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
@ -43,8 +40,6 @@ namespace ix
|
||||
std::atomic<bool> throttled(false);
|
||||
std::atomic<bool> fatalCobraError(false);
|
||||
|
||||
QueueManager queueManager(maxQueueSize);
|
||||
|
||||
auto timer = [&sentCount,
|
||||
&receivedCount,
|
||||
&sentCountTotal,
|
||||
@ -114,40 +109,6 @@ namespace ix
|
||||
|
||||
std::thread t2(heartbeat);
|
||||
|
||||
auto sender =
|
||||
[this, &queueManager, verbose, &sentCount, &stop, &throttled, &fatalCobraError] {
|
||||
while (true)
|
||||
{
|
||||
auto data = queueManager.pop();
|
||||
Json::Value msg = data.first;
|
||||
std::string position = data.second;
|
||||
|
||||
if (stop) break;
|
||||
if (msg.isNull()) continue;
|
||||
|
||||
if (_onBotMessageCallback &&
|
||||
_onBotMessageCallback(msg, position, verbose, throttled, fatalCobraError))
|
||||
{
|
||||
// That might be too noisy
|
||||
if (verbose)
|
||||
{
|
||||
CoreLogger::info("cobra bot: sending succesfull");
|
||||
}
|
||||
++sentCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreLogger::error("cobra bot: error sending");
|
||||
}
|
||||
|
||||
if (stop) break;
|
||||
}
|
||||
|
||||
CoreLogger::info("sender thread done");
|
||||
};
|
||||
|
||||
std::thread t3(sender);
|
||||
|
||||
std::string subscriptionPosition(position);
|
||||
|
||||
conn.setEventCallback([this,
|
||||
@ -160,8 +121,6 @@ namespace ix
|
||||
&throttled,
|
||||
&receivedCount,
|
||||
&fatalCobraError,
|
||||
&useQueue,
|
||||
&queueManager,
|
||||
&sentCount](const CobraEventPtr& event) {
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
{
|
||||
@ -190,8 +149,6 @@ namespace ix
|
||||
verbose,
|
||||
&throttled,
|
||||
&receivedCount,
|
||||
&queueManager,
|
||||
&useQueue,
|
||||
&subscriptionPosition,
|
||||
&fatalCobraError,
|
||||
&sentCount](const Json::Value& msg, const std::string& position) {
|
||||
@ -211,28 +168,9 @@ namespace ix
|
||||
|
||||
++receivedCount;
|
||||
|
||||
if (useQueue)
|
||||
{
|
||||
queueManager.add(msg, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_onBotMessageCallback &&
|
||||
_onBotMessageCallback(
|
||||
msg, position, verbose, throttled, fatalCobraError))
|
||||
{
|
||||
// That might be too noisy
|
||||
if (verbose)
|
||||
{
|
||||
CoreLogger::info("cobra bot: sending succesfull");
|
||||
}
|
||||
++sentCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreLogger::error("cobra bot: error sending");
|
||||
}
|
||||
}
|
||||
_onBotMessageCallback(
|
||||
msg, position, verbose,
|
||||
throttled, fatalCobraError, sentCount);
|
||||
});
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Subscribed)
|
||||
@ -308,9 +246,6 @@ namespace ix
|
||||
// heartbeat thread
|
||||
if (t2.joinable()) t2.join();
|
||||
|
||||
// sentry sender thread
|
||||
t3.join();
|
||||
|
||||
return fatalCobraError ? -1 : (int64_t) sentCount;
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,12 @@
|
||||
|
||||
namespace ix
|
||||
{
|
||||
using OnBotMessageCallback = std::function<bool(const Json::Value&,
|
||||
using OnBotMessageCallback = std::function<void(const Json::Value&,
|
||||
const std::string&,
|
||||
const bool verbose,
|
||||
std::atomic<bool>&,
|
||||
std::atomic<bool>&)>;
|
||||
std::atomic<bool>&,
|
||||
std::atomic<uint64_t>&)>;
|
||||
|
||||
class CobraBot
|
||||
{
|
||||
@ -30,8 +31,6 @@ namespace ix
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool useQueue,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "IXCobraToSentryBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
|
||||
@ -23,7 +22,6 @@ namespace ix
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
@ -32,85 +30,80 @@ namespace ix
|
||||
const std::string& /*position*/,
|
||||
const bool verbose,
|
||||
std::atomic<bool>& throttled,
|
||||
std::atomic<bool> &
|
||||
/*fatalCobraError*/) -> bool {
|
||||
auto ret = sentryClient.send(msg, verbose);
|
||||
HttpResponsePtr response = ret.first;
|
||||
|
||||
if (!response)
|
||||
{
|
||||
CoreLogger::warn("Null HTTP Response");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
for (auto it : response->headers)
|
||||
std::atomic<bool>& /*fatalCobraError*/,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
sentryClient.send(msg, verbose,
|
||||
[&sentCount, &throttled, &verbose](const HttpResponsePtr& response) {
|
||||
if (!response)
|
||||
{
|
||||
CoreLogger::info(it.first + ": " + it.second);
|
||||
CoreLogger::warn("Null HTTP Response");
|
||||
return;
|
||||
}
|
||||
|
||||
CoreLogger::info("Upload size: " + std::to_string(response->uploadSize));
|
||||
CoreLogger::info("Download size: " + std::to_string(response->downloadSize));
|
||||
|
||||
CoreLogger::info("Status: " + std::to_string(response->statusCode));
|
||||
if (response->errorCode != HttpErrorCode::Ok)
|
||||
if (verbose)
|
||||
{
|
||||
CoreLogger::info("error message: " + response->errorMsg);
|
||||
}
|
||||
|
||||
if (response->headers["Content-Type"] != "application/octet-stream")
|
||||
{
|
||||
CoreLogger::info("payload: " + response->payload);
|
||||
}
|
||||
}
|
||||
|
||||
bool success = response->statusCode == 200;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
CoreLogger::error("Error sending data to sentry: " + std::to_string(response->statusCode));
|
||||
CoreLogger::error("Body: " + ret.second);
|
||||
CoreLogger::error("Response: " + response->payload);
|
||||
|
||||
// Error 429 Too Many Requests
|
||||
if (response->statusCode == 429)
|
||||
{
|
||||
auto retryAfter = response->headers["Retry-After"];
|
||||
std::stringstream ss;
|
||||
ss << retryAfter;
|
||||
int seconds;
|
||||
ss >> seconds;
|
||||
|
||||
if (!ss.eof() || ss.fail())
|
||||
for (auto it : response->headers)
|
||||
{
|
||||
seconds = 30;
|
||||
CoreLogger::warn("Error parsing Retry-After header. "
|
||||
"Using " + retryAfter + " for the sleep duration");
|
||||
CoreLogger::info(it.first + ": " + it.second);
|
||||
}
|
||||
|
||||
CoreLogger::warn("Error 429 - Too Many Requests. ws will sleep "
|
||||
"and retry after " + retryAfter + " seconds");
|
||||
CoreLogger::info("Upload size: " + std::to_string(response->uploadSize));
|
||||
CoreLogger::info("Download size: " + std::to_string(response->downloadSize));
|
||||
|
||||
throttled = true;
|
||||
auto duration = std::chrono::seconds(seconds);
|
||||
std::this_thread::sleep_for(duration);
|
||||
throttled = false;
|
||||
CoreLogger::info("Status: " + std::to_string(response->statusCode));
|
||||
if (response->errorCode != HttpErrorCode::Ok)
|
||||
{
|
||||
CoreLogger::info("error message: " + response->errorMsg);
|
||||
}
|
||||
|
||||
if (response->headers["Content-Type"] != "application/octet-stream")
|
||||
{
|
||||
CoreLogger::info("payload: " + response->payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
if (response->statusCode == 200)
|
||||
{
|
||||
sentCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreLogger::error("Error sending data to sentry: " + std::to_string(response->statusCode));
|
||||
CoreLogger::error("Response: " + response->payload);
|
||||
|
||||
// Error 429 Too Many Requests
|
||||
if (response->statusCode == 429)
|
||||
{
|
||||
auto retryAfter = response->headers["Retry-After"];
|
||||
std::stringstream ss;
|
||||
ss << retryAfter;
|
||||
int seconds;
|
||||
ss >> seconds;
|
||||
|
||||
if (!ss.eof() || ss.fail())
|
||||
{
|
||||
seconds = 30;
|
||||
CoreLogger::warn("Error parsing Retry-After header. "
|
||||
"Using " + retryAfter + " for the sleep duration");
|
||||
}
|
||||
|
||||
CoreLogger::warn("Error 429 - Too Many Requests. ws will sleep "
|
||||
"and retry after " + retryAfter + " seconds");
|
||||
|
||||
throttled = true;
|
||||
auto duration = std::chrono::seconds(seconds);
|
||||
std::this_thread::sleep_for(duration);
|
||||
throttled = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
bool useQueue = true;
|
||||
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ namespace ix
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "IXCobraToStatsdBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include "IXStatsdClient.h"
|
||||
#include <chrono>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
@ -63,7 +62,6 @@ namespace ix
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
@ -79,7 +77,8 @@ namespace ix
|
||||
const std::string& /*position*/,
|
||||
const bool verbose,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool>& fatalCobraError) -> bool {
|
||||
std::atomic<bool>& fatalCobraError,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
std::string id;
|
||||
for (auto&& attr : tokens)
|
||||
{
|
||||
@ -122,7 +121,7 @@ namespace ix
|
||||
{
|
||||
CoreLogger::error("Gauge " + gauge + " is not a numeric type");
|
||||
fatalCobraError = true;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
@ -140,18 +139,14 @@ namespace ix
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
sentCount++;
|
||||
});
|
||||
|
||||
bool useQueue = true;
|
||||
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ namespace ix
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "IXCobraToStdoutBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -71,7 +70,6 @@ namespace ix
|
||||
bool fluentd,
|
||||
bool quiet,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
@ -83,24 +81,20 @@ namespace ix
|
||||
const std::string& position,
|
||||
const bool /*verbose*/,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool> &
|
||||
/*fatalCobraError*/) -> bool {
|
||||
std::atomic<bool>& /*fatalCobraError*/,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
if (!quiet)
|
||||
{
|
||||
writeToStdout(fluentd, jsonWriter, msg, position);
|
||||
}
|
||||
return true;
|
||||
sentCount++;
|
||||
});
|
||||
|
||||
bool useQueue = false;
|
||||
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ namespace ix
|
||||
bool fluentd,
|
||||
bool quiet,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* IXQueueManager.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXQueueManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
std::pair<Json::Value, std::string> QueueManager::pop()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
|
||||
if (_queues.empty())
|
||||
{
|
||||
Json::Value val;
|
||||
return std::make_pair(val, std::string());
|
||||
}
|
||||
|
||||
std::vector<std::string> games;
|
||||
for (auto it : _queues)
|
||||
{
|
||||
games.push_back(it.first);
|
||||
}
|
||||
|
||||
std::random_shuffle(games.begin(), games.end());
|
||||
std::string game = games[0];
|
||||
|
||||
auto duration = std::chrono::seconds(1);
|
||||
_condition.wait_for(lock, duration);
|
||||
|
||||
if (_queues[game].empty())
|
||||
{
|
||||
Json::Value val;
|
||||
return std::make_pair(val, std::string());
|
||||
}
|
||||
|
||||
auto msg = _queues[game].front();
|
||||
_queues[game].pop();
|
||||
return msg;
|
||||
}
|
||||
|
||||
void QueueManager::add(const Json::Value& msg, const std::string& position)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
|
||||
std::string game;
|
||||
if (msg.isMember("device") && msg["device"].isMember("game"))
|
||||
{
|
||||
game = msg["device"]["game"].asString();
|
||||
}
|
||||
|
||||
if (game.empty()) return;
|
||||
|
||||
// if the sending is not fast enough there is no point
|
||||
// in queuing too many events.
|
||||
if (_queues[game].size() < _maxQueueSize)
|
||||
{
|
||||
_queues[game].push(std::make_pair(msg, position));
|
||||
_condition.notify_one();
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* IXQueueManager.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <json/json.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class QueueManager
|
||||
{
|
||||
public:
|
||||
QueueManager(size_t maxQueueSize)
|
||||
: _maxQueueSize(maxQueueSize)
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<Json::Value, std::string> pop();
|
||||
void add(const Json::Value& msg, const std::string& position);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::queue<std::pair<Json::Value, std::string>>> _queues;
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _condition;
|
||||
size_t _maxQueueSize;
|
||||
};
|
||||
} // namespace ix
|
Reference in New Issue
Block a user