drogonframework / drogonframework/drogon

Using Coroutine

Open
#2,394 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
14.3k
Forks
1.4k
Avg merge
1d 13h
Merged PRs (30d)
14

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

#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();
// 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 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 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.