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 service-worker based cancellation (and maybe RPC) for use in vscode.dev by synchronous LSs #148967

Closed
jakebailey opened this issue May 6, 2022 · 5 comments
Assignees

Comments

@jakebailey
Copy link
Member

jakebailey commented May 6, 2022

Both TypeScript and Pylance are synchronous monstrosities, which on the desktop rely on synchronous filesystem accesses to check for cancellation of requests (as opposed to the more traditional RPC based cancel messages). In the browser, however, there's no synchronous filesystem at all, so both language servers opt to not implement cancellation at all.

There are only two synchronous things a web worker can do receive data:

  • SharedArrayBuffer. My understanding is that this is currently blocked due to the impact of the headers that would need to be applied to various CDNs and such.
  • Synchronous XMLHttpRequest. This is already used by TypeScript and Pylance to pull type declarations / type stubs in as needed.

The requests that a web worker makes with a synchronous XMLHttpRequest are visible to the site's service worker. Normally a service worker is used for caching of requests (for performance and offline support), but there's nothing stopping a service worker from answering requests without actually hitting the network.

This fact leads to an opportunity to create an API that to a web worker appears to be synchronous, but can be implemented asynchronously elsewhere.

I have a demo I presented to the TS team, the Pylance team, and @mjbvz: https://jakebailey.github.io/sw-cancellation-poc/

This demo works by having the service worker intercept requests to paths like /@cancellation@/, and then check to see if the main page (in this case, the client side of the RPC) has triggered cancellation or not. The main page can communicate to the service worker in any way it likes (HTTP or postMessage); all that matters is that the web worker can check this synchronously.

Cancellation is the main focus here; the data is ephemeral and best effort. But, this same method can be used to provide synchronous access to potentially any API, including file system access, which may simplify the implementation of VFS support in TypeScript and Pylance, both of which cannot do asynchronous accesses. My demo page also includes that as well.

I propose to add something like this to vscode.dev/github.dev's service worker; an extension cannot add its own service worker, so without SharedArrayBuffer, this is the only method available for TS and Python to get cancellation, and must be implemented in VS Code itself.

cc @DanielRosenwasser @RyanCavanaugh @heejaechang @bschnurr @debonte @gramster @erictraut @luabud

@DanielRosenwasser
Copy link
Member

@jrieken @dbaeumer are there any updates to cancellation that you could provide on this issue?

@dbaeumer
Copy link
Member

dbaeumer commented Aug 4, 2022

@DanielRosenwasser @jrieken and I had a discussion about this and since we are enabling SharedArrayBuffers for the WASI implementation for browsers we will likely use them for cancellation.

@mjbvz mjbvz closed this as completed Aug 5, 2022
@jakebailey
Copy link
Member Author

Is there a tracking issue for that implementation somewhere to follow?

@dbaeumer
Copy link
Member

dbaeumer commented Aug 8, 2022

No, but the implementation will very likely be in https://github.com/microsoft/vscode-wasi

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Aug 29, 2022

Just to give a TL;DR - this is something that both TypeScript and Pylance need in order to prevent hangs from long-running operations on the web.

For example, let's say a user types (which implicitly requests completions), and then keeps typing (which requests completions again). We can't detect that its results aren't needed, so the request has to be served up before the next completions request can even start. So if that request would usually take 200ms, there's a risk of 400ms completions and maybe some noisy UI

This gets exacerbated on the length of the operation. Find-all-refs, for instance, can take more than a few seconds. vscode.dev should feel lightweight, but each of these operations can make things feel choppy.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants
@joaomoreno @DanielRosenwasser @dbaeumer @alexdima @jakebailey @mjbvz @alexr00 and others