| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks @soyuka - in general i'm totally in favor and this is a valuable addition.
one thought just came to mind tho:
what's keeping us from having that as default behavior of the registry - configurable - and that config switch exposed via Builder - so we'd in the end could help users control the slight behavior switch here
Sorry, something went wrong.
|
Good call let me try this. |
Sorry, something went wrong.
Builder::build() runs all loaders eagerly and snapshots capabilities from the resulting registry. Both are computed once, when the server is built. Under a persistent runtime (e.g. FrankenPHP worker mode) the server is built a single time, so a loader whose data source is not yet ready at that moment (cold cache, un-warmed metadata) leaves the registry empty for the whole process — tools/list stays empty while tools/call still works. Make deferred loading the default behavior of Registry itself: it takes a loader and runs it on the first read (has*/get*), moving loading to request time when the application is initialized. The load runs once; the loaded flag is set only after a successful load, so a transient failure is retried on the next read. A re-entrancy guard lets loaders that read the registry during their own run (e.g. discovery's identity check) observe the partial state instead of recursing. Registrations made before the first read survive it. Expose the switch on Builder via setLazyLoading() (default on) so callers can opt back into eager loading at build time. In lazy mode capabilities are advertised from the configured sources so the initialize handshake does not force a load; in eager mode (or for a registry supplied via setRegistry(), which is always loaded eagerly) they are read from the loaded registry.
There was a problem hiding this comment.
that entire loader <=> registry dependency feels more and more odd when looking at Builder and ->load($this), but that's def debt from before and off scope here
Thanks for this already @soyuka!
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Summary
Builder::build() runs all loaders eagerly (ChainLoader::load($registry)) and then snapshots server capabilities from that registry (tools: $registry->hasTools(), etc.). Both happen once, when the server is built.
Under a persistent runtime (e.g. FrankenPHP worker mode) the server is built a single time and reused across requests. If a loader's data source is not yet ready at that moment — a cold cache, an application metadata layer that gets warmed later — the registry captures an empty state and never recovers for the lifetime of the process. tools/list (which reads the registry) returns [], while tools/call can still work if the consumer resolves handlers independently of the registry. This was reported downstream in api-platform/core#8370 (FrankenPHP worker mode).
Change
This also removes the need for the userland workarounds consumers currently apply (request-time list handlers, restoring-registry decorators) to keep discovery working under worker runtimes.
Tests
Notes
Behavioral change worth flagging for review: capabilities are now derived from configured sources, so a server with a discovery path or custom loader that ultimately yields nothing will advertise tools/resources/prompts where it previously advertised false. This is intentional (the whole point is not to inspect the registry at build), and harmless per MCP semantics, but it is a visible difference in the initialize response.