mirror of
https://github.com/openai/codex.git
synced 2026-11-06 20:20:34 +00:00
Retry realtime sideband attachment while an existing call activates (#51460)
## Why Instant Connect can return a call ID before ICE activates the call, causing sideband attachment to briefly fail with HTTP `404` while the client connects media. ## What changed Retry `404` responses from `connect_existing_call_sideband` up to three times, waiting 100, 300, and 800 milliseconds. Return the error once this activation retry budget is exhausted, and preserve the existing handling of other errors. ## Testing Add WebSocket coverage for successful attachment after three `404` responses, failure after four `404` responses, and no retry on HTTP `410`. Verify that successful attachment does not overwrite the prepared session configuration. GitOrigin-RevId: 5d18ff7eeeb9abd56388808828382f7350c7ae57
This commit is contained in:
@@ -42,6 +42,7 @@ use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::oneshot;
|
||||
@@ -908,15 +909,28 @@ impl RealtimeWebsocketClient {
|
||||
default_headers: HeaderMap,
|
||||
transcript_state: RealtimeTranscriptState,
|
||||
) -> Result<RealtimeWebsocketConnection, ApiError> {
|
||||
self.connect_sideband(
|
||||
config,
|
||||
call_id,
|
||||
extra_headers,
|
||||
default_headers,
|
||||
RealtimeSessionInitialization::ExistingCall,
|
||||
transcript_state,
|
||||
)
|
||||
.await
|
||||
// Instant Connect returns a call ID before ICE activates the call. Its sideband
|
||||
// can briefly return 404 while the client connects media in parallel.
|
||||
let mut activation_delays = [100, 300, 800].into_iter();
|
||||
loop {
|
||||
let result = self
|
||||
.connect_sideband(
|
||||
config.clone(),
|
||||
call_id,
|
||||
extra_headers.clone(),
|
||||
default_headers.clone(),
|
||||
RealtimeSessionInitialization::ExistingCall,
|
||||
transcript_state.clone(),
|
||||
)
|
||||
.await;
|
||||
if matches!(&result, Err(ApiError::Api { status, .. }) if *status == StatusCode::NOT_FOUND)
|
||||
&& let Some(delay_ms) = activation_delays.next()
|
||||
{
|
||||
sleep(Duration::from_millis(delay_ms)).await;
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
async fn connect_sideband(
|
||||
|
||||
Reference in New Issue
Block a user