Comments (36)
Hello @bkannadassan ,
- I am planning to open 1 socket for each request coming in for processing
in server with the backend and putting it in io read wait.- As explained by you looks like this read socket can't be a timed wait,
what would be your suggestion on the same ?.- I have one more option is timed wait, but this would delay the response
even if the response is ready from backend.
Yes, currently there is no custom connection-timeout functionality supported by oatpp.
I am not sure about your use-case or if this is critical for you.
At this point I can't suggest any good workaround as to make it actually work with oatpp-Async API one will need to tweak oatpp-epoll implementation itself.
- In client I see that we are using 2 executors, creating curlExecutor and
another is executor created and used when sending out a client request.
--> Want to understand if this curlExecutor does create another thread
? Would like to understand the purpose of the same.
Please specify what client
you are talking about.
If you mean this example project - then curl executor is added here just to show that one can substitute his own request executor as a "backend" for oatpp API Client.
In any case Clients async api calls are executed by coroutine which is run in the executor that you defined. - So no additional threads are populated for client calls.
Regards,
Leonid
from oatpp.
Hello @bkannadassan ,
Unfortunately there is no good way to do this. In order to do this you'l have to create your own oatpp::async::IOEventExecutor
implementation based on epoll.
I can't recommend any solutions at the moment. If something comes to my mind I'll inform you.
Regards,
Leonid
from oatpp.
Hello @bkannadassan ,
One of the possible ways of integrating oatpp with existing application/server and take advantage of oatpp REST controllers (ApiControllers) may look like this:
Create ApiController and Route its Endpoints
/* Create Router */
auto router = oatpp::web::server::HttpRouter::createShared();
/* Create ApiController instance and add its endpoints to Router */
auto myController = std::make_shared<MyController>();
myController->addEndpointsToRouter(router);
Handle Custom Requests using oatpp ApiController
/* Get route and endpoint to handle specified url */
auto route = router->getRoute("GET", "/hello");
/* Create Incoming Request with custom parameters */
auto request = oatpp::web::protocol::http::incoming::Request::createShared(... /* TODO fill in custom params*/);
/* Call endpoint for request and get response */
auto response = route.getEndpoint()->handle(request);
// TODO - process response
Please note: Creating custom request objects is pretty complex task. At the moment there is no convenience API for this purpose.
If you opt to go for this solution, I'll assist you.
Best Regards,
Leonid
from oatpp.
Closing this.
@bkannadassan please reopen if you have more questions on this topic
from oatpp.
from oatpp.
Hello @bkannadassan ,
Do you have HTTP parser in your existing application?
If yes, then I would suggest to start with the following:
-
Make sure that you can get the following values from you server for the incoming request:
- headers
- body
- path to endpoint
-
Make sure that your server can send response back with the following values provided:
- headers
- body
If you have it all, then the only thing left is to map from your-server request/response to oatpp request/response objects.
For this I'll prepare convenience APIs in order to make it easier.
If you don't have HTTP parser in your application, then you may use oatpp for that.
But in this case I would suggest to consider switching fully to oatpp.
Please Let me know in case of any questions.
I plan to introduce convenience APIs for oatpp request/response construction about next week.
Regards,
Leonid
from oatpp.
from oatpp.
Hello @bkannadassan ,
Thanks for letting me know.
So as I understand - you decided to use oatpp without integrating it with your existing libevent server.
Please let me know in case of any other questions.
Regards,
Leonid
from oatpp.
from oatpp.
from oatpp.
Hello @bkannadassan ,
I was thinking of your case and situation is the following:
-
oatpp could have been easily integrated with your "I/O engine" (libevent) in case you could implement the oatpp::data::stream::OutputStream
and oatpp::data::stream::InputStream interfaces for your I/O.
I'm not sure how exactly you work with libevent, but it may be quite difficult to do in case of an event APIs. - This is something that you have to investigate. -
Just in case if we can't do with http+rest with our libevent, we can
leverage one of our existing HTTP framework and integrate with oatpp rest
framework. Please do let us know on the same..
This case looks more straight forward for me. But in this case you'll have to hold all request/response info in the memory which will not suite for ex.: large files upload
Something like this.
Regards,
Leonid
from oatpp.
from oatpp.
Hey @bkannadassan ,
Yes, in both cases it can work in one thread.
Regards,
Leonid
from oatpp.
from oatpp.
Hello @bkannadassan ,
If you have a connection, then pass it directly to ConnectionHandler
:
- For multithreaded API use HttpConnectionHandler
- For Async API use AsyncHttpConnectionHandler
Example:
std::shared_ptr<oatpp::network::server::ConnectionHandler > connectionHandler = <previously created connection handler>;
...
std::shared_ptr<oatpp::data::stream::IOStream> connection = <create connection>;
std::unordered_map<oatpp::String, oatpp::String> parameterMap; // just empty params map
connectionHandler->handleConnection(connection, parametersMap)
You don't need to use Server
- it does nothing but gets connection and passes it to connection handler. So if you have your own accept loop - then pass connection directly to ConnectionHandler.
Regards,
Leonid
from oatpp.
from oatpp.
Hello @bkannadassan ,
- If no large data, then can we reduce the number of IO thread ?.
When using oatpp Async APIs oatpp::async::Executor
can be configured to be using the actual number of threads during the construction time.
However when already created it can't change the number of threads.
oatpp::async::Executor executor(
1 /* data-processing workers */,
1 /* I/O workers */,
1 /* timer workers */
);
Also when system has no load. All executor workers will be sleeping giving no load to your system.
So there is no much sense in decreasing number of executor threads.
In order to achieve the best performance I usually set such number of threads:
v_int32 cpus = <get number of machine CPUs>
oatpp::async::Executor executor(
cpus /* data-processing workers */,
0.5 * cpus /* I/O workers. Should be at least one. */,
1 /* timer workers */
);
- If a data received by the server needed to be processed by an
application should we add our function in the act handler/response handler?
When using oatpp Async APIs all requests processing is delegated to corresponding coroutines
mapped to serve the request.
Method act()
of coroutine is the entrypoint for coroutine.
https://github.com/oatpp/oatpp-starter-async/blob/master/src/controller/MyController.hpp#L43
Each method of coroutine should have NON-BLOCKING code only.
In order to wait for some operation (ex.: I/O) - coroutine should "notify" Executor
with the proper Action
that it should be rescheduled to an I/O or Timer worker.
Example of Async I/O code:
Full example is here
ENDPOINT_ASYNC("GET", "/body/string", EchoStringBody) {
ENDPOINT_ASYNC_INIT(EchoStringBody)
Action act() override {
/* return Action to start child coroutine to read body */
return request->readBodyToStringAsync().callbackTo(&EchoStringBody::returnResponse);
}
Action returnResponse(const oatpp::String& body){
/* return Action to return created OutgoingResponse */
return _return(controller->createResponse(Status::CODE_200, body));
}
};
Here, the act()
method returns the action telling executor to reschedule it on I/O thread, wait until body is full uploaded and then call Action returnResponse(const oatpp::String& body)
with the result.
Please note: that oatpp I/O worker uses its own implementation of epoll event loop.
More about oatpp async API read here
- Looks like Co-routines start from Data-Processing thread, have some
doubts here..
--> Only when there are more data to be received fd is moved to I/O
processing worker rt ?/
--> Once execution has done its moved to Timer Processing Workers, I see
it's moved to Data Processing later. Can you please give more clarity on
the same ?.
Current Coroutine calling another Co-routine inside the same can you please
share on an application ?. Because AFAIK each co-routine registered for a
specific tag.
"Data Processing" here is everything which is not an I/O or Timer.
Ex.:
- You prepare data like URLs/ports/IPs etc. - it's data processing.
- Trying to connect to server (socket connect) - it's I/O
- Management of the "ready" socket like - put it in the map, or array or whatever you do with the FD - is data processing.
- You call "read" on the socket - it's I/O
So on each step coroutine gets rescheduled.
Timer worker is not used for I/O at all. It is used to wait for some time only. Ex.: when you need to schedule some operation to happen by timer.
// Current Coroutine calling another Co-routine inside the same can you please
share on an application ?
See the example:
Action act() override {
/* return Action to start child coroutine to read body */
return request->readBodyToStringAsync().callbackTo(&EchoStringBody::returnResponse);
}
Action returnResponse(const oatpp::String& body){
/* return Action to return created OutgoingResponse */
return _return(controller->createResponse(Status::CODE_200, body));
}
Here coroutine calls another coroutine request->readBodyToStringAsync()
to read body and store it to string.
- Please note we are looking this interface to integrate for
1) Sending consul query to consul server {Have Seen A Sample
Implementation and would try to leverage the same}
2) Use Rest Interface to send Query to different tasks and receive a
response from the same.
We are looking to implement watch rest api similar to " curl -G
http://127.0.0.1:8500/v1/kv/lead?index=<mod-index#>&wait=10s " , this
would wait for a response from consul server. I hope this shouldn't be an
issue with the framework.
--> Do you see any issues in doing the same ?.
In order to get KV from Consul in Async manner you may use oatpp::consul
rest client.
https://github.com/oatpp/oatpp-consul/blob/master/src/oatpp-consul/rest/Client.hpp#L69
// We are looking to implement watch rest api similar to " curl -G http://127.0.0.1:8500/v1/kv/lead?index=<mod-index#>&wait=10s "
As far as I know (and can be seen from Consul API docs https://www.consul.io/api/kv.html) there is no &wait=10s
parameter in Consul KV API.
However for wait fot 10s
you can easily implement manually.
Additional Info:
Btw I have written with server implementation having both handler and
provider inside the same, but
addConn function takes fd and performs this task.
I have forked and created one in github under example-async.
I can see that you go with oatpp async API and you are trying to reuse oatpp::async::Connection
.
Please note that for async model oatpp::async::Connection
will suggest the async executor to reschedule coroutine(which is using this connection) to the I/O worker. And I/O worker is designed to uses oatpp implementation of epoll.
At this point I can see that integrating you own libevent server with oatpp Async will be hard.
I suggest to go with oatpp blocking model (simple multithreaded API). - This will make integration much easier.
So that integration will look like this:
- You get FD from libevent
- You pass FD to oatpp::web::server::HttpConnectionHandler.
oatpp::web::server::HttpConnectionHandler
creates a thread for that connection and processes it.
In this case you may use oatpp REST framework with simple APIs.
Btw you were saying about " Creating custom request objects is a pretty
complex task. At the moment there is no convenience API for this purpose.
", please let us know the timeline on the same since we might need the
same. I am planning to use ppconsul over this if possible so that ppconsul
will be framing the query to consul server.
This is planned for the nearest release.
By the end of July or by beginning of August.
Best Regards,
Leonid
from oatpp.
Hello @bkannadassan ,
Please find the project I've built for you - https://github.com/lganzzzo/oatpp-integration-example
This is an example of the possible way to integrate your project with oatpp REST framework.
Integration on "lower" level seems to be too complicated at the moment.
Best Regards,
Leonid
from oatpp.
from oatpp.
from oatpp.
from oatpp.
Hello @bkannadassan ,
Please do not make router static. Place it in config - as in the example project.
You can add you Controllers endpoints to router like as shown in the example:
https://github.com/lganzzzo/oatpp-integration-example/blob/master/src/App.cpp#L28
/* Get router component */
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
/* Create MyController and add all of its endpoints to router */
auto myController = std::make_shared<MyController>();
myController->addEndpointsToRouter(router);
Regards,
Leonid
from oatpp.
from oatpp.
from oatpp.
Hey @bkannadassan ,
If you are using oatpp Async API (as I can guess) with AsyncExecutor
then it is required to have at least one IO worker. And Each IO worker will populate two threads - two threads is required to be able to work in the full duplex mode.
Currently the only way to have no threads populated during the request processing in oatpp - is to implement integration as shown in the example project that I've built for you.
Regards,
Leonid
from oatpp.
Uh, you fixed that:)
Ok, thanks for letting me know.
Please let me know in case you have more questions.
Regards,
Leonid
from oatpp.
from oatpp.
from oatpp.
Hello @bkannadassan ,
Seems like you wanted to attache some image to your comment but image is not attached.
If I understand correctly, you have the following situation:
- You have no threads on your system by some reason (I didn't get if its hardware issue or because of your design).
- You already use libevent to receive I/O events and accept connections.
- You process each batch of events in the same thread. (he same thread that you run your event-loop in)
If it so,- then the best way for you to integrate with oatpp - is like in the example that I've created for you. In this case you will have no threads populated.
The flow is as follows:
(New Connection) --> (Libevent Accept) --> (Your HTTP parser) --> (Create oatpp Request Object from parsed values) --> (oatpp process request)
And when you have a response object from oatpp you do:
(oatpp process request) --> (obtain response object) --> (oatpp render response to buffer) --> (Your I/O processor Send buffer back to client)
In case of Async oatpp you will have to allocate min 5 threads:
- 1 accepting thread.
- 1 Data processing thread
- 2 I/O threads
- 1 Timer thread
With this number of threads you may then process whatever number of parallel connections you have.
But in this case the only thing that you can change is the acceptor. All other I/O will be handled by oatpp.
Please let me know if I misinterpreted something or in case you have more questions.
Best Regards,
Leonid
from oatpp.
from oatpp.
from oatpp.
from oatpp.
Hello @bkannadassan ,
I'll be able to reply later on Friday (EET).
Sorry for inconvenience.
Best Regards,
Leonid
from oatpp.
Hello @bkannadassan ,
Please use Github UI for commenting, and please use markdown code snippets.
See markdown cheatsheet for more info.
Because it is very hard to read unformatted code commented in email.
Coming back to your questions:
- I want to have this timeout in reading how to have wait for read with a
timeout ?.
Unfortunately timeout is not currently supported for coroutine actions of type TYPE_IO_WAIT
, TYPE_IO_REPEAT
- I think this response which I am putting in the buffer should be put in
a request so that it can be propagated into the subsequent co-routine. How
can this be done ?.
To obtain http response from other service in Async manner use oatpp ApiClient.
In this case your code will look something like this:
class HttpGetCoroutine : public oatpp::async::Coroutine<HttpGetCoroutine> {
private:
OATPP_COMPONENT(std::shared_ptr<app::Client>, appClient); // Your oatpp API client with "httpGetAsync" method defined as "API_CALL_ASYNC"
public:
Action act() override {
return appClient->httpGetAsync().callbackTo(&HttpGetCoroutine::onResponse);
}
Action onResponse(const std::shared_ptr<IncomingResponse>& response) {
return response->readBodyToStringAsync().callbackTo(&HttpGetCoroutine::onBodyRead);
}
Action onBodyRead(const oatpp::String& body) {
OATPP_LOGD("HttpGetCoroutine", "body='%s'", body->getData());
return finish();
}
};
Best Regards,
Leonid
from oatpp.
from oatpp.
Hi Leonid,
I am planning to start a co-routine to periodically run for every 10secs and check if there are any request pending for IO event for > 10sec and cleanup them. I can start the co-routine for this and trigger the same, but I am not sure how to get the list of pending request and find those > 10 secs, Can you provide some pointers on the same? or is it not possible to do the same ?.
rgds
Balaji Kamal Kannadassan
from oatpp.
Related Issues (20)
- ASYNC API and business logic (Question) HOT 1
- How to build oatpp on arm64? HOT 4
- About MySQL
- BODY_DTO fails to correctly parse "false" for Boolean HOT 1
- Sending "null" in request body causes seg-fault on any endpoint w/ BODY_DTO
- Can files be read asynchronously in ENDPOINT_ASYNC? HOT 1
- Regarding oatpp::async::CoroutineWithResult HOT 9
- How to add default values to the QUERY parameters of an ENDPOINT?
- Enhance Deserializer's "Error. Unknown field"
- How can I use OATPP to handle web browser request download file. HOT 2
- Memory leak in Object mapping HOT 1
- Deserialize json when not include required field only gives error when the field is specified as null
- [Question] readBodyIntoDTO when there's a list in the body
- API question
- how to make dynamic sql use oatpp-sqlite HOT 1
- LazyStringMapTemplate::get returns Nullptr wich is not in oatpp.io Documentation
- Please add support for CMake 3.16
- Cannot test if required integer query parameter is empty
- [Question] Is it possible during compilation to write out the generated oas-3.0.0.json file?
- May memory leak
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from oatpp.