Last active
January 20, 2021 10:31
-
-
Save marty1885/3fee810ec743ad874cbefb334abf52fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <drogon/drogon.h> | |
#include <exception> | |
#include <coroutine> | |
#include <stdexcept> | |
using namespace drogon; | |
int main() | |
{ | |
app().createDbClient("postgresql", "localhost", 5432, "test", "test", "some legit password 191561", 16) | |
.addListener("0.0.0.0", 4444) | |
.setThreadNum(1); | |
// Asking DB for data then reply (table only as 1 row) | |
// | |
// NOTE: Variables must be passed by value. Otherwise (references) can easily go out of scope. Since the function(subrutine) can | |
// exit while the coroutine is executing. | |
// NOTE: Must return a `promise_type`. Otherwise C++ doesn't see it as coroutine | |
// | |
// Performance: 7244.49 Q/s (98.32%) | |
// 1 Server thread and 4 client thread. CPU: Cortex-A72 @ 2GHz | |
// Benchmarked using ApacheBanchmark. Average over 100K requests | |
// | |
// It fluctuate a bit. Overall, coroutine is a bit slower than callback. | |
app().registerHandler("/coro", [](HttpRequestPtr req, std::function<void (const HttpResponsePtr &)> callback) -> AsyncTask { | |
auto sql = app().getDbClient(); | |
// Coroutines! YAY!!! | |
auto result = co_await sql->execSqlCoro("SELECT * FROM users;"); | |
//^^^^^ Copy by value kills the just-created coroutine frame. Somehow this made things faster then by reference | |
auto resp = HttpResponse::newHttpResponse(); | |
callback(resp); | |
}); | |
// The current solution of using callbacks | |
// | |
// Performance: 7367.88Q/s (100%) | |
app().registerHandler("/cb", [](const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) -> void{ | |
auto sql = app().getDbClient(); | |
sql->execSqlAsync("SELECT * FROM users", [callback](const drogon::orm::Result& result) { | |
auto resp = HttpResponse::newHttpResponse(); | |
callback(resp); | |
}, [](const drogon::orm::DrogonDbException& e){ | |
}); | |
}); | |
// ================================================================================================================== | |
// Misc tests | |
// Make sure the awaiter is written correctly to propergrate exceptions from callback into coroutine | |
app().registerHandler("/coro_bad_sql", [](HttpRequestPtr req, std::function<void (const HttpResponsePtr &)> callback) -> AsyncTask { | |
auto sql = app().getDbClient(); | |
try { | |
auto result = co_await sql->execSqlCoro("SELECT * FROM users WHERE username ============ ?;"); | |
throw std::logic_error("This line shouldn't run because of exceptions"); | |
} | |
catch(const drogon::orm::Failure& e) { | |
auto resp = HttpResponse::newHttpResponse(); | |
resp->setBody("Exception is cought"); | |
callback(resp); | |
} | |
}); | |
// Make sure SQL with parameters work | |
app().registerHandler("/coro_with_param", [](HttpRequestPtr req, std::function<void (const HttpResponsePtr &)> callback) -> AsyncTask { | |
auto sql = app().getDbClient(); | |
auto result = co_await sql->execSqlCoro("select * from users where username = $1 limit $2;", "the_user", 1); | |
auto resp = HttpResponse::newHttpResponse(); | |
callback(resp); | |
}); | |
app().registerHandler("/test_request_coro", [](HttpRequestPtr req, std::function<void (const HttpResponsePtr &)> callback) -> AsyncTask { | |
auto client = HttpClient::newHttpClient("http://example.com"); | |
auto example_req = HttpRequest::newHttpRequest(); | |
example_req->setPath("/"); | |
try { | |
auto example_resp = co_await client->sendRequestCoro(example_req); | |
if(example_resp->getBody().size() == 0) | |
throw std::runtime_error("Why is there nothing"); | |
} | |
catch(const std::exception& e) { | |
std::cerr << "Error in request: " << e.what() << std::endl; | |
} | |
auto resp = HttpResponse::newHttpResponse(); | |
callback(resp); | |
}); | |
app().run(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment