0

Description of behaviour

I have a React application which has a component where the user can upload multiple CSV files. The following happens on the client side:

  • Redux dispatch is used to trigger an async thunk action. Inside that action:
    • An additional nested dispatch is used to trigger a reducer function which puts all files in the Redux state, so that they are visible in the UI.
    • Files are then processed sequentially. Using a while loop until we have no more files, the following happens:
      • The Papa parse library's parse function processes the file inside a Promise:
        • As part of the step callback, the CSV data is read into an array of objects. Validation ensures that the CSV data cannot result in this array exceeding a limit of 1,000 elements.
        • As part of the complete callback, this array of 1,000 elements is mapped so that each array element translates to an HTTP PUT request to a back-end web service, which are then dispatched concurrently via the JavaScript fetch function and a wrapping Promise.all on which we await.
        • Once the complete function is finished, the outer Promise that wrapped the parse function is resolved.
      • Finally, a second nested dispatch call is triggered to store the result of the upload in Redux state (a simple status, with a list of errors). This ensures the UI can see the result of the individual file upload as soon as it's available. At this point, we no longer need to remember the file content itself, so this is also removed from the state.

Load Requirements

There is a requirement for users to upload possibly up to 100 files at a time through this component. Assuming the worst case, each file will translate to 1,000 fetch requests to the back-end.

I have load tested my code to these requirements and observed the following setups have no issues:

  • Chrome + starting up the application locally on my machine, with a mock back-end.

  • Firefox + deploying the application to the testing environment (so it's talking to the real back-end WS).

In these setups, all files are uploaded, and the UI remains fairly responsive whilst the browser gradually churns through the network requests (as long as the network tab of Developer Tools is not left open!)

The Problem

However, when using the following setup:

  • Chrome + deploying the application to the testing environment (so it's talking to the real back-end WS).

The following behaviour is observed:

  • The first 16 files are processed with no problems.
  • The 17th file seems to get through approximately a third of the requests (oddly it is almost always exactly at the 381st request where the problems begin - but it can't be a file-specific problem, because all 100 files in the test have identical content), and then the fetch function seems to error all of the remaining requests with a rather unhelpful generic message:
TypeError: Failed to fetch

However, when looking in the Developer Tools network tab, there is no evidence that any requests have failed, which leads me to believe the requests are not even "getting out of the door".

Once that 17th file has finished processing, all of the React components in my application will then disappear, as if the page has just gone blank.

When trying to refresh the browser tab, I then see an error:

Debugging connection was closed. Reason: Render process gone

If I then reload the page I can start the test all over again, and it will fail in almost exactly the same place.

It does seem to be a browser-specific problem because Firefox doesn't have this issue. However, I cannot explain why the issue is not reproducible when the React app is running on my local machine instead of deployed to our testing environment.

I suspected the issue was perhaps some kind of memory leak, but I also wondered if I could be exhausting Chrome's network cache (I tried setting the fetch cache setting to no-store but it didn't seem to make a difference). Or perhaps there is some hard limit to the total number of network requests a Chrome tab can make? However, none of these causes would explain why it works locally, so I'm feeling pretty stumped. Any advice or insight would be greatly appreciated!

Ian250221
  • 43
  • 4

0 Answers0