error-helper.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { ErrorDetails } from '../errors';
  2. import type { LoaderConfig, LoadPolicy, RetryConfig } from '../config';
  3. import type { ErrorData } from '../types/events';
  4. import type { LoaderResponse } from '../types/loader';
  5. export function isTimeoutError(error: ErrorData): boolean {
  6. switch (error.details) {
  7. case ErrorDetails.FRAG_LOAD_TIMEOUT:
  8. case ErrorDetails.KEY_LOAD_TIMEOUT:
  9. case ErrorDetails.LEVEL_LOAD_TIMEOUT:
  10. case ErrorDetails.MANIFEST_LOAD_TIMEOUT:
  11. return true;
  12. }
  13. return false;
  14. }
  15. export function getRetryConfig(
  16. loadPolicy: LoadPolicy,
  17. error: ErrorData,
  18. ): RetryConfig | null {
  19. const isTimeout = isTimeoutError(error);
  20. return loadPolicy.default[`${isTimeout ? 'timeout' : 'error'}Retry`];
  21. }
  22. export function getRetryDelay(
  23. retryConfig: RetryConfig,
  24. retryCount: number,
  25. ): number {
  26. // exponential backoff capped to max retry delay
  27. const backoffFactor =
  28. retryConfig.backoff === 'linear' ? 1 : Math.pow(2, retryCount);
  29. return Math.min(
  30. backoffFactor * retryConfig.retryDelayMs,
  31. retryConfig.maxRetryDelayMs,
  32. );
  33. }
  34. export function getLoaderConfigWithoutReties(
  35. loderConfig: LoaderConfig,
  36. ): LoaderConfig {
  37. return {
  38. ...loderConfig,
  39. ...{
  40. errorRetry: null,
  41. timeoutRetry: null,
  42. },
  43. };
  44. }
  45. export function shouldRetry(
  46. retryConfig: RetryConfig | null | undefined,
  47. retryCount: number,
  48. isTimeout: boolean,
  49. loaderResponse?: LoaderResponse | undefined,
  50. ): retryConfig is RetryConfig & boolean {
  51. if (!retryConfig) {
  52. return false;
  53. }
  54. const httpStatus = loaderResponse?.code;
  55. const retry =
  56. retryCount < retryConfig.maxNumRetry &&
  57. (retryForHttpStatus(httpStatus) || !!isTimeout);
  58. return retryConfig.shouldRetry
  59. ? retryConfig.shouldRetry(
  60. retryConfig,
  61. retryCount,
  62. isTimeout,
  63. loaderResponse,
  64. retry,
  65. )
  66. : retry;
  67. }
  68. export function retryForHttpStatus(httpStatus: number | undefined) {
  69. // Do not retry on status 4xx, status 0 (CORS error), or undefined (decrypt/gap/parse error)
  70. return (
  71. (httpStatus === 0 && navigator.onLine === false) ||
  72. (!!httpStatus && (httpStatus < 400 || httpStatus > 499))
  73. );
  74. }