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

chore: refactor node.rs into multiple modules #52

Merged
merged 3 commits into from
Nov 14, 2024

Conversation

ginnun
Copy link
Collaborator

@ginnun ginnun commented Nov 13, 2024

This PR does:

  • Split node.rs into submodules, located in different files
  • Add NodeConn::new

Please note that namings or locations might be a little off. This is a first step towards trying to keep node stuff under control. (since it is probably going to get bigger)

}

impl NodeConn {
pub fn new(underlying: pallas_network::facades::NodeClient) -> Self {
Copy link
Member

@michalrus michalrus Nov 13, 2024

Choose a reason for hiding this comment

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

In general I'm in favor of smaller files, but if you make NodeConn::new public to anyone, then we can no longer guarantee, that the module behaves soundly, e.g. calls .abort on line 105 of the new pool.rs.

Maybe let's make it pub(in crate::node), what do you think?

pub(in crate::node) fn new(underlying: pallas_network::facades::NodeClient) -> Self {
  // …
}

Cf. other options.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes sure, not a bad idea and I don't have any requirements for its visibility.

Done in bdebfe1

Side note:
Maybe, in the future we can also improve dropping NodeClient by implementing the Drop trait somewhere. It will be triggered once the struct is freed from the memory.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! 😌

I'd happily do that, but you can't run async code in a sync fn Drop::drop. At least not easily. You could create a new runtime there… Or message an existing runtime, which is what deadpool does, when their connection wrapper is dropped.

There's an AsyncDrop initiative [1] [2] in the async working group in the compiler team. This is also a list of more async issues for reference.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@michalrus Yeah, I remember this from your Slack thread.

}
}

pub async fn abort(&mut self) {
Copy link
Member

Choose a reason for hiding this comment

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

Now this is pub, and you allow passing a reference.

So after calling this, the user of NodeConn will end up with a NodeConn that has None as underlying. And after calling any other function, it will panic, since we use underlying.unwrap() everywhere else, because previously it was guaranteed that underlying will never be None.

I think the proper solution to this would be:

  1. Make underlying pub(in crate::node).
  2. Remove fn new and fn abort from NodeConn.
  3. Move their code to the pool.

This way you'll only have actual behavior methods like submit_transaction, ping, sync_progress in NodeConn, but it's complicated lifetime will be handled by the pool, and we can guarantee that it will be handled correctly.

Copy link
Collaborator Author

@ginnun ginnun Nov 14, 2024

Choose a reason for hiding this comment

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

Yes, that sounds right, I agree with your proposal. However, I assumed these were further refactorings and didn't change the inner structure of the modules themselves. Do you mind if we refactor it with another PR? I need this restructuring to build upon my changes.

Even further, I would like to be able to split various methods like submit_transaction, ping, sync_progress to their own submodules/files but combine them in one module for usage. This is because each of these methods has the potential to hold complex logic alone.

Copy link
Member

Choose a reason for hiding this comment

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

Okay, so we agreed in Slack that this would change the soundness of the interface. I pushed a fix in 9599a81.

Regarding splitting the interface into more files – definitely! Let's go for it.

Copy link
Member

@michalrus michalrus left a comment

Choose a reason for hiding this comment

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

LGTM – great!

@vladimirvolek
Copy link
Member

vladimirvolek commented Nov 14, 2024

We currently have both a node file and a node folder, which feels a bit confusing.
Can you split the node file into new folder?

image

@ginnun
Copy link
Collaborator Author

ginnun commented Nov 14, 2024

  1. I don't understand the split for connection and pool. Pool is also about connection, right?
  2. We currently have both a node file and a node folder, which feels a bit confusing.
  1. Yes, pool is a holder of multiple connection. They are related as you stated, but separating them aligns with the separation of concerns and should also be no problem in my opinion.

  2. About the node file and folder, I wanted to have the bigger conversation. The way I used is introduced in Rust 2018, and more cleaner in my opinion. My wish is to refactor all the modules in alignment with the new possibility(in another PR?). What do you think? further reading: https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html

image

@vladimirvolek
Copy link
Member

nods sounds reasonable :)

@vladimirvolek vladimirvolek merged commit 6a91bf3 into master Nov 14, 2024
4 checks passed
@michalrus michalrus deleted the chore/refactor-node branch November 14, 2024 12:36

/// Reports the sync progress of the node.
pub async fn sync_progress(&mut self) -> Result<SyncProgress, BlockfrostError> {
self.with_statequery(|generic_client: &mut localstate::GenericClient| {
Copy link
Member

Choose a reason for hiding this comment

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

@ginnun I didn't look closely enough! But look here. The changes aren't the same in the new file. Here it's after #39, and there before?

Copy link
Member

Choose a reason for hiding this comment

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

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.

3 participants