[HN Gopher] Retry XMLHttpRequest Carefully
       ___________________________________________________________________
        
       Retry XMLHttpRequest Carefully
        
       Author : aparks517
       Score  : 20 points
       Date   : 2022-06-28 18:11 UTC (4 hours ago)
        
 (HTM) web link (lofi.limo)
 (TXT) w3m dump (lofi.limo)
        
       | e12e wrote:
       | Very nice write-up. I'd be curious to see it using fetch rather
       | than the older xhr Api - that would make more sense as a library
       | _today_ I think? Or are there compelling reasons to stick with
       | xhr in a post-ie world?
        
         | dreamcompiler wrote:
         | I still use xhr because of familiarity. Using a javascript
         | closure as a callback in xhr works quite well and seems _much_
         | easier to me than dealing with the promises that are required
         | for fetch. (I understand what promises are; I just think the
         | ones in javascript are poorly-defined.)
         | 
         | https://pouchdb.com/2015/05/18/we-have-a-problem-with-promis...
        
           | mhink wrote:
           | From the end of the article you linked:
           | 
           | > Awaiting async/await
           | 
           | > That's the point I made in "Taming the asynchronous beast
           | with ES7", where I explored the ES7 async/await keywords, and
           | how they integrate promises more deeply into the language.
           | Instead of having to write pseudo-synchronous code (with a
           | fake catch() method that's kinda like catch, but not really),
           | ES7 will allow us to use the real try/catch/return keywords,
           | just like we learned in CS 101.
           | 
           | > This is a huge boon to JavaScript as a language. Because in
           | the end, these promise anti-patterns will still keep cropping
           | up, as long as our tools don't tell us when we're making a
           | mistake.
           | 
           | Async/await is extremely well-supported and reliable in the
           | ecosystem now, and allows you to express Promise-based
           | asynchronous flows with a much more natural syntax. I highly
           | recommend that you take a look, as it pretty much obviates
           | all the pain points mentioned in the linked article.
        
         | aparks517 wrote:
         | Thank you for your kind words! For lofi.limo I support back to
         | Chrome 49 and Firefox 52 (the last versions available for
         | Windows XP), which I /think/ both have Fetch, so I could have
         | probably used it here.
         | 
         | Fetch has about the same capabilities as XHR, so it should be a
         | drop-in replacement in this project. Let's call it an exercise
         | for the reader! ;)
        
           | chrismorgan wrote:
           | > _which I /think/ both have Fetch_
           | 
           | Yes: https://caniuse.com/fetch.
        
       | rbirkby wrote:
       | Just use axios and https://www.npmjs.com/package/retry-axios
        
         | eurasiantiger wrote:
         | Or node-fetch and @adobe/node-fetch-retry.
        
       | kerblang wrote:
       | Am I wrong or is this going to retry 404's and other 4xx things
       | that it shouldn't retry?
        
       | joshstrange wrote:
       | This post reminded of a /fun/ bug I ran into at my last job. The
       | root of the issue was our server was returning a 408 timeout
       | error when something timed out on the backend. Astute readers
       | might immediately notice an issue with that code, mainly that
       | it's for a /client/ timeout not 504 (server timeout).
       | 
       | Since we controlled the client and server you might think it
       | doesn't matter much, as long as the client knows how to handle a
       | 408 everything should be fine right? Well not exactly. We had a
       | number of pages/endpoints that would be overwhelmed when there
       | was too much data on the backend for a given user/company (which
       | was it's own issue but let's just take that as fact for this and
       | move on). We dutifully sent back 408's and knew that we needed to
       | optimize or chunk those endpoints in the future.
       | 
       | The problem was the code that timed out would keep running until
       | it finished (or hit a different timeout). On it's own this isn't
       | the end of the world, the server does work that never gets sent
       | to the client and essentially is thrown away. The problem was
       | some of these endpoints would run very heavy queries that could
       | bring down our database if enough of them were run in a short
       | window. Even more confusing it appeared as if our server was
       | running multiple of these queries for only 1 request.
       | 
       | We were using Akka (Actor-based) in our backend and thought maybe
       | something was misconfigured or that we might accidentally be
       | dropping duplicate messages into the queues that caused multiple
       | queries to get fired off. We fought with this on/off for months
       | (you know, something else is always a higher priority). Finally
       | we tracked down that the browser was sending multiple requests.
       | This was only clear when testing in a isolated dev environment
       | with no other traffic and you could clearly see a second request
       | being made after the first one timed out. What was extremely
       | frustrating is Chrome did not show this second request in the dev
       | tools, it only showed the initial request.
       | 
       | After more digging and a little luck I stumbled across a
       | "feature" of browsers where they will retry the same request
       | under certain circumstance and they wouldn't show that in dev
       | tool. A 408 was one of those cases. Switching to the correct
       | code, 504, immediately fixed our odd self-DDOS against our DB.
       | 
       | Obviously this was the fault of whoever initially defined
       | `TIMEOUT = 408` somewhere in our HTTP error codes class but to
       | this day I feel like Chrome should have had some indication that
       | it was firing off another request. If you left the tab open
       | Chrome would just keep retrying and slowly overwhelm the DB with
       | heavy queries until it fell over.
        
         | pgt wrote:
         | Thanks! Did not know some browsers would invisibly retry
         | requests that returned 408.
        
         | indemnity wrote:
         | Really curious what the use case is for _dev_ tools hiding a
         | network request from you?
         | 
         | Sure, don't display it in the UI, but if the browser is
         | retrying something I sure want to know about it when debugging!
         | 
         | Odd.
        
           | joshstrange wrote:
           | Yeah, that was my thought as well. It threw me for a loop
           | because I never would have expected that my browser dev tools
           | would hide something like that. It was a core tenant of my
           | debugging that was broken.
        
       | noduerme wrote:
       | At this point I like to wrap my remoting code (including optional
       | retries) into async functions that return a promise. The promise
       | resolves with a result from the server, or rejects with any sort
       | of error that can come from an XHR (or now, fetch), and the
       | consumer can decide what to do with that.
       | 
       | In my software I almost never do automatic retries, rather I warn
       | the user that there was a connection error if necessary, and
       | revert whatever state was waiting on a call. In my view anything
       | that can fail silently probably does not need to be retried right
       | now.
        
       | cratermoon wrote:
       | This is a good introduction to the subject. At the end you might
       | want to mention rate limiting, truncation (giving up after a
       | specified number of retries) and, for the most sophistication,
       | circuit breakers.
        
         | aparks517 wrote:
         | Thank you for your suggestions! I'll see if I can write a few
         | intelligent sentences on these (somewhat more advanced)
         | subjects.
        
       ___________________________________________________________________
       (page generated 2022-06-28 23:02 UTC)