I’ve run into this a few times and I can’t find much on the forum or docs so I thought I’d raise it.
I have some code like this:
let stopPromise = systemCanister.stop_canister(stop_args);
ignore Timer.setTimer<system>(#nanoseconds(0), func() : async () {
try {
await stopPromise;
req.stopResult := ?true;
} catch (e) {
D.print("Stop canister error: " # Error.message(e));
req.stopResult := ?false;
};
});
I want to start an async call and go ahead and return quickly(in this case I may be processing many other parallel executions on other canisters) and then I want to make sure no error occurs later on so I have this timer, which I kind of hoped would form a closure and keep the promise around.
The compiler gives me:
ill-scoped await: expected async type from current scope $@anon-func-232.56, found async type from other scope $installProc_start_install
scope $@anon-func-232.56 is lib.mo:232.74-241.10
scope $installProc_start_install is lib.mo:218.128-249.6
It seems I have lost my scope and can no longer await this.
If I want to add the promises to a buffer in my enclosing function I can await them all later without losing scope, but in this case I’m using the generic TimerTool framework and each possible call is getting its own function call and scope with an orchestrator determining how many we can run in parallel.
I see the obvious issue here I’m creating a closure and this could lead to some kind of memory swell if the canister gets backed up with calls or if for some reason the calls never come back (should be impossible?).
I’d much rather stick the promises in a global queue and deal with them all at one time, but that gives me this same kind of scope error.
Is this kind of functionality off the table for technical reasons or because it is complex to implement? Or have I made a bad assumption or syntax error somewhere?
Logically, I see that my timer has not been committed to state because I don’t await a timer creation so I see that I wouldn’t be guaranteed to have this scope in the future if my function traps. Is there an awaitable timer that could create a permanent, guaranteed scope? Maybe I’m the wrong path here?