Hi Geoff, I extracted all the important bits from our implementation into this gist:
https://gist.github.com/dmitrygusev/486ad56174450299b94cc364d3630b28 I'd start exploring it from here: https://gist.github.com/dmitrygusev/486ad56174450299b94cc364d3630b28#file-eagerloadresourceimpl-java-L94 In the gist you'll find full implementation, but configuration will likely be different depending on your project setup. You can find some examples in `TapestryEagerLoadModule` for how you can contribute variations to the warmup, e.g.: -- different locales, or other behaviours that can prepare a request thread for serving custom responses -- an example of contributing warmup logic as one of the health checks to the Dropwizard's healthcheck registry -- contributions to the `SkipEagerLoadForPatterns` to ignore certain files from direct access during warmup -- etc. Any questions or suggestions, please let me know. Regards, Dmitry On Mon, Dec 6, 2021 at 4:24 PM JumpStart < geoff.callender.jumpst...@gmail.com> wrote: > I think you’d want to make it a configuration option, so that development > can still come up quickly, but that sounds great for production. > > I’ve spent some time bouncing between Dmitry and Ben’s approaches. With > the latter I simplified it with Jsoup, but there are considerable > limitations to what can be preloaded that way. > > Dmitry, I have tried to flesh out what you’ve done, but I think my > knowledge of Tapestry internals is holding me back. You seem to have taken > a really deep dive! Is there any code that you’d feel comfortable sharing? > > Cheers, > > Geoff > > > On 4 Dec 2021, at 6:00 am, Thiago H. de Paula Figueiredo < > thiag...@gmail.com> wrote: > > > > Hi! > > > > Today I started wondering about how we could get Tapestry to run under > > Quarkus.io, including generating a native executable. Of course, this > won't > > include bytecode generated in runtime, something many libraries and > > frameworks do, Tapestry very much included. Then I researched a bit and > > found this: > https://quarkus.io/guides/writing-extensions#bytecode-recording. > > Basically, it's a hook for you to run the code that will generate > bytecode > > while the hook records everything (if I got it right). So, to write an > > extension for Tapestry, we would need to have every page and and every > > service (and maybe some other stuff too) fully realized, since > Tapestry-IoC > > and Tapestry load mostly everything in a lazy manner. This is something > > that could also solve Geoff's question: if we can somehow force Tapestry > to > > preload everything, then the app is ready and (at least mostly) warm when > > the first request is properly served. > > > > With the code Dmitry shared here, I wonder if you want to collaborate on > > implementing this preload feature on Tapestry itself out-of-the-box, > > avoiding some ugly workarounds needed since there's no actual support for > > that. :) > > > > Cheers! > > > > On Mon, Nov 29, 2021 at 7:36 PM Dmitry Gusev <dmitry.gu...@gmail.com> > wrote: > > > >> Hi Geoff, > >> > >> I don't think there's a simpler way, we're doing something similar. > >> > >> We created a REST endpoint with tynamo-resteasy which is effectively a > load > >> balancer health check. > >> On the first hit it starts the warmup process on the same request, > >> following requests return an error instantly if the initial warmup > routine > >> is still in progress. > >> > >> Our warmup logic is heavily based on tapestry internals & reflection, in > >> conjunction with eager loading services as described here: > >> https://gist.github.com/dmitrygusev/5562739 > >> > >> Warmup logic is a bit complicated, it's trying to: > >> - "touch" each page using ComponentClassResolver.getPageNames() > >> - recursively for each component with mixins on a page starting from > root > >> component, > >>> find imported assets via reflection (fields with names starting as > >> `importedAssets_`) > >>> stream each asset via `StreamableResourceSource` into no-op consumer > >> - find JS modules with `ModuleManager` and stream through no-op consumer > >> - every JS stack returned from `JavaScriptStackSource` assemble with > >> `JavaScriptStackAssembler` and stream through no-op consumer > >> - repeat above for each locale/axis > >> > >> Entire process usually takes 3-5 minute in our setup. > >> After it's done we return 200 to the load balancer and the first real > >> request is handled with hot caches. > >> > >> Hope this helps, > >> Dmitry > >> > >> On Mon, Nov 29, 2021 at 9:53 PM JumpStart < > >> geoff.callender.jumpst...@gmail.com> wrote: > >> > >>> Any suggestions on best ways to write a “health check” page to be > called > >>> by load balancers? > >>> > >>> My app is getting big, and the traffic is big. If the app fails > >> (hopefully > >>> never, but it’s a JVM) and the traffic is heavy enough, startup never > >> seems > >>> to complete - every request times out, the app log goes quiet, and CPU > >> goes > >>> to 100%. It appears to be due to race conditions possibly involving > asset > >>> compression, minimising, and first time into the pages. > >>> > >>> I’m considering having a startup service crawl every page, in every > >>> language, in every skinning, before setting a singleton flag that the > >>> health check page will read to determine whether the app is ready to > >>> receive traffic. > >>> > >>> Is there a simpler way? > >>> > >>> Geoff > >>> --------------------------------------------------------------------- > >>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > >>> For additional commands, e-mail: users-h...@tapestry.apache.org > >>> > >>> > >> > > > > > > -- > > Thiago > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > > -- Dmitry Gusev AnjLab Team http://anjlab.com