mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(jupyter): keep running event loop when waiting for messages (#26049)
Closes https://github.com/denoland/deno/issues/24421
This commit is contained in:
parent
a62c7e036a
commit
0dfd333649
2 changed files with 97 additions and 45 deletions
|
@ -357,56 +357,74 @@ pub struct JupyterReplSession {
|
||||||
|
|
||||||
impl JupyterReplSession {
|
impl JupyterReplSession {
|
||||||
pub async fn start(&mut self) {
|
pub async fn start(&mut self) {
|
||||||
|
let mut poll_worker = true;
|
||||||
loop {
|
loop {
|
||||||
let Some(msg) = self.rx.recv().await else {
|
tokio::select! {
|
||||||
break;
|
biased;
|
||||||
};
|
|
||||||
let resp = match msg {
|
|
||||||
JupyterReplRequest::LspCompletions {
|
|
||||||
line_text,
|
|
||||||
position,
|
|
||||||
} => JupyterReplResponse::LspCompletions(
|
|
||||||
self.lsp_completions(&line_text, position).await,
|
|
||||||
),
|
|
||||||
JupyterReplRequest::JsGetProperties { object_id } => {
|
|
||||||
JupyterReplResponse::JsGetProperties(
|
|
||||||
self.get_properties(object_id).await,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
JupyterReplRequest::JsEvaluate { expr } => {
|
|
||||||
JupyterReplResponse::JsEvaluate(self.evaluate(expr).await)
|
|
||||||
}
|
|
||||||
JupyterReplRequest::JsGlobalLexicalScopeNames => {
|
|
||||||
JupyterReplResponse::JsGlobalLexicalScopeNames(
|
|
||||||
self.global_lexical_scope_names().await,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
JupyterReplRequest::JsEvaluateLineWithObjectWrapping { line } => {
|
|
||||||
JupyterReplResponse::JsEvaluateLineWithObjectWrapping(
|
|
||||||
self.evaluate_line_with_object_wrapping(&line).await,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
JupyterReplRequest::JsCallFunctionOnArgs {
|
|
||||||
function_declaration,
|
|
||||||
args,
|
|
||||||
} => JupyterReplResponse::JsCallFunctionOnArgs(
|
|
||||||
self
|
|
||||||
.call_function_on_args(function_declaration, &args)
|
|
||||||
.await,
|
|
||||||
),
|
|
||||||
JupyterReplRequest::JsCallFunctionOn { arg0, arg1 } => {
|
|
||||||
JupyterReplResponse::JsCallFunctionOn(
|
|
||||||
self.call_function_on(arg0, arg1).await,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(()) = self.tx.send(resp) else {
|
maybe_message = self.rx.recv() => {
|
||||||
break;
|
let Some(msg) = maybe_message else {
|
||||||
};
|
break;
|
||||||
|
};
|
||||||
|
if self.handle_message(msg).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
poll_worker = true;
|
||||||
|
},
|
||||||
|
_ = self.repl_session.run_event_loop(), if poll_worker => {
|
||||||
|
poll_worker = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_message(
|
||||||
|
&mut self,
|
||||||
|
msg: JupyterReplRequest,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
let resp = match msg {
|
||||||
|
JupyterReplRequest::LspCompletions {
|
||||||
|
line_text,
|
||||||
|
position,
|
||||||
|
} => JupyterReplResponse::LspCompletions(
|
||||||
|
self.lsp_completions(&line_text, position).await,
|
||||||
|
),
|
||||||
|
JupyterReplRequest::JsGetProperties { object_id } => {
|
||||||
|
JupyterReplResponse::JsGetProperties(
|
||||||
|
self.get_properties(object_id).await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
JupyterReplRequest::JsEvaluate { expr } => {
|
||||||
|
JupyterReplResponse::JsEvaluate(self.evaluate(expr).await)
|
||||||
|
}
|
||||||
|
JupyterReplRequest::JsGlobalLexicalScopeNames => {
|
||||||
|
JupyterReplResponse::JsGlobalLexicalScopeNames(
|
||||||
|
self.global_lexical_scope_names().await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
JupyterReplRequest::JsEvaluateLineWithObjectWrapping { line } => {
|
||||||
|
JupyterReplResponse::JsEvaluateLineWithObjectWrapping(
|
||||||
|
self.evaluate_line_with_object_wrapping(&line).await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
JupyterReplRequest::JsCallFunctionOnArgs {
|
||||||
|
function_declaration,
|
||||||
|
args,
|
||||||
|
} => JupyterReplResponse::JsCallFunctionOnArgs(
|
||||||
|
self
|
||||||
|
.call_function_on_args(function_declaration, &args)
|
||||||
|
.await,
|
||||||
|
),
|
||||||
|
JupyterReplRequest::JsCallFunctionOn { arg0, arg1 } => {
|
||||||
|
JupyterReplResponse::JsCallFunctionOn(
|
||||||
|
self.call_function_on(arg0, arg1).await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tx.send(resp).map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn lsp_completions(
|
pub async fn lsp_completions(
|
||||||
&mut self,
|
&mut self,
|
||||||
line_text: &str,
|
line_text: &str,
|
||||||
|
|
|
@ -628,3 +628,37 @@ async fn jupyter_store_history_false() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn jupyter_http_server() -> Result<()> {
|
||||||
|
let (_ctx, client, _process) = setup().await;
|
||||||
|
client
|
||||||
|
.send(
|
||||||
|
Shell,
|
||||||
|
"execute_request",
|
||||||
|
json!({
|
||||||
|
"silent": false,
|
||||||
|
"store_history": false,
|
||||||
|
"code": r#"Deno.serve({ port: 10234 }, (req) => Response.json({ hello: "world" }))"#,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let reply = client.recv(Shell).await?;
|
||||||
|
assert_eq!(reply.header.msg_type, "execute_reply");
|
||||||
|
assert_json_subset(
|
||||||
|
reply.content,
|
||||||
|
json!({
|
||||||
|
"status": "ok",
|
||||||
|
"execution_count": 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in 0..3 {
|
||||||
|
let resp = reqwest::get("http://localhost:10234").await.unwrap();
|
||||||
|
let text: serde_json::Value = resp.json().await.unwrap();
|
||||||
|
assert_eq!(text, json!({ "hello": "world" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue