Deduplicate multipart retry checks
This commit is contained in:
@@ -3,7 +3,7 @@ import {nanoid} from 'nanoid/non-secure'
|
||||
|
||||
import {AbortError} from '#/lib/async/cancelable'
|
||||
import {type CompressedVideo} from '#/lib/media/video/types'
|
||||
import {isRetryableHttpStatus, shouldRetryError} from '#/lib/strings/errors'
|
||||
import {shouldRetryError} from '#/lib/strings/errors'
|
||||
import {getServiceAuthToken} from '../upload.shared'
|
||||
import {mimeToExt} from '../util'
|
||||
import {
|
||||
@@ -19,7 +19,7 @@ import {getMissingParts, planParts} from './planParts'
|
||||
import {createChunkReader} from './readChunk'
|
||||
import {createUploadPart} from './uploadPart'
|
||||
import {uploadParts} from './uploadParts'
|
||||
import {delay} from './utils'
|
||||
import {delay, isRetryableMultipartError} from './utils'
|
||||
|
||||
export class MultipartFallbackError extends Error {}
|
||||
|
||||
@@ -208,7 +208,7 @@ async function getUploadStatusWithRetry(
|
||||
return await getUploadStatus(jobId, token, signal)
|
||||
} catch (err) {
|
||||
throwIfAborted(signal)
|
||||
if (!isRetryableStatusError(err)) throw err
|
||||
if (!isRetryableMultipartError(err)) throw err
|
||||
lastError = err
|
||||
if (attempt < 3) await delay(500 * 2 ** (attempt - 1), signal)
|
||||
}
|
||||
@@ -216,16 +216,6 @@ async function getUploadStatusWithRetry(
|
||||
throw lastError
|
||||
}
|
||||
|
||||
function isRetryableStatusError(err: unknown) {
|
||||
return (
|
||||
err instanceof TypeError ||
|
||||
(err instanceof MultipartUploadError &&
|
||||
(err.error === 'ServiceOverloaded' ||
|
||||
err.status === undefined ||
|
||||
isRetryableHttpStatus(err.status)))
|
||||
)
|
||||
}
|
||||
|
||||
async function abortThenFallbackOrResolve(
|
||||
jobId: string,
|
||||
token: string,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {AbortError} from '#/lib/async/cancelable'
|
||||
import {isRetryableHttpStatus} from '#/lib/strings/errors'
|
||||
import {createProgressAggregator} from './aggregateProgress'
|
||||
import {MultipartUploadError} from './api'
|
||||
import {MULTIPART_CONCURRENCY, MULTIPART_MAX_ATTEMPTS} from './constants'
|
||||
import {
|
||||
type ChunkReader,
|
||||
@@ -9,7 +7,7 @@ import {
|
||||
type PartUploadResult,
|
||||
type UploadPartFn,
|
||||
} from './types'
|
||||
import {delay} from './utils'
|
||||
import {delay, isRetryableMultipartError} from './utils'
|
||||
|
||||
/**
|
||||
* Uploads every part with a concurrency cap and per-part retry, aggregating
|
||||
@@ -121,7 +119,7 @@ async function uploadPartWithRetry({
|
||||
throw new AbortError()
|
||||
}
|
||||
lastError = err
|
||||
if (!isRetryablePartError(err)) throw err
|
||||
if (!isRetryableMultipartError(err)) throw err
|
||||
if (attempt < maxAttempts) {
|
||||
await delay(500 * 2 ** (attempt - 1), signal)
|
||||
}
|
||||
@@ -129,13 +127,3 @@ async function uploadPartWithRetry({
|
||||
}
|
||||
throw lastError
|
||||
}
|
||||
|
||||
function isRetryablePartError(err: unknown) {
|
||||
return (
|
||||
err instanceof TypeError ||
|
||||
(err instanceof MultipartUploadError &&
|
||||
(err.error === 'ServiceOverloaded' ||
|
||||
err.status === undefined ||
|
||||
isRetryableHttpStatus(err.status)))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import {AbortError} from '#/lib/async/cancelable'
|
||||
import {isRetryableHttpStatus} from '#/lib/strings/errors'
|
||||
import {MultipartUploadError} from './api'
|
||||
|
||||
export function isRetryableMultipartError(err: unknown) {
|
||||
return (
|
||||
err instanceof TypeError ||
|
||||
(err instanceof MultipartUploadError &&
|
||||
(err.error === 'ServiceOverloaded' ||
|
||||
err.status === undefined ||
|
||||
isRetryableHttpStatus(err.status)))
|
||||
)
|
||||
}
|
||||
|
||||
export function delay(ms: number, signal: AbortSignal) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
||||
Reference in New Issue
Block a user