Skip to content

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

Merged
merged 22 commits into from
Feb 9, 2018

Conversation

MrMeemus
Copy link
Contributor

@MrMeemus MrMeemus commented Feb 8, 2018

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:

  • Verifies query A does not retrieve responses from query B.

Additional fixes:

  • Logging for the completion refresher database connection.
  • Not failing the completion refresher when it cannot connect.
  • Correct casing for the error message event for the ResultSubset event.
  • Additional logging to expedite future issues.
  • Refactored and converged all JSON RPC contracts test into a single file as most of the code was redundant and hard to maintain.
  • Add'tl test changes mentioned in the commits.

@MrMeemus MrMeemus self-assigned this Feb 8, 2018
@MrMeemus MrMeemus added the bug label Feb 8, 2018
@MrMeemus MrMeemus changed the title Ron/query results completion displayed Fix completion refresher query results leak and active query error Feb 8, 2018
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(
Copy link
Member

@pensivebrian pensivebrian Feb 8, 2018

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

Copy link
Contributor Author

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(
Copy link
Member

@pensivebrian pensivebrian Feb 8, 2018

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

Copy link
Contributor Author

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(
Copy link
Member

@pensivebrian pensivebrian Feb 8, 2018

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

Copy link
Contributor Author

@MrMeemus MrMeemus Feb 8, 2018

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two options:

  1. we currently generate an owner_id in the constructor, so can generate a new owner_id as part of the copy operation.

  2. 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)

Copy link
Contributor Author

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):
Copy link
Member

@pensivebrian pensivebrian Feb 8, 2018

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Member

@pensivebrian pensivebrian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@pensivebrian
Copy link
Member

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):
Copy link
Member

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.

Copy link
Member

@pensivebrian pensivebrian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@MrMeemus
Copy link
Contributor Author

MrMeemus commented Feb 9, 2018

@pensivebrian ship it ribbit :)

@MrMeemus MrMeemus merged commit 959b652 into master Feb 9, 2018
@MrMeemus MrMeemus deleted the ron/query_results_completion_displayed branch February 9, 2018 02:02
hejack0207 pushed a commit to hejack0207/osql-cli that referenced this pull request Apr 27, 2018
…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.
hejack0207 pushed a commit to hejack0207/osql-cli that referenced this pull request Apr 27, 2018
…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.
hejack0207 pushed a commit to hejack0207/osql-cli that referenced this pull request Apr 27, 2018
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants