{
  "version": 3,
  "sources": ["../../../src/store/utils/retry.ts"],
  "sourcesContent": ["/**\n * Retry utilities for upload operations.\n *\n * Provides exponential backoff calculation and error classification\n * for determining whether failed uploads should be retried.\n */\n\n/**\n * Internal dependencies\n */\nimport type { QueueItemId } from '../types';\n\nexport interface RetryDelayOptions {\n\t/** The current retry attempt number (1-based). */\n\tattempt: number;\n\t/** Initial delay in milliseconds before the first retry. */\n\tinitialDelay: number;\n\t/** Maximum delay in milliseconds (cap for exponential growth). */\n\tmaxDelay: number;\n\t/** Multiplier for exponential backoff (e.g., 2 means double each time). */\n\tmultiplier: number;\n\t/** Jitter factor (0-1) to add randomness to prevent thundering herd. */\n\tjitter: number;\n}\n\n/**\n * Calculates the delay before the next retry attempt using exponential backoff with jitter.\n *\n * The formula is: min(initialDelay * multiplier^(attempt-1), maxDelay) * (1 +/- jitter)\n *\n * @param options - Configuration for the retry delay calculation.\n * @return The delay in milliseconds before the next retry.\n *\n * @example\n * // With defaults: attempt 1 = ~1000ms, attempt 2 = ~2000ms, attempt 3 = ~4000ms\n * calculateRetryDelay({\n *   attempt: 1,\n *   initialDelay: 1000,\n *   maxDelay: 30000,\n *   multiplier: 2,\n *   jitter: 0.1,\n * });\n */\nexport function calculateRetryDelay( options: RetryDelayOptions ): number {\n\tconst { attempt, initialDelay, maxDelay, multiplier, jitter } = options;\n\n\t// Calculate base exponential delay: initialDelay * multiplier^(attempt-1).\n\tconst exponentialDelay = initialDelay * Math.pow( multiplier, attempt - 1 );\n\n\t// Cap the delay at maxDelay.\n\tconst cappedDelay = Math.min( exponentialDelay, maxDelay );\n\n\t// Apply jitter: multiply by a random factor between (1-jitter) and (1+jitter).\n\t// This helps prevent multiple failed uploads from retrying at exactly the same time.\n\tconst jitterFactor = 1 + ( Math.random() * 2 - 1 ) * jitter;\n\n\treturn Math.floor( cappedDelay * jitterFactor );\n}\n\n/**\n * Patterns in error messages that indicate a transient/retryable condition.\n *\n * The upload path rejects with plain `Error` instances from `fetch` and\n * `@wordpress/api-fetch`, so message matching is the most reliable signal.\n * Covers Chrome (`Failed to fetch`), Safari (`Load failed`), Node DNS/TCP\n * failures, and the localized `apiFetch` `fetch_error` message.\n */\nconst RETRYABLE_MESSAGE_PATTERNS = [\n\t/network/i,\n\t/timeout/i,\n\t/ECONNRESET/i,\n\t/fetch failed/i,\n\t/connection/i,\n\t/socket/i,\n\t/ETIMEDOUT/i,\n\t/ENOTFOUND/i,\n\t/Could not get a valid response/i,\n\t/Failed to fetch/i,\n\t/Load failed/i,\n];\n\n/**\n * Determines whether an upload error should trigger an automatic retry.\n *\n * Returns `false` once the retry budget is exhausted, otherwise returns\n * `true` if the error message looks transient (see `RETRYABLE_MESSAGE_PATTERNS`).\n *\n * Accepts both `Error` instances and plain strings: the editor's media-upload\n * wrapper forwards only the error *message* (a string) to the queue, so the\n * upload path frequently rejects with a string rather than an `Error`.\n *\n * @param error      The error that occurred, or its message.\n * @param retryCount The number of retries already attempted.\n * @param maxRetries The maximum number of retries allowed.\n * @return Whether the error should be retried.\n */\nexport function shouldRetryError(\n\terror: Error | string,\n\tretryCount: number,\n\tmaxRetries: number\n): boolean {\n\tif ( retryCount >= maxRetries ) {\n\t\treturn false;\n\t}\n\n\tconst message = typeof error === 'string' ? error : error?.message || '';\n\treturn RETRYABLE_MESSAGE_PATTERNS.some( ( pattern ) =>\n\t\tpattern.test( message )\n\t);\n}\n\n/**\n * Module-level storage for retry timer IDs.\n *\n * Timer references are kept outside Redux state because they are\n * non-serializable and only needed for cleanup on cancellation.\n */\nexport const retryTimers = new Map<\n\tQueueItemId,\n\tReturnType< typeof setTimeout >\n>();\n\n/**\n * Clears any pending retry timer for the given item.\n *\n * @param id Item ID.\n */\nexport function clearRetryTimer( id: QueueItemId ): void {\n\tconst pendingTimer = retryTimers.get( id );\n\tif ( pendingTimer !== undefined ) {\n\t\tclearTimeout( pendingTimer );\n\t\tretryTimers.delete( id );\n\t}\n}\n"],
  "mappings": ";AA2CO,SAAS,oBAAqB,SAAqC;AACzE,QAAM,EAAE,SAAS,cAAc,UAAU,YAAY,OAAO,IAAI;AAGhE,QAAM,mBAAmB,eAAe,KAAK,IAAK,YAAY,UAAU,CAAE;AAG1E,QAAM,cAAc,KAAK,IAAK,kBAAkB,QAAS;AAIzD,QAAM,eAAe,KAAM,KAAK,OAAO,IAAI,IAAI,KAAM;AAErD,SAAO,KAAK,MAAO,cAAc,YAAa;AAC/C;AAUA,IAAM,6BAA6B;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAiBO,SAAS,iBACf,OACA,YACA,YACU;AACV,MAAK,cAAc,YAAa;AAC/B,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAW;AACtE,SAAO,2BAA2B;AAAA,IAAM,CAAE,YACzC,QAAQ,KAAM,OAAQ;AAAA,EACvB;AACD;AAQO,IAAM,cAAc,oBAAI,IAG7B;AAOK,SAAS,gBAAiB,IAAwB;AACxD,QAAM,eAAe,YAAY,IAAK,EAAG;AACzC,MAAK,iBAAiB,QAAY;AACjC,iBAAc,YAAa;AAC3B,gBAAY,OAAQ,EAAG;AAAA,EACxB;AACD;",
  "names": []
}
