2017-09-13 00:57:09 +08:00
|
|
|
#include <chrono>
|
2017-09-12 21:25:43 +08:00
|
|
|
#include <experimental/optional>
|
|
|
|
#include <map>
|
2017-09-13 00:57:09 +08:00
|
|
|
#include <random>
|
2017-08-30 23:17:43 +08:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "communication/bolt/client.hpp"
|
|
|
|
#include "communication/bolt/v1/decoder/decoded_value.hpp"
|
2017-09-12 21:25:43 +08:00
|
|
|
#include "utils/exceptions.hpp"
|
2017-08-30 23:17:43 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
void PrintJsonDecodedValue(std::ostream &os,
|
|
|
|
const communication::bolt::DecodedValue &value) {
|
|
|
|
using communication::bolt::DecodedValue;
|
|
|
|
switch (value.type()) {
|
|
|
|
case DecodedValue::Type::Null:
|
|
|
|
os << "null";
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::Bool:
|
|
|
|
os << (value.ValueBool() ? "true" : "false");
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::Int:
|
|
|
|
os << value.ValueInt();
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::Double:
|
|
|
|
os << value.ValueDouble();
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::String:
|
|
|
|
os << "\"" << value.ValueString() << "\"";
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::List:
|
|
|
|
os << "[";
|
|
|
|
PrintIterable(os, value.ValueList(), ", ",
|
|
|
|
[](auto &stream, const auto &item) {
|
|
|
|
PrintJsonDecodedValue(stream, item);
|
|
|
|
});
|
|
|
|
os << "]";
|
|
|
|
break;
|
|
|
|
case DecodedValue::Type::Map:
|
|
|
|
os << "{";
|
|
|
|
PrintIterable(os, value.ValueMap(), ", ",
|
|
|
|
[](auto &stream, const auto &pair) {
|
|
|
|
PrintJsonDecodedValue(stream, {pair.first});
|
|
|
|
stream << ": ";
|
|
|
|
PrintJsonDecodedValue(stream, pair.second);
|
|
|
|
});
|
|
|
|
os << "}";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
std::terminate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-12 21:25:43 +08:00
|
|
|
template <typename TClient>
|
2017-08-30 23:17:43 +08:00
|
|
|
communication::bolt::QueryData ExecuteNTimesTillSuccess(
|
2017-09-12 21:25:43 +08:00
|
|
|
TClient &client, const std::string &query,
|
|
|
|
const std::map<std::string, communication::bolt::DecodedValue> ¶ms,
|
|
|
|
int times) {
|
|
|
|
std::experimental::optional<utils::BasicException> last_exception;
|
2017-09-13 00:57:09 +08:00
|
|
|
static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
|
|
|
|
static thread_local std::uniform_int_distribution<> rand_dist_{10, 50};
|
2017-08-30 23:17:43 +08:00
|
|
|
for (int i = 0; i < times; ++i) {
|
|
|
|
try {
|
2017-09-12 21:25:43 +08:00
|
|
|
auto ret = client.Execute(query, params);
|
2017-08-30 23:17:43 +08:00
|
|
|
return ret;
|
2017-09-12 21:25:43 +08:00
|
|
|
} catch (const utils::BasicException &e) {
|
2017-09-08 16:15:13 +08:00
|
|
|
last_exception = e;
|
2017-09-13 00:57:09 +08:00
|
|
|
std::this_thread::sleep_for(
|
|
|
|
std::chrono::milliseconds(rand_dist_(pseudo_rand_gen_)));
|
2017-08-30 23:17:43 +08:00
|
|
|
}
|
|
|
|
}
|
2017-09-14 03:20:03 +08:00
|
|
|
LOG(WARNING) << query << " failed " << times << "times";
|
2017-09-08 16:15:13 +08:00
|
|
|
throw last_exception;
|
2017-08-30 23:17:43 +08:00
|
|
|
}
|
|
|
|
}
|