#include #include #include #include "../shared/GlobalConfigFile.h" #include "../shared/DatabaseWithRetry.h" #include "../shared/DatabaseForThread.h" #include "../shared/MiscSQL.h" #include "../ax_alert_server/Types.h" #include "DataFormat.h" #include "AutoSecondaryData.h" #include "FieldLists.h" #include "Strategy.h" /* This is an interactive way to test the alerts. You can enter a collaborate * string and a list of alerts to grab from the database and watch the code * run. * * To run this test: * ./fast_alert_search -f ../../live_server/config_common.txt -i port_number=1234 -i test_specific_alerts=1 */ // Find in database, convert to record, return as a vector, no side effects. // getAlerts() adds "SELECT ... WHERE ", and the caller provides the rest of // the SQL. static std::vector< RecordRef > getAlerts(std::string const &sql2) { static const auto fields = DatabaseFieldInfo::getAlertFields(); static const std::string sql1 = "SELECT " + DatabaseFieldInfo::makeSqlFieldList(fields) + " FROM alerts WHERE "; const std::string sql = sql1 + sql2; std::vector< Record::Ref > result; MysqlResultRef fromDatabase = DatabaseForThread(DatabaseWithRetry::SLAVE)->tryQueryUntilSuccess(sql); result.reserve(fromDatabase->numRows()); for (; fromDatabase->rowIsValid(); fromDatabase->nextRow()) result.push_back(DatabaseFieldInfo::makeRecord(fromDatabase, fields)); return result; } // Internally (i.e. most of the C++ code) we only deal with collaborate strings // that start with "O=" or similar. The GUI is responsible for removing // "http://...?" part, if it exists. But there is no GUI for this test! static std::string stripURL(std::string collaborate) { const auto pieces = explode("?", collaborate); assert(pieces.size() < 3); // pieces.size() == 1 means no ?, use it all as is. // pieces.size() == 2 means a normal URL, grab the part after the ? // pieces.size() > 2 means more than one ?. Which is never valid. The ? is // a special character and should be quoted. If we see it here it's some // type of mistake. return pieces[pieces.size() - 1]; } static void doTestSpecificAlertsNow() { DatabaseWithRetry &database = *DatabaseForThread(DatabaseWithRetry::SLAVE); UserId userId = 4; std::string collaborate; std::unordered_set< std::string > dates; std::map< int64_t, RecordRef > alerts; // id => alert // Find in database, load them into our list, show feedback to the user. // addAlerts() adds "SELECT ... WHERE ", and the caller provides the rest of // the SQL. const auto addAlerts = [&](std::string const &sql) { const auto newAlerts = getAlerts(sql); std::cout<<"Loaded: "; if (newAlerts.empty()) std::cout<<"none"; else for (RecordRef const &alert : newAlerts) { int64_t id = alert->lookUpValue(MainFields::id).getInt(); alerts[id] = alert; std::cout<lookUpValue(MainFields::timestamp).getInt(); const std::string date = dateToMysql(timestamp, false); if (dates.insert(date).second) { // First time we've seen this date. AutoSecondaryData &asd = AutoSecondaryData::instance(); asd.addAlertsDaily(date); asd.notifyWhenReady([date]() { std::cout<<" [alerts_daily for "<