Skip to content
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

add async interface #12

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open

add async interface #12

wants to merge 1 commit into from

Conversation

davschul
Copy link

@davschul davschul commented Feb 7, 2022

This is a very early version of async message reading with a request for comments whether this in general would be acceptable and what I need to do to make sure this doesn't break anything.

pylsp_jsonrpc/endpoint.py Outdated Show resolved Hide resolved
@@ -35,6 +65,19 @@ def __init__(self, dispatcher, consumer, id_generator=lambda: str(uuid.uuid4()),
self._client_request_futures = {}
self._server_request_futures = {}
self._executor_service = futures.ThreadPoolExecutor(max_workers=max_workers)
self._cancelledRequests = set()

def init_async(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we have a way to set a asyncio event loop executor by parameter? https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.set_event_loop

Copy link
Author

Choose a reason for hiding this comment

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

This init_async function was more a relict of a previous attempt... I think it is save to initialize the queue in the default initializer...

Regarding set_event_loop I don't how I achieve something similar to davschul/python-lsp-server@215f79d in a more ellegant way, And I'm open to suggestions :)

Copy link
Contributor

Choose a reason for hiding this comment

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

No worries, this can be looked in a future iteration.

pylsp_jsonrpc/streams.py Outdated Show resolved Hide resolved
async def consume_task(self):
log.warning("starting task")
loop = asyncio.get_running_loop()
while True:
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this infinite loop being exited at any point? i.e., what happens at teardown time

Copy link
Author

Choose a reason for hiding this comment

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

I guess the loop is never cleanly exited, let me check what python has to offer to stop this loop here.

@andfoy
Copy link
Contributor

andfoy commented Feb 8, 2022

@davschul, thanks for the changes, we would appreciate if you added some tests for the async interface

@davschul
Copy link
Author

@davschul, thanks for the changes, we would appreciate if you added some tests for the async interface

The last changeset addresses the shutdown, I'll have another look for the tests next

@davschul
Copy link
Author

@davschul, thanks for the changes, we would appreciate if you added some tests for the async interface

The last changeset addresses the shutdown, I'll have another look for the tests next

Took a first stab at adding tests


def init_async(self):
self._messageQueue = asyncio.Queue()
self._consume_task = asyncio.create_task(self.consume_task())
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this task run on the executor?

Copy link
Author

Choose a reason for hiding this comment

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

This task will not run in an executor from https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor, but needs to be started after the event loop was started. I pushed an example implementation to davschul/python-lsp-server@9f0f03d

Copy link
Contributor

Choose a reason for hiding this comment

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

The infinite loop has potential to block the main event loop, which could lead to performance degradation/unexpected blockage. I think in this case it would be better to run this on a separate event loop

Copy link
Author

Choose a reason for hiding this comment

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

The asyncio queues used to send the messages cannot be used from different event loops. What might cause the block here in your opinion?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry for the long break, I was side tracked a bit in the python lsp support in Qt Creator and some urgent bugs before our release. I added a restriction to the loop, but I guess that not really what you've expected right?

@andfoy
Copy link
Contributor

andfoy commented Jun 8, 2022

Sorry for forgetting about this one! I think it looks better than a while True loop

@andfoy
Copy link
Contributor

andfoy commented Jun 8, 2022

I don't know why the tests are not running

@ccordoba12
Copy link
Member

Closing and reopening to see if they run.

@ccordoba12 ccordoba12 closed this Jun 8, 2022
@ccordoba12 ccordoba12 reopened this Jun 8, 2022
@bicobus
Copy link

bicobus commented Nov 3, 2022

Sorry to bother @andfoy and @ccordoba12 ; has this PR been forgotten? It seems somewhat helpful.

@ccordoba12
Copy link
Member

No, it hasn't. The thing is we also need to make python-lsp-server async to merge this one. And the we don't have the manpower for that right now, sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants