Skip to content

Commit

Permalink
Merge pull request #190 from posit-dev/feature/frontend-comm-spec
Browse files Browse the repository at this point in the history
Switch to new frontend comm spec
  • Loading branch information
lionel- authored Dec 23, 2023
2 parents ffd8cd0 + 7198bd8 commit 9216ec3
Show file tree
Hide file tree
Showing 16 changed files with 212 additions and 195 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions crates/amalthea/src/comm/base_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,16 @@ pub fn json_rpc_error(code: JsonRpcErrorCode, message: String) -> Value {
}
})
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct JsonRpcError {
pub error: JsonRpcErrorData,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct JsonRpcErrorData {
pub message: String,
pub code: JsonRpcErrorCode,
}
2 changes: 1 addition & 1 deletion crates/amalthea/src/comm/comm_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub enum Comm {
Other(String),
}

#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub enum CommMsg {
/// A message that is part of a Remote Procedure Call (RPC). The first value
/// is the unique ID of the RPC invocation (i.e. the Jupyter message ID),
Expand Down
15 changes: 7 additions & 8 deletions crates/amalthea/src/comm/comm_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,15 @@ impl CommManager {

// If we found it, send the message to the comm. TODO: Fewer unwraps
if let Some(index) = index {
self.open_comms
.get(index)
.unwrap()
.incoming_tx
.send(msg)
.unwrap();
let comm = self.open_comms.get(index).unwrap();
log::trace!("Comm manager: Sending message to comm '{}'", comm.comm_name);

comm.incoming_tx.send(msg).unwrap();
} else {
warn!(
log::warn!(
"Received message for unknown comm channel {}: {:?}",
comm_id, msg
comm_id,
msg
);
}
},
Expand Down
127 changes: 91 additions & 36 deletions crates/amalthea/src/comm/frontend_comm.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,105 @@
/*
* frontend_comm.rs
*
* Copyright (C) 2023 Posit Software, PBC. All rights reserved.
*
*/
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2023 Posit Software, PBC. All rights reserved.
*--------------------------------------------------------------------------------------------*/

//
// AUTO-GENERATED from frontend.json; do not edit.
//

use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;

use crate::comm::base_comm::JsonRpcErrorCode;
use crate::wire::client_event::ClientEvent;
/// Items in Params
pub type Params = serde_json::Value;

/// The method result
pub type CallMethodResult = serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "msg_type", rename_all = "snake_case")]
pub enum FrontendMessage {
Event(ClientEvent),
RpcRequest(FrontendRpcRequest),
RpcResultResponse(FrontendRpcResult),
RpcResultError(FrontendRpcError),
/// Parameters for the CallMethod method.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CallMethodParams {
/// The method to call inside the interpreter
pub method: String,

/// The parameters for `method`
pub params: Vec<Params>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct FrontendRpcRequest {
pub method: String,
pub params: Vec<Value>,
/// Parameters for the Busy method.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct BusyParams {
/// Whether the backend is busy
pub busy: bool,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct FrontendRpcResult {
pub id: String,
pub result: Value,
/// Parameters for the ShowMessage method.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct ShowMessageParams {
/// The message to show to the user.
pub message: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct FrontendRpcErrorData {
pub message: String,
pub code: JsonRpcErrorCode,
/// Parameters for the PromptState method.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct PromptStateParams {
/// Prompt for primary input.
pub input_prompt: String,

/// Prompt for incomplete input.
pub continuation_prompt: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "msg_type", rename_all = "snake_case")]
pub struct FrontendRpcError {
pub id: String,
pub error: FrontendRpcErrorData,
/// Parameters for the WorkingDirectory method.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct WorkingDirectoryParams {
/// The new working directory
pub directory: String,
}

/**
* RPC request types for the frontend comm
*/
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "method", content = "params")]
pub enum FrontendRpcRequest {
/// Run a method in the interpreter and return the result to the frontend
///
/// Unlike other RPC methods, `call_method` calls into methods implemented
/// in the interpreter and returns the result back to the frontend using
/// an implementation-defined serialization scheme.
#[serde(rename = "call_method")]
CallMethod(CallMethodParams),

}

/**
* RPC Reply types for the frontend comm
*/
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "method", content = "result")]
pub enum FrontendRpcReply {
/// The method result
CallMethodReply(CallMethodResult),

}

