Skip to content

Commit 83a1c7d

Browse files
waleedlatif1claude
andcommitted
fix(knowledge): report only the admission wait still left at the deadline
The bucket's stated wait is stored as an absolute instant so a deadline hit after a sleep carries the remainder, not the original duration. A test pins the knowledge admission wait below the retry budget the processing deadline reserves for each request. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent dba94dd commit 83a1c7d

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

‎apps/sim/lib/core/rate-limiter/provider-admission.ts‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,17 @@ export async function waitForProviderAdmission(input: ProviderAdmissionInput): P
8686
},
8787
})
8888

89-
/** The bucket's last stated wait, so a deadline hit between polls still reports when capacity returns. */
90-
let lastRetryAfterMs: number | undefined
89+
/** When the bucket last said capacity returns, so a deadline hit after a sleep reports the wait still left. */
90+
let capacityAvailableAt: number | undefined
9191
for (;;) {
9292
input.signal?.throwIfAborted()
93-
if (Date.now() >= deadlineAt) throw new ProviderAdmissionTimeoutError(lastRetryAfterMs)
93+
if (Date.now() >= deadlineAt) {
94+
const remainingMs =
95+
capacityAvailableAt === undefined ? undefined : capacityAvailableAt - Date.now()
96+
throw new ProviderAdmissionTimeoutError(
97+
remainingMs !== undefined && remainingMs > 0 ? remainingMs : undefined
98+
)
99+
}
94100
if (await isProviderQuotaExhausted(input))
95101
throw new ProviderQuotaExhaustedError(input.providerId)
96102
let result: AtomicAdmissionResult
@@ -112,7 +118,7 @@ export async function waitForProviderAdmission(input: ProviderAdmissionInput): P
112118
}
113119
if (result.allowed) return
114120
const waitMs = Math.max(1, result.retryAfterMs)
115-
if (Number.isFinite(waitMs)) lastRetryAfterMs = waitMs
121+
if (Number.isFinite(waitMs)) capacityAvailableAt = Date.now() + waitMs
116122
if (!Number.isFinite(waitMs) || waitMs >= deadlineAt - Date.now()) {
117123
if (await isProviderQuotaExhausted(input))
118124
throw new ProviderQuotaExhaustedError(input.providerId)

‎apps/sim/lib/embeddings/client.test.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
assertKnowledgeEmbeddingCapacityForDeployment,
1111
clampEmbeddingConcurrency,
1212
EMBEDDING_MAX_RETRIES,
13+
EMBEDDING_RETRY_BUDGET_MS,
1314
EmbeddingAPIError,
1415
EmbeddingOutputLimitError,
1516
EmbeddingQuotaExhaustedError,
@@ -1802,6 +1803,10 @@ describe('durable embedding batches', () => {
18021803
expect(fetchMock).not.toHaveBeenCalled()
18031804
})
18041805

1806+
it('keeps the checkpointed admission wait inside the retry budget the processing deadline reserves', () => {
1807+
expect(KNOWLEDGE_EMBEDDING_ADMISSION_WAIT_MS).toBeLessThan(EMBEDDING_RETRY_BUDGET_MS)
1808+
})
1809+
18051810
it('limits checkpointed admission waits while retaining the interactive request budget', async () => {
18061811
fetchMock.mockImplementation(() => Promise.resolve(jsonResponse(openAIBody([[1]], 7))))
18071812
await embed(['text'], { apiKey: 'fixture-key', checkpoints: memoryCheckpoints() })

0 commit comments

Comments
 (0)