(&self, port: Option<u16>, timeout_ms: u64)
| 209 | signature = (port = None, timeout_ms = 5000) |
| 210 | )] |
| 211 | pub fn start(&self, port: Option<u16>, timeout_ms: u64) -> PyResult<PyRunningGraphServer> { |
| 212 | let (sender, receiver) = crossbeam_channel::bounded::<BridgeCommand>(1); |
| 213 | let (start_sender, start_receiver) = crossbeam_channel::bounded::<ServerStarted>(1); |
| 214 | let cloned_sender = sender.clone(); |
| 215 | let server = self.0.clone(); |
| 216 | |
| 217 | let join_handle = thread::spawn(move || { |
| 218 | block_on(async move { |
| 219 | let running_server = match port { |
| 220 | None => server.start().await?, |
| 221 | Some(port) => server.start_with_port(port).await?, |
| 222 | }; |
| 223 | if let Err(_) = start_sender.send(ServerStarted { |
| 224 | port: running_server.port(), |
| 225 | }) { |
| 226 | // This happens if the other end of the channel doesn't exist |
| 227 | running_server.stop().await; |
| 228 | return Ok(()); |
| 229 | }; |
| 230 | |
| 231 | let tokio_sender = running_server._get_sender().clone(); |
| 232 | tokio::task::spawn_blocking(move || { |
| 233 | match receiver.recv().expect("Failed to wait for cancellation") { |
| 234 | BridgeCommand::StopServer => tokio_sender |
| 235 | .blocking_send(()) |
| 236 | .expect("Failed to send cancellation signal"), |
| 237 | BridgeCommand::StopListening => (), |
| 238 | } |
| 239 | }); |
| 240 | let result = running_server.wait().await; |
| 241 | _ = cloned_sender.send(BridgeCommand::StopListening); |
| 242 | result |
| 243 | }) |
| 244 | }); |
| 245 | |
| 246 | let port = match start_receiver.recv_timeout(Duration::from_millis(timeout_ms)) { |
| 247 | Ok(msg) => msg.port, |
| 248 | Err(err) => { |
| 249 | match err { |
| 250 | RecvTimeoutError::Timeout => { |
| 251 | return Err(PyRuntimeError::new_err(format!( |
| 252 | "Failed to start server in {timeout_ms} milliseconds" |
| 253 | ))) |
| 254 | } |
| 255 | RecvTimeoutError::Disconnected => { |
| 256 | // failure in server start, extract the error |
| 257 | let result = join_handle.join().unwrap(); // propagate any panic |
| 258 | let err = match result { |
| 259 | Ok(_) => PyRuntimeError::new_err("Failed to start server"), |
| 260 | Err(err) => adapt_err_value(&err), |
| 261 | }; |
| 262 | return Err(err); |
| 263 | } |
| 264 | } |
| 265 | } |
| 266 | }; |
| 267 | |
| 268 | let server = PyRunningGraphServer::new(join_handle, sender, port)?; |
no test coverage detected