-
Notifications
You must be signed in to change notification settings - Fork 264
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
Implement experimental module fallback service for testing #1423
Conversation
Thanks for putting up this PR! 🙂 It looks like we still need to specify all modules ahead-of-time, even if their contents are then fetched from the fallback service. For Vitest, we won't know which modules we need to load upfront, so would need a mechanism that requests from the module fallback service for all modules that couldn't be found. Ideally we'd also have support for the following:
|
45e589c
to
acf7491
Compare
Ok, updated to support fallback for unknown modules. Also added a header to the fallback request that indicates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested this out with a bunch of differently typed modules including returning modules from the fallback service that make further requests to the fallback service. 🙂 All seems to work nicely, with Node 19.4.0. With Node 20.9.0, it looks like a Host
header is required on requests, or else Node will return a 400 response.
acf7491
to
4714dbb
Compare
Hey again! 👋 I've now got a MVP of the Vitest integration working using the fallback service and unsafe eval bindings. 🎉
|
@mrbbot ...
This becomes a bit tricky to implement but not impossible. It would largely mean that an individual
Just to make sure I understand, you'd like the request to the fallback service to include both the specifier of the module being imported/required and the specifier of the referent? Should be possible with a few additional minor tweaks.
This one should be fixed with the refactor that treats specifiers as proper URLs but I'll verify that. This is a bit of a larger change so I might not do anything for this one immediately and just handle it as part of the larger refactor.
Yeah, this is one that I've been wanting to revisit for a while. For now since you have a workaround let's leave it as is. After the larger refactor is done I'll revisit circular requires/imports in general. |
4714dbb
to
6e13a3f
Compare
@jasnell Yep, something like that. Here are some examples of the ideal behaviour I'm looking for:
Essentially, rather than receiving something like If it's helpful, this is what my module fallback service implementation looks like at the moment too: https://github.com/cloudflare/workers-sdk/blob/bcoll/vitest-pool-workers/packages/vitest-pool-workers/src/pool/module-fallback.ts |
ok, I'll likely be able to work up changes for this by end of day tomorrow. |
6e13a3f
to
fa9e8ca
Compare
@mrbbot ... ok, I've pushed up some update fixup commits that hopefully address most if not all of your needs. Be aware that it changes quite a bit.
I don't think it hits all of your cases in https://github.com/cloudflare/workerd/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc#issuecomment-1828786854 but it hopefully gets close and we can continue to iterate if necessary. In the future, once my planned module registry refactor is done, some of the details on this may change. Your code will likely need to be able to deal with both the old and the new. My plan there is to introduce a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasnell Thanks for making those changes. I was able to massively simplify my fallback service implementation. 😃 I've added some comments for some minor tweaks I needed to make to get things working.
Your code will likely need to be able to deal with both the old and the new.
I'm not too worried about this. miniflare
pins its workerd
version already, so we can just update the code when workerd
changes. 👍
9b4c699
to
3a61d6a
Compare
b4e66b6
to
d3110f7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As requested, added the changes I needed to make to get this working as suggestions. 👍
da328ed
to
d51e631
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified this works with the current Vitest pool implementation without any additional patches. 🎉
d51e631
to
542e54a
Compare
Adds the ability to load modules lazily from a local http fallback service. The fallback service is a simple http server that returns the Worker::Module configuration for a module dynamically rather than embedded within the worker configuration. This is only usable for local dev. See samples/module_fallback for an example. Co-authored-by: MrBBot <bcoll@cloudflare.com>
542e54a
to
d14f17f
Compare
Ok, internal CI run looks good and shows this can land without requiring internal changes to land at the same time. Will get this merged. |
Adds the ability to load modules lazily from a local http fallback service. The fallback service is a simple http server that returns the Worker::Module configuration for a module dynamically rather than embedded within the worker configuration. This is only usable for local dev. See samples/module_fallback for an example.
Not all modules will use the fallback service. In the worker configuration, a module has to be explicitly configured to use the fallback. Also, because of the nature of the ESM modules and the way v8 handles them, there really is no hot-module-reloading. Once a module is loaded for a worker it cannot be replaced without restarting the worker. Currently that's only possible by either shutting workerd down or using the
--watch
feature which watches for changes in the source configuration file on disk. We'll need to try work around that separately.The module loading using the fallback service is lazy-ish. The fallback service won't be engaged until the module is actually imported but since most imports are static it will appear as if the fallback service is being accessed immediately on worker startup for most cases. You'll see the laziness of the loader in action if you're using dynamic imports or require (e.g.
import(...)
orrequire(...)
).The fallback service is a simple http server that must return a properly JSON serialized form of the
Worker::Module
configuration as specified by the workerd.capnp schema. The request URL will be the specifier of the module in afile://
URL form (e.g. a module specifier offoo
will be passed to the fallback service asfile:///foo
. No other headers or details are passed in theGET
request.For now, every request to the fallback service spins up its own kj::Thread that is joined synchronously with the current thread. We could update that to use a single persistent thread with a queue but the current approach is simpler and raw performance really isn't a concern at this point. We can always tweak that more later.