Use asyncio - #2880
Conversation
Add a test that checks that "tcp server mode" works. Server meaning that this plugin acts as the TCP server and the langserver connects as TCP client.
Add a test that checks that "tcp server mode" works. Server meaning that this plugin acts as the TCP server and the langserver connects as TCP client.
Conflicts: tests/server.py
✅ Deploy Preview for sublime-lsp ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
Also write the rest of the requests in terms of Session.request
|
Would be useful to split it into smaller chunks, if possible. For example it would likely be possible to make Lots of assumptions on my side but that's what I feel. I was actually looking into that before as I wanted to move start_async into dedicated thread so that it doesn't black other plugins (kinda opposite goal of yours but also kinda similar as I guess with asyncio it will also run on dedicated thread). See #2863 It will be hard to review it properly with a big dump of code that refactors most of the code base. |
- Add sublime.set_timeout executor wrapper - Make all request handlers `async` - Define a CancellableInflightStreamingRequest class that enables `async for` syntax - Start inheriting DocumentSyncListener from sublime_aio.ViewEventListener (This one doesn't work yet) The state is fairly broken at this point.
| class Session(APIHandler, TransportCallbacks): | ||
| class Session(APIHandler, TransportCallbacks, TaskContainer): | ||
|
|
||
| _MAX_WAIT_ATTEMPTS = 40 |
There was a problem hiding this comment.
"max wait" for what? Naming could be more specific.
There was a problem hiding this comment.
The code block is something but the code should be self-explanatory so I would suggest a name like _FILE_DELETED_MAX_CHECK_ATTEMPTS
Co-authored-by: Rafał Chłodnicki <rchl2k@gmail.com>
This PR switches the codebase to using
async deffunctions andasyncio. The loop provider issublime_aio.close #2863.
should be merged (and released) at the same time as:
The main driver for doing this is to decrease the thread usage of this plugin from O(n) to O(1) threads, where
nis the number of language servers running. The secondary driver is syntax sugar.Why is this PR so large? Please read: What color is your function?
Self-contained bits:
sublime.set_timeout_asyncLSP.plugin.core.aio.call_soon_threadsafedef f() -> Promise[T]: ...async def f() -> T: ...Promise.then(lambda x: ...)x = await f()session.send_request_async(R(), lambda x: ...)x = await session.request(R())try ... except ResponseException:blockasync for partial_result in session.stream(R()):(caveat: only works forlist[...]-style responses)LSP.plugin.core.aio.run_coroutine_threadsafe(f())PromiseobjectsPromise.thenawait promisePromise.allasyncio.gathersublime.set_timeout_async(f, timeout_ms=1000)await asyncio.sleep(1)threading.Lock, or write very complicated queueing logicasyncio.Lockasyncfunction in aPromisePromise.wrap_taskfcallsgggfasync def f(): await g()async def f(): g()f, guaranteed called from asyncio threadaio.TaskContainer.create_task(g())def f(): g()f, any threaddef f(): aio.run_coroutine_threadsafe(g()), or useaio.TaskContainer.create_task_threadsafe(g())def f(): g()The Plan
Make "most" code run on the sublime_aio thread
Most code is doing bookkeeping. This type of code used to run on the Sublime "async" thread. It should run on the asyncio loop thread.
Previously, the code attempted to make most code run on the ST async thread. We never really enforced this. We tried to make it clear that a function/method should be running on the ST async thread by suffixing it with
_async.If you have an
async defcoroutine function, then such a coroutine function is forced to run on the asyncio loop thread. So enforcement becomes automatic.Keep
_asyncsuffixes, assume they run on the asyncio threadWhen a method or function has the suffix
_asyncin its name, we tried to ensure these functions run on the ST async thread. These can now be assumed to be running on the asyncio thread.Make compute-intensive function run on the Sublime "async" thread
The only compute-intensive code we deal with are parsing and emitting JSON. Only the JSON parser/emitter should run on the ST async thread.
Bridging code for existing LSP-* plugins
We made sure that all AbstractPlugin and LspPlugin related (class)methods ran on the ST async thread. I want to now make sure all these (class)methods run on the sublime_aio thread with this pull request.
Certain methods may also be marked
asyncfor LspPlugin, most notablyon_pre_startand perhapson_initialize.The
Promiseobject can be awaited, so older AbstractPlugin/LspPlugin-related functionality returning promises from request handlers work.