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

feat(BOUN-1236): add client code for canister #2426

Open
wants to merge 1 commit into
base: or-salt-log-1
Choose a base branch
from

Conversation

rikonor
Copy link
Contributor

@rikonor rikonor commented Nov 4, 2024

This PR adds the client code for the canister. It will later be used by ic-boundary to interact with the canister.

@rikonor rikonor self-assigned this Nov 4, 2024
@rikonor rikonor requested a review from a team as a code owner November 4, 2024 19:53
@github-actions github-actions bot added the feat label Nov 4, 2024
Copy link
Contributor

@nikolay-komarevskiy nikolay-komarevskiy left a comment

Choose a reason for hiding this comment

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

Great job! Left some questions/suggestions.


#[derive(Clone)]
pub struct Canister {
agent: Agent,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do You intend to unit test register() and other implementations? Having an Agent field would make it a bit difficult, i guess. Consider using generics with traits to facilitate testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does make sense to do this but I would rather do it for CanisterMethods and then we can unit test the Tracker part. This would be more valuable because the Tracker is basically a state machine with more involved logic than these simple Canister methods.

use anyhow::{anyhow, Context};
use async_trait::async_trait;
use candid::{Decode, Encode, Principal};
use ic_canister_client::Agent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't one use agent-rs directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is what we discussed during standup - this Agent is a different implementation that allows you to specify a Sender, which the regular Agent implementation does not.

Copy link
Contributor

@nikolay-komarevskiy nikolay-komarevskiy Nov 6, 2024

Choose a reason for hiding this comment

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

drop a comment in code plz

}

#[async_trait]
pub trait Register: Sync + Send {
Copy link
Contributor

Choose a reason for hiding this comment

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

Curios, why do You need Sync + Send here. Is there going to be concurrency involved?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is required because Register is an async trait.


let resp = self
.agent
.execute_update(
Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment above regarding Agent and unit testing. IMO a trait would be useful here for unit testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would we be unit testing though? These are very thin functions that just make use of the underlying agent.

Copy link
Contributor

Choose a reason for hiding this comment

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

What would we be unit testing though?

You could test for the expected errors, cause ATM this is not possible, i suppose. It's just a suggestion, if this function remains thin, maybe it's an overkill.

#[automock]
#[async_trait]
pub trait ExecutesCalls: Sync + Send {
    async fn execute_update(&self) -> Result<....>;
    async fn execute_query(&self) -> Result<...>;
}

pub struct Canister<Agent> {
    agent: Agent,
}

impl<Agent: ExecutesCalls> Register for Canister<Agent> {
    async fn register(&self) -> Result<(), String> {
        let response = self.agent.execute_update();
        ...
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants