bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
38.69k stars 1.32k forks source link

How to reload / delay when server is busy #2801

Open tacman opened 3 months ago

tacman commented 3 months ago

There's probably already a way to do this, but I can't seem to find it.

I want to trigger a load that I know will take a lot of time. Instead of polling and figuring out how to stop polling after some condition, is there a way to say "load this ajax, and if the server response with a 503 (Server is Busy), try again in n seconds and keep trying until you get another http status, like a 200"

Alternatively, how do I poll and then stop polling when some result has been acheived?

Thanks. HTMX rocks.

Telroshan commented 3 months ago

About cancelling/controlling polling; PR #2576 (and its v1 counterpart #2577) might interest you!

MichaelWest22 commented 3 months ago

I think the better way to handle this on the server backend is if you need to render something that takes variable/long time is to create a background array/queue of jobs to render the thing. When the request comes in if the item is not in the array/queue already then add it as a background task. Then check if the task is finished and maybe add a short sleep delay and check again to handle quick jobs. If the job finishes then you return the result but if it has not then you return the original htmx fragment that did the request but with the "every 2s" polling or a 2s delay. So it just constantly replaces the requesting element over top with a new polling request and then finally with the result. Any network or other errors it polls again to retry. If your result needs to go elsewhere then you can return a blank response to delete the polling requester element plus a oob swap to insert the data somewhere.

tacman commented 3 months ago

Hmm. Indeed that's what i want, but it seems like a poll-until option would be more elegant.

I have an idea of how to do it in stimulusjs, but tasks like this seem particularly well suited for htmx.

But since you're the author you would obviously know better than me.

My use case: if a string isn't translated, show a dimmed, flashing original, while the server fetches the translated string via an api or cache to a translation service like Google or deepl or libretranslate. When it finishes, the page content is replaced.

My server-side version of this is terrible on the first page load.

On Sun, Aug 11, 2024, 6:37 PM MichaelWest22 @.***> wrote:

I think the better way to handle this on the server backend is if you need to render something that takes variable/long time is to create a background array/queue of jobs to render the thing. When the request comes in if the item is not in the array/queue already then add it as a background task. Then check if the task is finished and maybe add a short sleep delay and check again to handle quick jobs. If the job finishes then you return the result but if it has not then you return the original htmx fragment that did the request but with the "every 2s" polling or a 2s delay. So it just constantly replaces the requesting element over top with a new polling request and then finally with the result. Any network or other errors it polls again to retry. If your result needs to go elsewhere then you can return a blank response to delete the polling requester element plus a oob swap to insert the data somewhere.

— Reply to this email directly, view it on GitHub https://github.com/bigskysoftware/htmx/issues/2801#issuecomment-2282911543, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEXIQKUWGNB4UHUCUXGHTLZQ7RTFAVCNFSM6AAAAABMEIAY3KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEOBSHEYTCNJUGM . You are receiving this because you authored the thread.Message ID: @.***>

MichaelWest22 commented 3 months ago

I'm not the author just a nobody. By the way the default hx-trigger="every 2s" on an element actually does basically exactly what you were asking for just by default in htmx. every 2 seconds it makes a request and if it gets back a 200 it swaps in the response to the page but if it returns a 5xx it does nothing and keeps on polling every 2 seconds till it gets a 200.

As for your use case it seems pretty easy to implement in htmx as on your first full page load you generate all your page content and when your server finds a element that has no translation you instead return a div or whatever with the css styles and pre translated content you want to display to the user plus you put a hx-get on the element to point to a url that gets the translated version of that component from your backend and add a hx-trigger="every 2s" or similar and it will load the page and show the dimmed/flashing version and then make several requests to get the translated version till it gets a 200 response from the server and swaps out that portion of the html with the translated version. This is a great super simple first version that can just return 5xx errors till the result works and then you can make it better by getting the translate endpoint to replace the element each time it polls with progress info on the request and make the request more async in the backend and maybe add an expiry timestamp to the request or a counter so that the backend can detect when its gone to long and return a failed response to stop it polling in a loop forever.

MichaelWest22 commented 3 months ago

Also see https://htmx.org/examples/lazy-load/ as a basic example but you can also set it to hx-trigger="load, every 2s" which will try the lazy load straight away and also every 2 seconds after as well if you think it needs retries. Thinking about it a great thing to add to the "every 1s" format would be "every 1s for 2m" that i think would be easy enough to add as an option to set a time limit for polling.