-
Notifications
You must be signed in to change notification settings - Fork 49
Decouple schema fetch queries timeouts from server side timeouts #361
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
Decouple schema fetch queries timeouts from server side timeouts #361
Conversation
d94edcc to
31d490a
Compare
31d490a to
ea6ed21
Compare
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.
Test classes need to have Test in thier name
ea6ed21 to
d1f38d8
Compare
| shard_aware_options=None, | ||
| metadata_request_timeout=datetime.timedelta(seconds=2), | ||
| ): |
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 it will be less confusing if the default is in one place (definition of the field) and here it is just None)
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.
done
cassandra/metadata.py
Outdated
| class SchemaQueryMessage(QueryMessage): | ||
| def __init__(self, query, consistency_level, serial_consistency_level=None, | ||
| fetch_size=None, paging_state=None, timestamp=None, continuous_paging_options=None, keyspace=None, | ||
| custom_timeout=None): | ||
| super(SchemaQueryMessage, self).__init__( | ||
| add_timeout_to_query(query, custom_timeout), consistency_level, | ||
| serial_consistency_level=serial_consistency_level, fetch_size=fetch_size, paging_state=paging_state, | ||
| timestamp=timestamp, continuous_paging_options=continuous_paging_options, keyspace=keyspace) | ||
|
|
||
|
|
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
super(SchemaQueryMessage, self).__init__instead ofsuper().__init__? I tried to research it quickly, and internet says that in Python 3 those are equal. - Parameter name should be something like
server_side_timeout- right now it is not clear which timeout is it for someone reading the code. - A comment explaining what this class is would be appreciated. It's not obvious to me why you are introducing new class instead of adding parameter to
QueryMessagecontructor. - Also consider introducing it in a separate commit. I'd like to see this PR split into commits because it is not easy to digest as one commit. Possible way to split:
- Introduce
SchemaQueryMessage, explaining its purpose, and change usages of QueryMessage to SchemaQueryMessage (without using custom_timeout parameter for now) - Add timeout parameter to I think Metadata.refresh - or whatever is the place from which it is taken to be passed to
SchemaQueryMessage - Add the plumbing in Cluster - this is the moment that the new feature is actually used.
- Add tests
I'll wait with further review until the PR is split into commits to be more digestable.
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.
@Lorak-mmk , I have dropped SchemaQueryMessage, and split PR into commits, please take a look
|
@dkropachev what's the status of this PR? |
I have postponed working on this PR due to the higher priority tasks on my side and @Lorak-mmk being focused on rust driver. |
|
@dkropachev let's try to merge this by the end of quarter if possible. |
d40a956 to
cbfc3fb
Compare
|
aarch64 tests failing on |
cassandra/metadata.py
Outdated
| def __init__(self, connection, timeout, fetch_size, metadata_request_timeout=None): | ||
| super(SchemaParserV22, self).__init__(connection, timeout, fetch_size, metadata_request_timeout) | ||
| self.keyspaces_result = [] | ||
| self.tables_result = [] |
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.
SchemaParser* structs are not part of public interface I think, se we should be able to add new mandatory argument to __init__. Wouldn't it be better for metadata_request_timeout to be such an argument, like timeout is? There is less room for mistakes on the caller side with mandatory arguments, and you are always passing the argument anyway.
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.
done
cassandra/util.py
Outdated
|
|
||
| def add_timeout_to_query(stmt: str, metadata_request_timeout: datetime.timedelta) -> str: | ||
| if metadata_request_timeout is None: | ||
| return stmt | ||
| ms = int(metadata_request_timeout / datetime.timedelta(milliseconds=1)) | ||
| if ms == 0 or _query_timeout_regexp.search(stmt) is not None: | ||
| return stmt | ||
| return f"{stmt} USING TIMEOUT {ms}ms" |
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 metadata_request_timeout can be None then the type should be Optional[datetime.timedelta].
I really wish we could sit down and add types to the whole driver and then run pyright (or other type checker) in CI.
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
cassandra/util.py
Outdated
|
|
||
| def add_timeout_to_query(stmt: str, metadata_request_timeout: datetime.timedelta) -> str: | ||
| if metadata_request_timeout is None: | ||
| return stmt | ||
| ms = int(metadata_request_timeout / datetime.timedelta(milliseconds=1)) |
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.
Better name for this function would be maybe_add_timeout_to_query as it doesn't always add the 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.
fixed
cassandra/util.py
Outdated
|
|
||
|
|
||
| _query_timeout_regexp = re.compile('USING[ \t]+TIMEOUT[ \t]+[0-9]+[a-z]+[ \t]*;?$') | ||
|
|
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 control all the places where the add_timeout_to_query function is called, there should be no need to have such a regex and performs checks with it.
If this is supposed to be a more universal function (and thus requiring this regex) then there are some problems with it (some of them unsolvable):
- For INSERT there may be no literal
USING TIMEOUT.INSERT INTO ks.t2 (pk, ck) VALUES (1, 2) USING TIMESTAMP 12345678 AND TIMEOUT 360ms;is a valid statement. I don't think it's fixable using regular expressions. - As soon as some new element of SELECT is added (and USING TIMEOUT doesn't have to be at the end of the statement) similar problem as above happens for SELECTs.
- Time unit can use uppercase letters, so
[a-z]is wrong. USING TIMEOUTis case insensitive.
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.
agree, at the worst we will see that query fails on the integration and unit tests, regexp removed.
This option allows user to control timeout for driver internal queries. Idea is to make driver queries more resilient and being independent of user queries.
ed356aa to
5b0a63f
Compare
5b0a63f to
7a4ae44
Compare
….metadata_request_timeout PR scylladb#361 that have introduced `metadata_request_timeout` intentionally pulled actual `metadata_request_timeout` from `control_connection_timeout`, because both `metadata_request_timeout` and `control_connection_timeout` has to be inline. Since this PR brings `Cluster.metadata_request_timeout` back, we need to pull it from `Cluster.metadata_request_timeout`
….metadata_request_timeout PR scylladb#361 that have introduced `metadata_request_timeout` intentionally pulled actual `metadata_request_timeout` from `control_connection_timeout`, because both `metadata_request_timeout` and `control_connection_timeout` has to be inline. Since this PR brings `Cluster.metadata_request_timeout` back, we need to pull it from `Cluster.metadata_request_timeout`
….metadata_request_timeout PR #361 that have introduced `metadata_request_timeout` intentionally pulled actual `metadata_request_timeout` from `control_connection_timeout`, because both `metadata_request_timeout` and `control_connection_timeout` has to be inline. Since this PR brings `Cluster.metadata_request_timeout` back, we need to pull it from `Cluster.metadata_request_timeout`
Scylla have an ability to override server timeout by appending
USING TIMEOUT <timeout>msto the queryMake driver add
USING TIMEOUT <control_connection_timeout*1000>msfor scylla connectionsCloses #320