-
Notifications
You must be signed in to change notification settings - Fork 193
Fix completion refresher query results leak and active query error #161
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
Conversation
… with addt'l logging.
…e code was redundant and hard to maintain.
…se queue when it's completed.
…in addition to id.
… events based on it's owner uri.
mssqlcli/main.py
Outdated
return [(None, None, None, | ||
'Auto-completion refresh started in the background.')] | ||
|
||
def get_completion_refresher_mssqlcliclient(self, mssqlcliclient): | ||
mssqlcliclient_completion_refreshser = MssqlCliClient( |
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.
nit: naming - since we're creating a new MssqlCliClient, can we call this method create_completion_refresher_mssqlcliclient #Closed
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.
mssqlcli/main.py
Outdated
return [(None, None, None, | ||
'Auto-completion refresh started in the background.')] | ||
|
||
def get_completion_refresher_mssqlcliclient(self, mssqlcliclient): | ||
mssqlcliclient_completion_refreshser = MssqlCliClient( |
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.
mssqlcliclient_completion_refreshser [](start = 8, length = 36)
spelling: refreshser #Closed
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.
mssqlcli/main.py
Outdated
return [(None, None, None, | ||
'Auto-completion refresh started in the background.')] | ||
|
||
def get_completion_refresher_mssqlcliclient(self, mssqlcliclient): | ||
mssqlcliclient_completion_refreshser = MssqlCliClient( |
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.
MssqlCliClient [](start = 47, length = 14)
Perhaps we introduce a copy method to MssqlCliClient to centralize copying an instance? #Closed
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 originally thought that would be a good idea, but then OOP wise I don't think a mssqlclient should be responsible for copying itself and generating a new owner URI. I moved that responsibility up a level. Let me know your thoughts. #Closed
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.
Two options:
-
we currently generate an owner_id in the constructor, so can generate a new owner_id as part of the copy operation.
-
we can pass in the owner_id in the copy method.
I think I like #2, and if the value not passed, we create it:
if not owner_uri:
self.owner_uri = generate_owner_uri()
Maybe clone would be a better name to avoid shallow/deep copy confusion.
In reply to: 167103472 [](ancestors = 167103472)
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.
expected_complete_event=1) | ||
rpc_client.shutdown() | ||
|
||
def test_query_execute_response_AdventureWorks2014(self): |
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_query_execute_response_AdventureWorks2014 [](start = 8, length = 46)
Can we add a test that does concurrent queries on two different owner uri?
Also, can we add any tests for non-happy path failure scenarios? For example, the refresh connection is killed while executing while the query connection continues. #Closed
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.
That's what this test does. It ensures that Request A never retrieves responses for Request B. This was the root cause of the display leak which is why I targeted this type of unit test. I can add a query connection failed test.
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.
Based on our discussion for restructuring the test story, I'll hold off on the failed connection test for 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.
🕐
This PR is awesome! I can't wait to take this for a spin. Just some minor issues. |
mssqlcli/main.py
Outdated
return [(None, None, None, | ||
'Auto-completion refresh started in the background.')] | ||
|
||
def create_completion_refresher_mssqlcliclient(self, mssqlcliclient): |
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.
create_completion_refresher_mssqlcliclient [](start = 8, length = 42)
I think we can delete this method can just call clone directly.
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.
@pensivebrian ship it ribbit :) |
…bcli#161) * Adding a lock acquisition during executing a single batch query. * Fixing casing in order to retrieve proper error message. * Adding support for owner uri in json rpc response dequeueing. * Adding support for a separate connection for the completion refrehser with addt'l logging. * Marking string as unicode for py2/3 compat. * Converging all sqltoolsservice test to a single file since most of the code was redundant and hard to maintain. * Adding missing json rpc client tests and reformatted for readability. * Adding clean up for each request to remove it's owner uri from response queue when it's completed. * Adding request finished for owner uri of request when a exception occurs. * Setting response_str to None to avoid assignment exception. * Fixing build.py format. * Adding owner URI to connection complete event during failure. * Changing get response signature in jsonrpcclient to accept owner uri in addition to id. * Removing copyright headers from files I touched. * Refactored test json rpc contracts tests. * Adding unit test for ensuring query execute requests retrieve correct events based on it's owner uri. * Fixing typo in refresher name. * Renaming method for creating a new mssqlcliclient for completion refresher. * Renamed baseline files for simplicity. * Removed copyright header. * Refactoring and adding clone support to mssqlcliclient. * Removing unnecessary call to get a new mssql cli client.
…bcli#161) * Adding a lock acquisition during executing a single batch query. * Fixing casing in order to retrieve proper error message. * Adding support for owner uri in json rpc response dequeueing. * Adding support for a separate connection for the completion refrehser with addt'l logging. * Marking string as unicode for py2/3 compat. * Converging all sqltoolsservice test to a single file since most of the code was redundant and hard to maintain. * Adding missing json rpc client tests and reformatted for readability. * Adding clean up for each request to remove it's owner uri from response queue when it's completed. * Adding request finished for owner uri of request when a exception occurs. * Setting response_str to None to avoid assignment exception. * Fixing build.py format. * Adding owner URI to connection complete event during failure. * Changing get response signature in jsonrpcclient to accept owner uri in addition to id. * Removing copyright headers from files I touched. * Refactored test json rpc contracts tests. * Adding unit test for ensuring query execute requests retrieve correct events based on it's owner uri. * Fixing typo in refresher name. * Renaming method for creating a new mssqlcliclient for completion refresher. * Renamed baseline files for simplicity. * Removed copyright header. * Refactoring and adding clone support to mssqlcliclient. * Removing unnecessary call to get a new mssql cli client.
…bcli#161) * Adding a lock acquisition during executing a single batch query. * Fixing casing in order to retrieve proper error message. * Adding support for owner uri in json rpc response dequeueing. * Adding support for a separate connection for the completion refrehser with addt'l logging. * Marking string as unicode for py2/3 compat. * Converging all sqltoolsservice test to a single file since most of the code was redundant and hard to maintain. * Adding missing json rpc client tests and reformatted for readability. * Adding clean up for each request to remove it's owner uri from response queue when it's completed. * Adding request finished for owner uri of request when a exception occurs. * Setting response_str to None to avoid assignment exception. * Fixing build.py format. * Adding owner URI to connection complete event during failure. * Changing get response signature in jsonrpcclient to accept owner uri in addition to id. * Removing copyright headers from files I touched. * Refactored test json rpc contracts tests. * Adding unit test for ensuring query execute requests retrieve correct events based on it's owner uri. * Fixing typo in refresher name. * Renaming method for creating a new mssqlcliclient for completion refresher. * Renamed baseline files for simplicity. * Removed copyright header. * Refactoring and adding clone support to mssqlcliclient. * Removing unnecessary call to get a new mssql cli client.
Fix for #103 and #95.
a.) A query is already in progress for this editor session. Please cancel this query or wait for its completion.
Sqltoolsservice was not designed for MARS (Multiple Active Result Set) support. Meaning it cannot handle concurrent queries for a single connection. The previous design for mssql-cli was to share a connection between the main thread and the completion refresher thread. Due to this, if a query from the main thread was executed at the same time as the query from the background, this error message would be populated.
Solution: Use a separate connection for the completion refresher thread. For Cloud support, this connection is new every time we refresh the completions when the database is altered or context changed.
b.) Query results from background completion refresher thread leaks onto main prompt.
When retrieving events from the shared JSON RPC client, a query/complete event would have no correlation with the request that submitted it. If the main thread executes in between the background threads query and fills the event queue with a query complete event, the background thread will break and never retrieve it's own results. The main thread then resumes and picks up the response from the background thread.
Solution: On top of maintaining a separate connection, responses are now retrieved via both a ID and/or Owner URI. This prevents connection A from retrieving results from connection B.
Added unit test:
Additional fixes: