-
Notifications
You must be signed in to change notification settings - Fork 133
IGNITE-27056 added request timeouts to C++ client #7080
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
base: main
Are you sure you want to change the base?
Conversation
# Conflicts: # modules/platforms/cpp/ignite/client/detail/node_connection.h
|
|
||
| std::optional<std::chrono::time_point<std::chrono::steady_clock>> timeout{}; | ||
| if (m_configuration.get_operation_timeout().count() > 0) { | ||
| timeout = std::chrono::steady_clock::now() + m_configuration.get_operation_timeout(); |
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.
In java client there is an optimization for calling analog of ::now(). I am not aware of performance of this method. Should we research if similiar optimisation is required?
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.
Why? What exactly should be optimized here?
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.
TLDR:
I was under impression that java's System.currentTimeMillis() and steady_clock::now() have similar implementation and drawbacks. But learning a bit deeper revealed to me that system_clock::now() should be analogous to System.currentTimeMillis().
as I said I don't know any performance issues of this method. In java case there were some issues with analogous System.currentTimeMillis() on windows platform. That could be a reason why in ignite codebase we have org.apache.ignite.internal.util.FastTimestamps#coarseCurrentTimeMillis.
what optimization could be (if calling std::chrono::steady_clock::now() would be slower than we can afford). We spawn a thread which updates atomic value every X seconds. Instead of calling ::now() we read from atomic variable. As I googled a bit calling steady_clock::now() doesn't switch context from userspace to kernelspace (on opposing of calling system_clock::now()).
I am pretty sure that we don't want to do it right now, but maybe small task to research performance impact of calling ::now on each request.
| using namespace ignite; | ||
|
|
||
| const std::vector<std::string> DEFAULT_VERSIONS = {"9.1.0", "9.1.1", "9.1.2", "9.1.3", "9.1.4"}; | ||
| const std::vector<std::string> DEFAULT_VERSIONS = {"3.0.0"}; |
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.
unrelated to this ticket but mistake I made in previous 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.
What about 3.1.0?
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.
fixed
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.
Pull request overview
This PR adds request timeout support to the C++ client for Apache Ignite. The implementation allows clients to specify an operation timeout that applies to individual network operations, causing them to fail if the server doesn't respond within the specified time.
Key changes:
- Adds
operation_timeoutconfiguration parameter toignite_client_configuration - Implements timeout tracking in
node_connectionusing pending request metadata - Creates a fake server test infrastructure to simulate timeout scenarios
- Adds new error code
CLIENT_OPERATION_TIMEOUTfor timeout failures
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/platforms/cpp/ignite/client/ignite_client_configuration.h | Adds operation timeout configuration getter/setter with validation |
| modules/platforms/cpp/ignite/common/error_codes.h | Adds CLIENT_OPERATION_TIMEOUT error code |
| modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java | Adds corresponding Java error code |
| modules/platforms/cpp/ignite/client/detail/node_connection.h | Adds pending_request structure with timeout metadata |
| modules/platforms/cpp/ignite/client/detail/node_connection.cpp | Implements timeout handling logic with periodic checks |
| modules/platforms/cpp/tests/fake_server/* | New fake server infrastructure for testing timeout scenarios |
| modules/platforms/cpp/tests/fake_server/connection_test.cpp | Tests for handshake and timeout functionality |
| modules/platforms/cpp/ignite/protocol/buffer_adapter.h | Refactors magic number to use constant |
| modules/platforms/cpp/tests/client-test/main.cpp | Temporary bypass of connection check (likely for testing) |
| modules/platforms/cpp/tests/compatibility-tests/main.cpp | Updates default version for compatibility testing |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| std::vector<int64_t> keys_for_erasure; | ||
|
|
||
| for (auto& [id, req] : m_request_handlers) { | ||
| if (req.timeouts_at > now) { |
Copilot
AI
Nov 26, 2025
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.
The comparison logic is inverted. This should be req.timeouts_at < now to check if the request has timed out (i.e., the timeout time point is in the past). Currently, it marks requests as timed out when they haven't expired yet.
| if (req.timeouts_at > now) { | |
| if (req.timeouts_at < now) { |
|
|
||
| std::stringstream ss; | ||
| ss << "Operation timeout [req_id=" << id << "]"; | ||
| auto res = req.handler->set_error(ignite_error(error::code::CLIENT_OPERATION_TIMEOUT,ss.str())); |
Copilot
AI
Nov 26, 2025
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.
Missing space after comma in function call. Should be ss.str()) → ss.str()) with proper spacing: CLIENT_OPERATION_TIMEOUT, ss.str().
| auto res = req.handler->set_error(ignite_error(error::code::CLIENT_OPERATION_TIMEOUT,ss.str())); | |
| auto res = req.handler->set_error(ignite_error(error::code::CLIENT_OPERATION_TIMEOUT, ss.str())); |
|
|
||
| std::optional<std::chrono::time_point<std::chrono::steady_clock>> timeout{}; | ||
| if (m_configuration.get_operation_timeout().count() > 0) { | ||
| timeout = std::chrono::steady_clock::now() + m_configuration.get_operation_timeout(); |
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.
Why? What exactly should be optimized here?
| std::stringstream ss; | ||
| ss << "Operation timeout [req_id=" << id << "]"; | ||
| auto res = req.handler->set_error(ignite_error(error::code::CLIENT_OPERATION_TIMEOUT,ss.str())); |
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 think we should also log it as a warning here.
| std::vector<int64_t> keys_for_erasure; | ||
|
|
||
| for (auto& [id, req] : m_request_handlers) { | ||
| if (req.timeouts_at > now) { |
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.
It seems wrong. Do tests pass?
| if (req.timeouts_at > now) { | |
| if (req.timeouts_at < now) { |
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 will add a test which would fail with suc incorrect code. Thats left as artifact of refactoring.
| { | ||
| std::lock_guard lock(m_request_handlers_mutex); | ||
|
|
||
| std::vector<int64_t> keys_for_erasure; |
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.
Let's try avoiding additional memory allocation here. Let's erase values as we move through the map. We hold the lock anyway. It can be done with iterator:
auto it = map.begin();
while (it != map.end()) {
if (something) {
it = map.erase(it);
continue;
}
++it;
}| /** | ||
| * Default operation | ||
| */ | ||
| static constexpr std::chrono::milliseconds DEFAULT_OPERATION_TIMEOUT = std::chrono::milliseconds(0); |
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.
| static constexpr std::chrono::milliseconds DEFAULT_OPERATION_TIMEOUT = std::chrono::milliseconds(0); | |
| static constexpr std::chrono::milliseconds DEFAULT_OPERATION_TIMEOUT{0}; |
| // | ||
| // Created by Ed on 21.11.2025. | ||
| // |
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.
License
| // | ||
| // Created by Ed on 25.11.2025. | ||
| // | ||
|
|
||
| #include "response_action.h" |
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.
Empty file? Let's remove.
| // | ||
| // Created by Ed on 21.11.2025. | ||
| // | ||
|
|
||
| #include "fake_server.h" |
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.
Empty file, let's remove.
| // | ||
| // Created by Ed on 25.11.2025. | ||
| // |
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.
License.
| #include <netinet/in.h> | ||
| #include <sys/socket.h> | ||
| #include <unistd.h> |
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.
Is this implementation for Linux only?
https://issues.apache.org/jira/browse/IGNITE-27056
Thank you for submitting the pull request.
To streamline the review process of the patch and ensure better code quality
we ask both an author and a reviewer to verify the following:
The Review Checklist
- There is a single JIRA ticket related to the pull request.
- The web-link to the pull request is attached to the JIRA ticket.
- The JIRA ticket has the Patch Available state.
- The description of the JIRA ticket explains WHAT was made, WHY and HOW.
- The pull request title is treated as the final commit message. The following pattern must be used: IGNITE-XXXX Change summary where XXXX - number of JIRA issue.
Notes