Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in relatedProductsLoader: Use of Promise.all Causes Loader to Fail When Any productList Call Rejects #877

Closed
portolucas opened this issue Sep 23, 2024 · 1 comment · Fixed by #878
Labels

Comments

@portolucas
Copy link
Contributor

Issue Type
Bug

Bug Report

Description
There is an issue with the relatedProductsLoader function where it uses Promise.all to fetch related products. If any individual call within the Promise.all fails (e.g., due to an API error or network issue), the entire Promise.all rejects. This causes the loader to fail and propagate the error up the call stack, potentially leading to unhandled promise rejections and application instability.

Steps to Reproduce (for bugs)
Use the relatedProductsLoader in an application to fetch related products.
Simulate a failure in one of the batched calls to productList (e.g., by causing an API endpoint to return an error or by interrupting the network connection).

Observe that the Promise.all in the loader rejects due to the failure in one of the promises.
Notice that the loader does not handle the error internally, and the error propagates to the calling function.

Expected Behavior
The relatedProductsLoader should handle errors internally to ensure that a failure in one of the batched productList calls does not cause the entire loader to fail. Instead, it should:

  • Use Promise.allSettled to wait for all promises to complete, regardless of individual failures.
  • Collect and return the successful results.
  • Handle or log the errors from failed promises appropriately.
  • Ensure that the loader's return type remains consistent (Product[] | null), even when some calls fail.

Actual Behavior

  • The loader uses Promise.all, which rejects if any promise rejects.
  • A failure in any productList call causes the entire loader to reject.
  • Errors are not handled within the loader, leading to potential unhandled promise rejections.
  • The calling code may receive unexpected errors or null values, disrupting the application flow.

Additional Context
This issue affects the robustness and resilience of applications using the relatedProductsLoader.

Modifying the loader to use Promise.allSettled and handling the results can resolve the problem.

Example modification:

const relatedProductsResults = await Promise.allSettled(
  batchedIds.map((ids) =>
    productList({ props: { similars: false, ids } }, req, ctx)
  ),
);

const relatedProducts = relatedProductsResults
  .filter(
    (result): result is PromiseFulfilledResult<Product[]> =>
      result.status === "fulfilled",
  )
  .flatMap((result) => result.value)
  .filter((x): x is Product => Boolean(x));

By handling errors internally, the loader becomes more stable and prevents failures from propagating unnecessarily.

@IncognitaDev
Copy link
Contributor

IncognitaDev commented Nov 12, 2024

Close by the #878

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants