dfinity / motoko

Simple high-level language for writing Internet Computer canisters
Apache License 2.0
502 stars 98 forks source link

Manage spawned canisters #3374

Open chenyan-dfinity opened 2 years ago

chenyan-dfinity commented 2 years ago

Consider the following code with Child1 and Child2 being actor class that have identical Candid interface, but different implementations:

import Child1 "Child1";
import Child2 "Child2";

actor {
  type Child = Child1.Child1;
  let buckets : [var ?Child] = Array.init(100, null);

  public func put(index : Nat) : async () {
    let bucket = switch (buckets[index]) {
      case null { spawn(index) };
      case (?bucket) { bucket };
    };
    ...
  };

  func spawn(index: Nat) : async Child {
    let bucket = if (index > 10) {
      await Child1.Child1(#text "init args")
    } else {
      await Child2.Child2(#num index)
    };
    buckets[index] := bucket;
    bucket
  };
}

If I upgrade this canister (even with the same Wasm), the spawned canisters that were allocated pre-upgrade get lost. Of course, I can make buckets stable, then I can still remember the canister ids after the upgrade. But if the actor class Child1 or Child2 gets a new implementation, I cannot upgrade these spawned canisters even if I still remember the stable buckets array.

One idea to solve this problem is to make a special table in the Motoko stable memory to store allocated canister ids with some metadata (TBD). Before we call create_canister, we consult this table to decide if we want to reuse a previously allocated canister or create a new one. Maybe related to the named adapton idea.

chenyan-dfinity commented 2 years ago

cc @matthewhammer @ByronBecker

matthewhammer commented 2 years ago

Maybe related to the named adapton idea.

In both cases (here and in Named Adapton),

unlike in Named Adapton,

Still, despite the big differences, perhaps some intuitions from Named Adapton will be helpful.

chenyan-dfinity commented 2 years ago

the programmer chooses names to identify resources that get cached and reused across different running versions

Yes, we can draw on inspirations from adapton to see what's the best syntax to annotate this keyed/named allocation.

here, there is no "the computation" getting re-run over and over

I would argue this simplifies the problem. Essentially, we want to have keyed/named allocation for canister ids, even for unrelated computations. The only thing we instrument/monitor are the management canister calls.