-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Hello, An Tao! I'm using your Drogon framework without controllers. The bottom line is that every 5 minutes a method from my class should be run to make a series of API requests to the server.
main.cpp
#include <drogon/drogon.h>
#include "octopus.h"
int main()
{
drogon::HttpAppFramework &root = drogon::app();
root.loadConfigFile("../../config_drogon.json");
InSomnia::Octopus octopus;
octopus.starter();
drogon::app().run();
return 0;
}
octopus.cpp
void Octopus::starter()
{
const Config &config = Config::get_instance();
const Octopus_Mode octopus_mode = config.get_octopus_mode();
const double delay_start =
config.get_octopus_delay_start(); // seconds
const double period =
config.get_octopus_period(); // seconds
drogon::HttpAppFramework &root = drogon::app();
trantor::EventLoop *loop = root.getLoop();
if (octopus_mode == Octopus_Mode::IMITATION)
{
loop->runAfter(delay_start, [this]()
{
this->exec();
});
}
else if (octopus_mode == Octopus_Mode::REALITY)
{
loop->runAfter(delay_start, [this]()
{
this->exec();
});
loop->runEvery(period, [this]()
{
this->exec();
});
}
else if (octopus_mode == Octopus_Mode::DATABASE_MAINTENANCE)
{
loop->runAfter(delay_start, []()
{
// Create user in data base
User::create_user_db();
// Print list users from data base
const std::string str_list_users =
User::print_list_users_from_db();
std::cout << "Users:\n" << str_list_users << "\n";
std::cout.flush();
});
}
else if (octopus_mode == Octopus_Mode::SANBOX)
{
loop->runAfter(delay_start, [this]()
{
// Test hash librarys
// Sandbox::test_hash_library();
// Test Trade API ByBit
this->sandbox = std::make_shared<Sandbox>();
// this->sandbox->test_trade_api_bybit();
this->sandbox->test_trade_api_bybit_coro();
});
}
else
{
throw std::runtime_error("Octopus mode is incorrect");
}
}
I first started the event loop (app.run()) and then (delayed by timer) called my methods that access the database and the remote server via API
Basically, this approach worked fine until I started using coroutines in the code. When using sendRequestCoro, the coroutine started executing and never ended. When debugging, it was clear that the thread was dying after launching the coroutine. As I diagnosed, the problem was that the coroutine was running in the same thread as the main event loop
If I moved the event loop to a separate thread, then the root was executed correctly, but accessing the database broke and deteriorated
Then I did this
int main()
{
drogon::HttpAppFramework &root = drogon::app();
root.loadConfigFile("../../config_drogon.json");
std::mutex mtx;
std::condition_variable cv;
bool is_initialized = false;
std::thread app_thread([&root, &mtx, &cv, &is_initialized]()
{
root.getLoop()->queueInLoop([&mtx, &cv, &is_initialized]()
{
{
std::lock_guard<std::mutex> lock(mtx);
is_initialized = true;
}
cv.notify_one(); // Сообщаем основному потоку, что можно продолжать
std::cout << "Drogon initialized signal sent." << std::endl;
});
std::cout << "Starting Drogon..." << std::endl;
root.run();
std::cout << "Drogon stopped." << std::endl;
});
std::cout << "Waiting for Drogon to initialize..." << std::endl;
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [&is_initialized] { return is_initialized; });
lock.unlock();
std::cout << "Drogon initialized. Proceeding with runTest." << std::endl;
InSomnia::Octopus octopus;
octopus.starter();
app_thread.join();
std::cout << "Application finished." << std::endl;
return 0;
}
But I see this code as ugly. Secondly, I can no longer use the launch of my methods every 5 minutes, since the
trantor::EventLoop *loop = root.getLoop();
loop->runEvery(...);
spoils the coroutine challenge (she goes into oblivion again)
An Tao, please tell me how to write beautiful and elegant Drogon code that calls one of my methods every 5 minutes. To make all Drogon functions work and it was right