Files
codex/codex-rs/exec-server/tests/websocket.rs
jif-oai 085ffb4456 feat: move exec-server ownership (#16344)
This introduces session-scoped ownership for exec-server so ws
disconnects no longer immediately kill running remote exec processes,
and it prepares the protocol for reconnect-based resume.
- add session_id / resume_session_id to the exec-server initialize
handshake
  - move process ownership under a shared session registry
- detach sessions on websocket disconnect and expire them after a TTL
instead of killing processes immediately (we will resume based on this)
- allow a new connection to resume an existing session and take over
notifications/ownership
- I use UUID to make them not predictable as we don't have auth for now
- make detached-session expiry authoritative at resume time so teardown
wins at the TTL boundary
- reject long-poll process/read calls that get resumed out from under an
older attachment

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-10 14:11:47 +01:00

63 lines
2.0 KiB
Rust

#![cfg(unix)]
mod common;
use codex_app_server_protocol::JSONRPCError;
use codex_app_server_protocol::JSONRPCMessage;
use codex_app_server_protocol::JSONRPCResponse;
use codex_exec_server::InitializeParams;
use codex_exec_server::InitializeResponse;
use common::exec_server::exec_server;
use pretty_assertions::assert_eq;
use uuid::Uuid;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn exec_server_reports_malformed_websocket_json_and_keeps_running() -> anyhow::Result<()> {
let mut server = exec_server().await?;
server.send_raw_text("not-json").await?;
let response = server
.wait_for_event(|event| matches!(event, JSONRPCMessage::Error(_)))
.await?;
let JSONRPCMessage::Error(JSONRPCError { id, error }) = response else {
panic!("expected malformed-message error response");
};
assert_eq!(id, codex_app_server_protocol::RequestId::Integer(-1));
assert_eq!(error.code, -32600);
assert!(
error
.message
.starts_with("failed to parse websocket JSON-RPC message from exec-server websocket"),
"unexpected malformed-message error: {}",
error.message
);
let initialize_id = server
.send_request(
"initialize",
serde_json::to_value(InitializeParams {
client_name: "exec-server-test".to_string(),
resume_session_id: None,
})?,
)
.await?;
let response = server
.wait_for_event(|event| {
matches!(
event,
JSONRPCMessage::Response(JSONRPCResponse { id, .. }) if id == &initialize_id
)
})
.await?;
let JSONRPCMessage::Response(JSONRPCResponse { id, result }) = response else {
panic!("expected initialize response after malformed input");
};
assert_eq!(id, initialize_id);
let initialize_response: InitializeResponse = serde_json::from_value(result)?;
Uuid::parse_str(&initialize_response.session_id)?;
server.shutdown().await?;
Ok(())
}