Closed ghost closed 6 years ago
Hi,
When I've started the development of OCILIB about 10 years ago as a high level API, I had to make a choice between using OCI synchronously or asynchronously (as both mode are supported, with some limitations to the asynchronous mode). I choose to not implement asynchronous mode for 2 reasons:
I do not have plans for supporting it in the future.
Best regards,
Vincent
@brano543 Run ocilib calls inside a separate thread. That is what I do when using ocilib in a GUI app for example.
@bangusi Could you provide an example on how exactly you do it, so you continue your event loop and then send the response back? I am using nghttp2_asio example and basically my problem is that I don't know how to put it as background job.
This is basically what I am doing now. Unfortunately the library is too complex for me to understand what it is exactly being done under the hood, because every time I try to print some status at end of get_report function, it almost instantly exits the function, so I don't know what is blocking the socket. Maybe it waits for res.end() to be called to continue. Could you advise?
void get_report(const request &req, const response &res)
{
//get the response body
vector<uint8_t> *msgpack_v = new vector<uint8_t>();
//this callback gets called every time a chunk of data is recieved
req.on_data([&res, msgpack_v](const uint8_t *data, std::size_t len) {
if (len > 0)
{
std::copy(data, data + len, std::back_inserter(*msgpack_v));
}
else if (len == 0)
{
//set the response headers correctly
header_map headers;
headers.emplace("content-type", header_value{"application/octet-stream", 0});
headers.emplace("access-control-allow-origin", header_value{"*", 0});
//set temporary download dir
boost::filesystem::path input_path(boost::filesystem::current_path());
boost::filesystem::path folder("/download");
boost::filesystem::path download_folder = input_path / folder;
string destination_directory = download_folder.string();
//first we need to get the report name
json object = json::from_msgpack(*msgpack_v);
string report_name = object["name"].get<string>();
vector<json> data = object["data"];
//cleanup memory
delete msgpack_v;
Validator validator = Validator();
unordered_map<string, string> validation_schema;
validation_schema["Receipt Required Flag"] = "(Y|N)";
unordered_map<string, string> parameters = validator.validate_form(data, validation_schema);
//blocking call
vector<vector<string>> results =get_report(destination_directory, parameters["Receipt Required Flag"]);
}});
}
@brano543 I have never used boost::asio apart from cursory glance but here is how I typically make sql calls when I want asynchronous behaviour
void get_report(...)
{
// execute your sql (calls to ocilib )
// catch any exeptions
// post results to the event queue of your main thread
}
// start a thread, pass parameters: note that std::thread will make copies so is you want to get the result of your sql back make sure you passs in-parametere such as a std::shared_ptr or plain pointer
std::thread th(get_report, destination_directory, parameters["Receipt Required Flag"]);
th.detach();
@bangusi Thank you for your advice, this was the first thing I have tried and helped me. However, in order to make it work with the boost::asio::io_service, I had to pass it into the thread, so I ended up with doing it like i describe here https://github.com/nghttp2/nghttp2/issues/1116.
Hello,
have you considered adding asynchronous feature to the library? Currently when I run an event loop, long-running calls to Oracle block it completely.