feat: trace resource requests to allow fetching dynamic resources from pyodide process without a page refresh #5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
Terminology
pyodide
is project that lets us run Python in web browsers via WebAssembly (WASM).asset
is a file generated by the Datasette server running in Pyodide.serviceworker
is a JS script that intercepts requests. It can't reach the webworker directly.webworker
is a JS script that hostspyodide
. It isn't strictly required, but we do it because the file is big + potentially slow. Code in the webworker doesn't interrupt the main rendering thread. It can't reach the serviceworker directly.Changes
In #4, assets were only available on the second fetch. I wasn't sure how to block the service-worker process while it was waiting for the webworker to respond. This PR removes that hurdle by using JS
Promises
. Instead of checking for the datasette response in a cache, the service-worker uses arequestId
as a form of "bookkeeping" for the server to include in its response, ensuring that response can be matched to the request with a message-passing rather than callback-based dataflow.server-worker.js
intercepts the request, and decides whether to check for it in the local cache, pass it through to the public internet via fetch, or ask the web-worker for it.webworker
, we add an entry to the registry with a uniquerequestId
to handle an async message from the webworker, and wait for up to TIMEOUT seconds. A message is sent to the parent HTML page that can be forwarded to thewebworker
, including arequestId
and apath
.Meanwhile, in the
webworker
, we await messages from the other process. The Pyodide process uses thepath
to generate an appropriate response (text, json, etc), and returns it (including a proper MIME Type) along with therequestId
.Finally, back in the
serviceworker
: when we receive a message with a requestId, we return the result to the host HTML page. To cleanup / free up memory, we delete the "pending" request from the response registry.Testing
This can also be tested with cloudflare: https://d2ae7b89.datasette-lite.pages.dev/
http://localhost:3000/?install=datasette-nteract-data-explorer#/content/pypi_packages?_nocol=description
http://localhost:3000/?install=datasette-nteract-data-explorer#/content/pypi_packages?_nocol=keywords&_nocol=description
Here's a sample graph: https://a.cl.ly/Z4uDgerK
Notes
Pyodide assets are cached, so this should work offline after the first loadMoving this part to a separate PRIllustrated Explainer
Here's a cartoon of the problem that this PR solves.