Opinion: The Rust CDK needs to embrace the actor model like Motoko and provide better primitives to write actor canisters

This is kind of an opinion piece but I’ve been programming canisters for around a year now.

I’ve programmed a multi canister backend with Motoko and things mostly work. The actor model is mostly embraced there.

I’m currently programming another backend with Rust and believe it is, as of today, a superior language owing to the amount of control and safety it provides. While still providing the nice productivity abstractions you expect out of a modern language. Provided you are willing to put in the time and patience to learn it.

Both these backends are multi canisters which is where the actor paradigm is supposed to shine.

Quoting Wikipedia, an actor is defined as:

An actor is a computational entity that, in response to a message it receives, can concurrently:

  • send a finite number of messages to other actors;
  • create a finite number of new actors;
  • designate the behavior to be used for the next message it receives.

Looking at Rust,

send a finite number of messages to other actors

This is basically inter-canister calls on the IC. There are 2 ways for this:

  • Using the import macro - this is broken right now
  • Using the ic_cdk::api::call::call - This mostly works but is severely undocumented and has weird quirks like even single response values have to be tuples

Secondly,

create a finite number of new actors

This is the ability to spawn new canisters by a canister. Currently we have to figure out an esoteric way of doing this which is sorta undocumented. This leads to around a 100 lines of boilerplate code that calls into the management canister and does some plumbing to give you back your canister. Motoko has a concept of actor class that Rust is missing. Rust needs an alternative of some kind that makes this API friendly.

There is also no prescribed method on how to manage these actors once they have been spawned with no guidance on how to perform upgrades or migrations. Which is a huge roadblock for adoption of multi canister backends.

Finally,

designate the behavior to be used for the next message it receives

This is basically the public methods that the canister exposes and these work as you would expect them to. No major complaints here.

As an aside, we also need better authorization primitives to be better able to gate who is allowed to execute what when calling into actors

Without the seamless availability of actors, it will be a struggle to build composable systems consisting of a fleet of actors talking to each other

P.S. Although the above reads like a rant, it is also a wish-list for things that should improve. I’m just a humble community member who only wishes to see the IC succeed.

1 Like

Can you expand on why the Motoko dev experience is abysmal?

Hi @JaMarco,

Is it cool if I retract my Motoko statement here and send you a DM with my last impressions as I had shared them earlier. Reason is I want to focus on Rust on this thread

1 Like

I thought to really use the actor model we’d have to stick to oneway calls.

See Zero-downtime upgrades of Internet Computer canisters – Blog – Joachim Breitner's Homepage

1 Like

I think that’s a limitation of how canisters are implemented, actors don’t have any such limitations from what I seem to understand.

I believe the difference is in how the response is received back. Currently with the async/await paradigm, we rely on the System API to ensure that a response is received eventually.

Actors, from what I read, have a slightly different model, where the caller’s address along with the message would be sent to the recipient actor and when the recipient actor is done with whatever it’s supposed to do, it will pass the response back as another one-way message and the initial caller has logic to handle said message.

I believe there are tradeoffs involved in both.

In the way the IC handles things, the network ensures that no messages are dropped. But canister upgrades require the canister to stop. In the actor model, message passing would be atomic and canister upgrades would not require stopping the canister explicitly.

Here’s an old video from the now defunct Channel 9 that was run by Microsoft that I found on the topic from the creator of the paradigm himself:

2 Likes

Thank you very much for these thoughts! @lwshang is currently thinking a lot over how the Rust CDK should look like. I’ll forward this to him

3 Likes