Skip to content

Commit c7a6fc9

Browse files
committed
fix(uploads): add timeout/abort to kb api fallback upload
1 parent a8ede19 commit c7a6fc9

2 files changed

Lines changed: 38 additions & 29 deletions

File tree

apps/sim/app/workspace/[workspaceId]/knowledge/hooks/use-knowledge-upload.ts

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createLogger } from '@sim/logger'
33
import { sleep } from '@sim/utils/helpers'
44
import { useQueryClient } from '@tanstack/react-query'
55
import {
6+
calculateUploadTimeoutMs,
67
DirectUploadError,
78
isTransientUploadError,
89
LARGE_FILE_THRESHOLD,
@@ -157,37 +158,45 @@ const uploadFileThroughAPI = async (
157158
formData.append('context', 'knowledge-base')
158159
if (workspaceId) formData.append('workspaceId', workspaceId)
159160

160-
const response = await fetch(KB_API_UPLOAD_ENDPOINT, {
161-
method: 'POST',
162-
body: formData,
163-
})
161+
const controller = new AbortController()
162+
const timeoutId = setTimeout(() => controller.abort(), calculateUploadTimeoutMs(file.size))
164163

165-
if (!response.ok) {
166-
let errorData: { message?: string; error?: string } | null = null
167-
try {
168-
errorData = (await response.json()) as { message?: string; error?: string }
169-
} catch {}
170-
throw new KnowledgeUploadError(
171-
`Failed to upload ${file.name}: ${errorData?.message || errorData?.error || response.statusText}`,
172-
'API_UPLOAD_ERROR',
173-
errorData
174-
)
175-
}
164+
try {
165+
const response = await fetch(KB_API_UPLOAD_ENDPOINT, {
166+
method: 'POST',
167+
body: formData,
168+
signal: controller.signal,
169+
})
176170

177-
const result = (await response.json()) as {
178-
fileInfo?: { path?: string }
179-
path?: string
180-
}
181-
const filePath = result.fileInfo?.path ?? result.path
182-
if (!filePath) {
183-
throw new KnowledgeUploadError(
184-
`Invalid upload response for ${file.name}: missing file path`,
185-
'API_UPLOAD_ERROR',
186-
result
187-
)
188-
}
171+
if (!response.ok) {
172+
let errorData: { message?: string; error?: string } | null = null
173+
try {
174+
errorData = (await response.json()) as { message?: string; error?: string }
175+
} catch {}
176+
throw new KnowledgeUploadError(
177+
`Failed to upload ${file.name}: ${errorData?.message || errorData?.error || response.statusText}`,
178+
'API_UPLOAD_ERROR',
179+
errorData
180+
)
181+
}
182+
183+
const result = (await response.json()) as {
184+
fileInfo?: { path?: string }
185+
path?: string
186+
}
187+
const filePath = result.fileInfo?.path ?? result.path
188+
if (!filePath) {
189+
throw new KnowledgeUploadError(
190+
`Invalid upload response for ${file.name}: missing file path`,
191+
'API_UPLOAD_ERROR',
192+
result
193+
)
194+
}
189195

190-
return { filePath }
196+
return { filePath }
197+
} finally {
198+
clearTimeout(timeoutId)
199+
}
191200
}
192201

193202
const toAbsoluteUrl = (path: string): string =>

apps/sim/lib/uploads/client/direct-upload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const isTransientUploadError = (error: unknown): boolean => {
7676
return error.status >= 500 && error.status < 600
7777
}
7878

79-
const calculateUploadTimeoutMs = (fileSize: number): number => {
79+
export const calculateUploadTimeoutMs = (fileSize: number): number => {
8080
const sizeInMb = fileSize / (1024 * 1024)
8181
const dynamicBudget = BASE_TIMEOUT_MS + sizeInMb * TIMEOUT_PER_MB_MS
8282
return Math.min(dynamicBudget, MAX_TIMEOUT_MS)

0 commit comments

Comments
 (0)