Deduplicate multipart retry checks

This commit is contained in:
vineyardbovines
2026-07-29 12:43:34 -04:00
parent 0a614e0969
commit 33d387a719
3 changed files with 17 additions and 27 deletions
+3 -13
View File
@@ -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,
+2 -14
View File
@@ -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)))
)
}
+12
View File
@@ -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) => {