remote_kernels.rs

  1use futures::{channel::mpsc, StreamExt as _};
  2use gpui::AppContext;
  3use jupyter_protocol::{ExecutionState, JupyterMessage, KernelInfoReply};
  4// todo(kyle): figure out if this needs to be different
  5use runtimelib::JupyterKernelspec;
  6
  7use super::RunningKernel;
  8use jupyter_websocket_client::RemoteServer;
  9use std::fmt::Debug;
 10
 11#[derive(Debug, Clone)]
 12pub struct RemoteKernelSpecification {
 13    pub name: String,
 14    pub url: String,
 15    pub token: String,
 16    pub kernelspec: JupyterKernelspec,
 17}
 18
 19impl PartialEq for RemoteKernelSpecification {
 20    fn eq(&self, other: &Self) -> bool {
 21        self.name == other.name && self.url == other.url
 22    }
 23}
 24
 25impl Eq for RemoteKernelSpecification {}
 26
 27pub struct RemoteRunningKernel {
 28    remote_server: RemoteServer,
 29    pub working_directory: std::path::PathBuf,
 30    pub request_tx: mpsc::Sender<JupyterMessage>,
 31    pub execution_state: ExecutionState,
 32    pub kernel_info: Option<KernelInfoReply>,
 33}
 34
 35impl RemoteRunningKernel {
 36    pub async fn new(
 37        kernelspec: RemoteKernelSpecification,
 38        working_directory: std::path::PathBuf,
 39        request_tx: mpsc::Sender<JupyterMessage>,
 40        _cx: &mut AppContext,
 41    ) -> anyhow::Result<(
 42        Self,
 43        (), // Stream<Item=JupyterMessage>
 44    )> {
 45        let remote_server = RemoteServer {
 46            base_url: kernelspec.url,
 47            token: kernelspec.token,
 48        };
 49
 50        // todo: launch a kernel to get a kernel ID
 51        let kernel_id = "not-implemented";
 52
 53        let kernel_socket = remote_server.connect_to_kernel(kernel_id).await?;
 54
 55        let (mut _w, mut _r) = kernel_socket.split();
 56
 57        let (_messages_tx, _messages_rx) = mpsc::channel::<JupyterMessage>(100);
 58
 59        // let routing_task = cx.background_executor().spawn({
 60        //     async move {
 61        //         while let Some(message) = request_rx.next().await {
 62        //             w.send(message).await;
 63        //         }
 64        //     }
 65        // });
 66        // let messages_rx = r.into();
 67
 68        anyhow::Ok((
 69            Self {
 70                remote_server,
 71                working_directory,
 72                request_tx,
 73                execution_state: ExecutionState::Idle,
 74                kernel_info: None,
 75            },
 76            (),
 77        ))
 78    }
 79}
 80
 81impl Debug for RemoteRunningKernel {
 82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 83        f.debug_struct("RemoteRunningKernel")
 84            // custom debug that keeps tokens out of logs
 85            .field("remote_server url", &self.remote_server.base_url)
 86            .field("working_directory", &self.working_directory)
 87            .field("request_tx", &self.request_tx)
 88            .field("execution_state", &self.execution_state)
 89            .field("kernel_info", &self.kernel_info)
 90            .finish()
 91    }
 92}
 93
 94impl RunningKernel for RemoteRunningKernel {
 95    fn request_tx(&self) -> futures::channel::mpsc::Sender<runtimelib::JupyterMessage> {
 96        self.request_tx.clone()
 97    }
 98
 99    fn working_directory(&self) -> &std::path::PathBuf {
100        &self.working_directory
101    }
102
103    fn execution_state(&self) -> &runtimelib::ExecutionState {
104        &self.execution_state
105    }
106
107    fn set_execution_state(&mut self, state: runtimelib::ExecutionState) {
108        self.execution_state = state;
109    }
110
111    fn kernel_info(&self) -> Option<&runtimelib::KernelInfoReply> {
112        self.kernel_info.as_ref()
113    }
114
115    fn set_kernel_info(&mut self, info: runtimelib::KernelInfoReply) {
116        self.kernel_info = Some(info);
117    }
118
119    fn force_shutdown(&mut self) -> anyhow::Result<()> {
120        unimplemented!("force_shutdown")
121    }
122}