/**
* Front-end events for the frontend comm
*/
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "method", content = "params")]
pub enum FrontendEvent {
#[serde(rename = "busy")]
Busy(BusyParams),

#[serde(rename = "show_message")]
ShowMessage(ShowMessageParams),

#[serde(rename = "prompt_state")]
PromptState(PromptStateParams),

#[serde(rename = "working_directory")]
WorkingDirectory(WorkingDirectoryParams),

}

5 changes: 4 additions & 1 deletion crates/amalthea/src/comm/help_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use serde::Deserialize;
use serde::Serialize;

/// Possible values for the Kind parameter of the ShowHelp method.
/// Possible values for Kind in ShowHelp
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub enum ShowHelpKind {
#[serde(rename = "html")]
Expand Down Expand Up @@ -56,6 +56,7 @@ pub enum HelpRpcRequest {
/// delivered.
#[serde(rename = "show_help_topic")]
ShowHelpTopic(ShowHelpTopicParams),

}

/**
Expand All @@ -67,6 +68,7 @@ pub enum HelpRpcReply {
/// Whether the topic was found and shown. Topics are shown via a Show
/// Help notification.
ShowHelpTopicReply(bool),

}

/**
Expand All @@ -77,5 +79,6 @@ pub enum HelpRpcReply {
pub enum HelpEvent {
#[serde(rename = "show_help")]
ShowHelp(ShowHelpParams),

}

6 changes: 5 additions & 1 deletion crates/amalthea/src/comm/plot_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
use serde::Deserialize;
use serde::Serialize;

/// A rendered plot
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct PlotResult {
/// The plot data, as a base64-encoded string
pub data: String,

/// The MIME type of the plot data
pub mime_type: String,
pub mime_type: String
}

/// Parameters for the Render method.
Expand Down Expand Up @@ -43,6 +44,7 @@ pub enum PlotRpcRequest {
/// data is returned in a base64-encoded string.
#[serde(rename = "render")]
Render(RenderParams),

}

/**
Expand All @@ -53,6 +55,7 @@ pub enum PlotRpcRequest {
pub enum PlotRpcReply {
/// A rendered plot
RenderReply(PlotResult),

}

/**
Expand All @@ -63,5 +66,6 @@ pub enum PlotRpcReply {
pub enum PlotEvent {
#[serde(rename = "update")]
Update,

}

30 changes: 14 additions & 16 deletions crates/amalthea/src/socket/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crossbeam::channel::Receiver;
use crossbeam::channel::Sender;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::Value;

use crate::comm::base_comm::json_rpc_error;
use crate::comm::base_comm::JsonRpcErrorCode;
Expand Down Expand Up @@ -127,9 +126,21 @@ impl CommSocket {
Ok(m) => match request_handler(m) {
Ok(reply) => match serde_json::to_value(reply) {
Ok(value) => value,
Err(err) => self.json_rpc_internal_error(err, data),
Err(err) => json_rpc_error(
JsonRpcErrorCode::InternalError,
format!(
"Failed to process {} request: {err} (request: {data:})",
self.comm_name
),
),
},
Err(err) => self.json_rpc_internal_error(err, data),
Err(err) => json_rpc_error(
JsonRpcErrorCode::MethodNotFound,
format!(
"No handler for {} request (method not found): {err:} (request: {data:})",
self.comm_name
),
),
},
Err(err) => json_rpc_error(
JsonRpcErrorCode::InvalidRequest,
Expand All @@ -144,17 +155,4 @@ impl CommSocket {
self.outgoing_tx.send(response).unwrap();
true
}

fn json_rpc_internal_error<T>(&self, err: T, data: Value) -> Value
where
T: std::fmt::Display,
{
json_rpc_error(
JsonRpcErrorCode::InternalError,
format!(
"Failed to process {} request: {err} (request: {data:})",
self.comm_name
),
)
}
}
7 changes: 1 addition & 6 deletions crates/amalthea/src/wire/wire_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,7 @@ impl WireMessage {

fn comm_msg_type(data: Option<&Value>) -> String {
if let Some(Value::Object(map)) = data {
if let Some(Value::String(msg_type)) = map.get("msg_type") {
if msg_type == "event" {
if let Some(Value::String(event_name)) = map.get("name") {
return String::from(format!("{msg_type}/{event_name}"));
}
}
if let Some(Value::String(msg_type)) = map.get("method") {
return msg_type.clone();
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ark/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ark"
version = "0.1.39"
version = "0.1.40"
edition = "2021"
rust-version = "1.70.0"
description = """
Expand Down
Loading

0 comments on commit 9216ec3

Please sign in to comment.