Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement back end -> front end comm messages #218

Merged
merged 28 commits into from
Mar 6, 2023

Conversation

jmcphers
Copy link
Collaborator

@jmcphers jmcphers commented Mar 2, 2023

This change fleshes out a previously unimplemented part of the language runtime framework: specifically, it makes it possible for "comms" (client instances, such as the Environment pane) to send messages to the front end.

It also dramatically simplifies the code needed to implement a comm. Formerly, you had to provide a Rust struct that could be sent across threads (Send) and implemented a trait. After this change, the contract just gives you a Sender<Value> (where Value is any JSON data). Sending data to the channel causes it to be forwarded to the front end.

It works something like this:

graph LR
comm1 -- data --> receiver1 --> select -- metadata --> i[IOPub] -- zeromq --> Positron
comm2 -- data --> receiver2 --> select
comm3 -- data --> receiver3 --> select
Loading

That is: each comm gets its own unique Sender channel which has a unique Receiver channel. A dedicated thread runs a Select that waits for any of the comms to emit data. When a Receiver emits data, we look up the metadata associated with the comm and amend the message with the comm's ID. This gets further wrapped up with Jupyter headers and delivered to the front end via ZeroMQ.

Unit tests are included for the above that test sending data to and receiving data from a comm; the tests use a dummy comm implementation that just echoes any data sent to it. This implementation is also a useful reference for the simplest possible comm.

Finally, this change also adds retry logic to the R Language Pack's server connectivity. For now this is borrowed from the Python Language Pack, but we should have something more robust here (will file an issue).

@petetronic petetronic requested a review from kevinushey March 3, 2023 21:45
Copy link
Contributor

@kevinushey kevinushey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM; only concern is around rustfmt noise.


fn target_name(&self) -> String {
"lsp".to_string()
pub fn msg_rx(&self) -> Sender<CommChannelMsg> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function is called msg_rx but appears to return msg_tx; is that intentional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also confused how this would be used since we're just throwing away the created receiver.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've clarified the name and added a comment explaining this. In short, the LSP is sort of a dummy comm -- it has the same lifecycle (so we can start/stop/query it like a regular comm) but because it has its own TCP connection it doesn't send or receive messages over the Jupyter protocol.

@@ -274,10 +275,10 @@ fn test_kernel() {
info!("Received execute reply: {:?}", reply);
assert_eq!(reply.content.status, Status::Ok);
assert_eq!(reply.content.execution_count, 2);
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These trailing commas are kind of noisy; can we configure rustfmt to skip this sort of change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(That is, I think either form is fine -- we should ask rustfmt to accept both has-trailing-comma and no-trailing-comma forms)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, can we configure rustfmt to only run on regions of the file that we've explicitly modified?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's possible for rustfmt to accept either one -- it is supposed to be opinionated. Nor is it possible to get it to run only on changed lines.

rust-lang/rustfmt#1324

@@ -248,32 +251,38 @@ export class LanguageRuntimeAdapter
* Creates a new client instance.
*
* @param type The type of client to create
* @param params The parameters for the client; the format of this object is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any restrictions on this type (e.g. it must be a JavaScript object? it must be parsable as JSON?) I'm just wondering if there's something mildly more typed than any that we could use. But any is probably fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I checked the spec and it says that data is a dict, so I think that implies it has to be an object of some kind. I've updated the relevant types.

@jmcphers jmcphers merged commit 15203fb into main Mar 6, 2023
@wesm wesm deleted the feature/comm-channel-msg branch March 15, 2024 18:33
wesm pushed a commit that referenced this pull request Mar 28, 2024
Merge pull request #218 from posit-dev/feature/force-quit

Add force quit method
--------------------
Commit message for posit-dev/positron-python@b06f70d:

add force quit method


Authored-by: Jonathan McPherson <jonathan@rstudio.com>
Signed-off-by: Jonathan McPherson <jonathan@rstudio.com>
wesm pushed a commit that referenced this pull request Mar 28, 2024
Merge pull request #218 from posit-dev/feature/force-quit

Add force quit method
--------------------
Commit message for posit-dev/positron-python@b06f70d:

add force quit method


Authored-by: Jonathan McPherson <jonathan@rstudio.com>
Signed-off-by: Jonathan McPherson <jonathan@rstudio.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants