-
Notifications
You must be signed in to change notification settings - Fork 216
Send websocket payload using a queue #633
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: develop
Are you sure you want to change the base?
Conversation
It looks like it needs a pass with |
My project which uses |
Just leaving a note that I saw this happen before too. I recall it required many requests to be made in a very short period, and only occurred with specific setup of IO (which could be that it was just making it fast enough to allow this issue to occur). I wonder if there is a way to reliably reproduce this issue and add a test which would confirm that this patch solves it. |
I am working on a test for this. For now this patch does not work on Python 3.9, it prevents the server from starting up at all in websocket mode:
|
So I have a test on krassowski#1 which fails when |
The following diff makes this PR run fine for me: diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py
index 2826ea1..e2f98c4 100644
--- a/pylsp/python_lsp.py
+++ b/pylsp/python_lsp.py
@@ -117,7 +117,8 @@ def start_ws_lang_server(port, check_parent_process, handler_class) -> None:
) from e
with ThreadPoolExecutor(max_workers=10) as tpool:
- send_queue = asyncio.Queue()
+ send_queue = None
+ loop = None
async def pylsp_ws(websocket):
log.debug("Creating LSP object")
@@ -147,11 +148,15 @@ def start_ws_lang_server(port, check_parent_process, handler_class) -> None:
"""Handler to send responses of processed requests to respective web socket clients"""
try:
payload = json.dumps(message, ensure_ascii=False)
- asyncio.run(send_queue.put((payload, websocket)))
+ loop.call_soon_threadsafe(send_queue.put_nowait, (payload, websocket))
except Exception as e:
log.exception("Failed to write message %s, %s", message, str(e))
async def run_server():
+ nonlocal send_queue, loop
+ send_queue = asyncio.Queue()
+ loop = asyncio.get_running_loop()
+
async with websockets.serve(pylsp_ws, port=port):
while 1:
# Wait until payload is available for sending Still no luck in creating an isolated reproduction. Any ideas? |
Hi,
we experienced JSON responses from the websocket server being mixed up if the requests from client (code editor, Monaco in our case) are too frequent. The response payload was basically unparseable JSON, and it seemed like a mashed up content of multiple JSON responses. Handling the send operations one-by-one by using the
asyncio.Queue
seemed to fix the issue, so here is a suggestion to apply the same fix into the main codebase.