Bugfix/Openai assistant thread not found (#3426)

fix openai assistant thread not found by exponential backoff retries
This commit is contained in:
Henry Heng 2024-10-29 15:26:59 +00:00 committed by GitHub
parent cf0617537c
commit ebc4641a60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 149 additions and 92 deletions

View File

@ -267,8 +267,15 @@ class OpenAIAssistant_Agents implements INode {
// List all runs, in case existing thread is still running // List all runs, in case existing thread is still running
if (!isNewThread) { if (!isNewThread) {
const promise = (threadId: string) => { const promise = (threadId: string) => {
return new Promise<void>((resolve) => { return new Promise<void>((resolve, reject) => {
const maxWaitTime = 30000 // Maximum wait time of 30 seconds
const startTime = Date.now()
let delay = 500 // Initial delay between retries
const maxRetries = 10
let retries = 0
const timeout = setInterval(async () => { const timeout = setInterval(async () => {
try {
const allRuns = await openai.beta.threads.runs.list(threadId) const allRuns = await openai.beta.threads.runs.list(threadId)
if (allRuns.data && allRuns.data.length) { if (allRuns.data && allRuns.data.length) {
const firstRunId = allRuns.data[0].id const firstRunId = allRuns.data[0].id
@ -286,9 +293,28 @@ class OpenAIAssistant_Agents implements INode {
} }
} else { } else {
clearInterval(timeout) clearInterval(timeout)
resolve() reject(new Error(`Empty Thread: ${threadId}`))
} }
}, 500) } catch (error: any) {
if (error.response?.status === 404) {
clearInterval(timeout)
reject(new Error(`Thread not found: ${threadId}`))
} else if (error.response?.status === 429 && retries < maxRetries) {
retries++
delay *= 2
console.warn(`Rate limit exceeded, retrying in ${delay}ms...`)
} else {
clearInterval(timeout)
reject(new Error(`Unexpected error: ${error.message}`))
}
}
// Timeout condition to stop the loop if maxWaitTime is exceeded
if (Date.now() - startTime > maxWaitTime) {
clearInterval(timeout)
reject(new Error('Timeout waiting for thread to finish.'))
}
}, delay)
}) })
} }
await promise(threadId) await promise(threadId)
@ -576,9 +602,17 @@ class OpenAIAssistant_Agents implements INode {
const promise = (threadId: string, runId: string) => { const promise = (threadId: string, runId: string) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const maxWaitTime = 30000 // Maximum wait time of 30 seconds
const startTime = Date.now()
let delay = 500 // Initial delay between retries
const maxRetries = 10
let retries = 0
const timeout = setInterval(async () => { const timeout = setInterval(async () => {
try {
const run = await openai.beta.threads.runs.retrieve(threadId, runId) const run = await openai.beta.threads.runs.retrieve(threadId, runId)
const state = run.status const state = run.status
if (state === 'completed') { if (state === 'completed') {
clearInterval(timeout) clearInterval(timeout)
resolve(state) resolve(state)
@ -637,7 +671,7 @@ class OpenAIAssistant_Agents implements INode {
`Error processing thread: ${state}, Thread ID: ${threadId}, Run ID: ${runId}, Tool: ${tool.name}` `Error processing thread: ${state}, Thread ID: ${threadId}, Run ID: ${runId}, Tool: ${tool.name}`
) )
) )
break return
} }
} }
@ -656,16 +690,39 @@ class OpenAIAssistant_Agents implements INode {
} }
} catch (e) { } catch (e) {
clearInterval(timeout) clearInterval(timeout)
reject(new Error(`Error submitting tool outputs: ${state}, Thread ID: ${threadId}, Run ID: ${runId}`)) reject(
new Error(`Error submitting tool outputs: ${state}, Thread ID: ${threadId}, Run ID: ${runId}`)
)
} }
} }
} else if (state === 'cancelled' || state === 'expired' || state === 'failed') { } else if (state === 'cancelled' || state === 'expired' || state === 'failed') {
clearInterval(timeout) clearInterval(timeout)
reject( reject(
new Error(`Error processing thread: ${state}, Thread ID: ${threadId}, Run ID: ${runId}, Status: ${state}`) new Error(
`Error processing thread: ${state}, Thread ID: ${threadId}, Run ID: ${runId}, Status: ${state}`
)
) )
} }
}, 500) } catch (error: any) {
if (error.response?.status === 404 || error.response?.status === 429) {
clearInterval(timeout)
reject(new Error(`API error: ${error.response?.status} for Thread ID: ${threadId}, Run ID: ${runId}`))
} else if (retries < maxRetries) {
retries++
delay *= 2 // Exponential backoff
console.warn(`Transient error, retrying in ${delay}ms...`)
} else {
clearInterval(timeout)
reject(new Error(`Max retries reached. Error: ${error.message}`))
}
}
// Stop the loop if maximum wait time is exceeded
if (Date.now() - startTime > maxWaitTime) {
clearInterval(timeout)
reject(new Error('Timeout waiting for thread to finish.'))
}
}, delay)
}) })
} }