-
Notifications
You must be signed in to change notification settings - Fork 440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sending sync request through http_client #448
Conversation
Codecov Report
@@ Coverage Diff @@
## main #448 +/- ##
==========================================
- Coverage 94.46% 94.16% -0.30%
==========================================
Files 194 195 +1
Lines 8509 8571 +62
==========================================
+ Hits 8038 8071 +33
- Misses 471 500 +29
|
@maxgolov Need you review for this : ) Thanks. |
ext/test/http/curl_http_test.cc
Outdated
received_requests_.clear(); | ||
curl::SessionManager session_manager; | ||
|
||
auto session = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I need to send 2 synchronous requests from two different threads, do I need to create two separate sessions?
Why do I have to specify session IP, port, and Uri separately - is there a reason to not having something like:
oReq.open("GET", "http://www.example.org/example.txt")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I need to send 2 synchronous requests from two different threads, do I need to create two separate sessions?
Session
is a logical entity here for maintaining session id, ssl cert ( if needed ), callback object ( for async request) etc. HTTP is stateless protocol, so it doesn't makes sense to have ongoing session, and sending HTTP Requests over that.
Why do I have to specify session IP, port, and Uri separately - is there a reason to not having something like:
oReq.open("GET", "http://www.example.org/example.txt")
Yeah, its doable as separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I have done the modified sync requests as below:
HttpClient httpClient;
auto result = httpClient.Get(url);
if (result){
auto response = result.GetResponse();
} else {
std::cout << result.GetSessionState();
}
auto session = sessionManager.createSession("localhost", 8000); | ||
auto request = session->CreateRequest(); | ||
request->AddHeader(..); | ||
SessionState session_state; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is not a session
state - this is given request
state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct.
@@ -153,6 +153,33 @@ class Session : public http_client::Session | |||
}); | |||
} | |||
|
|||
virtual std::unique_ptr<http_client::Response> SendRequestSync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it would be much cleaner if you operate only on Response
object rather than on SessionState
. Let me elaborate - right now you have two possible states:
success
- in this case you returnResponse
and status code; orfailure
- in this case you force the user to test ifResponse
ptr is nullptr, and then inspect theSessionState
parameter passed by reference.. which is not reallySession
state (becauseSession
may have multiple requests), but rather this exactRequest
state.
So since in reality it is Request
state, can you have this aggregated on Response
object - making sure that you always return Response
: failed or succeeded, always return it. It may be successful response or empty response, failed response, with an indication on Response
object that it's a failed response. Then you avoid the nullptr entirely, you avoid checking on two separate objects, and you can just propagate the object elsewhere to the place that needs to make a decision what to do next with that failed request-response pair.
Could you please clarify - if the original intent of SessionManager
was to support more than one concurrent request at a time? If so, then SessionState
is a misleading name for a synchronous request resultt. Session may have more than one request, one failed, one successful, and SessionState
name does not represent the actual SessionManager
Session state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Response
object represents http-response containing - body, header and code. Any error during http handshake are returned in SessionState
. This is to keep it consistent with how we achieve it in async requests:
EventHandler::OnResponse(Response &);
EventHandler::OnError(SessionState);
Session::SendRequest(EventHandler &); // async
unique_ptr<Request> Session::SendRequestSync(SessionState &); // sync
If it's fine, we can always return empty response in case of error, and the Response::status_code
would be 0 in that case.
Session
is more of logical entity, and doesn't represent multiple ongoing http requests.
SessionManager
-> Multiple Session
s.
Single Session
-> Single Request
{ | ||
// we have a http response | ||
auto response = std::unique_ptr<Response>(new Response()); | ||
response->headers_ = curl_operation_->GetResponseHeaders(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you propagate Response code? If you are using int for that, then in Java it'd typically allocate -1
for failed response status code, which can then be used to determine if request was actually processed, as in connected and got some response code from server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently we use uint16_t
for status_code. If it's fine, we can always return empty response in case of error, and the Response::status_code
would be 0 in that case ?
{ | ||
is_session_active_ = true; | ||
std::string url = host_ + std::string(http_request_->uri_); | ||
curl_operation_.reset(new HttpOperation(http_request_->method_, url, nullptr, RequestMode::Sync, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we set RequestMode::Sync
in SendSync()
or just deduce it from SendSync()
and SendAsync()
. Is the inconsistency between ctor and SendSync()
handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do need to know the actual sync mode in ctor. There are some initializations done in ctor, and the sync mode
information is used to propagate the error/results to clients.
Is the inconsistency between ctor and SendSync() handled?
What kind of inconsistency we are talking about.
@@ -117,7 +117,7 @@ class ElasticsearchLogExporter final : public sdklogs::LogExporter | |||
ElasticsearchExporterOptions options_; | |||
|
|||
// Object that stores the HTTP sessions that have been created | |||
std::unique_ptr<ext::http::client::SessionManager> session_manager_; | |||
std::unique_ptr<ext::http::client::HttpClient> session_manager_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename the variable name to http_client_
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, this needs to be done in both cc and h. I was thinking to change it once @maxgolov is fine with the current changes ( to avoid reverting back). But thanks for noticing it. I will add this as pending change in PR description.
private: | ||
std::shared_ptr<Request> http_request_; | ||
std::string host_; | ||
std::unique_ptr<HttpOperation> curl_operation_; | ||
uint64_t session_id_; | ||
SessionManager &session_manager_; | ||
HttpClient &session_manager_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename the variable to http_client_
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with some minor comments.
Currently, http_client api supports sending async http requests, with error and response received through callback. For exporters, we need to have the status of http request returned from export function ( refer - #444 (comment) ) . Adding a method to send sync request in client interface, along with it's curl implementation.
Summary of changes:
2. Split
SessionManager
toHttpClient
( default async http client ) andHttpClientSync
( sync http client )2. Sync Request Example:
GET:
POST:
Pending Change: