Motoko: forcing a round wait in self call

I want to await a call to an update on my own canister. Is there a good strategy to make sure this goes through a full consensus round?

I thought about retrying and checking the timestamp and throwing it away if it hasn’t changed, but I don’t want to just self call a hundred times and burn cycles.

Edit: I know a timer would be better here, but the interop party has requested a single atomic call and I basically want to block until I’ve processed a number of things.

Can you please clarify? Are you looking for a 1-round delay function or are you asking merely about self-awaiting? A self-await works just like any other await (specifically excluding await*), but your call may get scheduled in the same round of consensus as a short-circuit mechanism. Control still only returns to the calling site after that call has finished

I want to specifically delay one round.

1 Like

You can’t delay by one round (or X rounds for that matter) because the round concept is not exposed to the canister developers.

Edit: I know a timer would be better here, but the interop party has requested a single atomic call and I basically want to block until I’ve processed a number of things.

If you want to block until you’ve processed a number of things, it sounds like you would be able to do one self-call once the last thing you’ve processed is done and then move on? Or maybe I don’t understand what you have in mind exactly.

Probably, the easiest way to wait until the next round is to use timers. Setting a one-off timer with a minimum 1ns delay should do the trick.

This is not self call, but may be helpful await Random.blob();

2 Likes

I have a very specific use case here. I’m guessing it would be possible since before you HAD to wait one round.

The use case is perceived atomicity for the client. They’ve asked to make a call and not have it return until finished. I need to alert other canisters via one shot, but I only want to alert them one at a time and give them time to revert to an endpoint and I’ll search for their response before sending the next notification.

Currently I can’t await a timer can I?

Actually, a timer will only trigger 2 rounds out of 3 in the presence of messages. @ZenVoich’s suggestion to use Random.blob() sounds like your best bet.

Although I’m not clear on how everything is supposed to fit together. Why are you sending one shot messages and then awaiting some side-effect of said message? Why do you expect that said side-effect will take one round to materialize? (it may well do so within the same round. Or take multiple rounds.)

The target of the notification can be specified by the caller or elected by a subscriber, but they will be canisters not in our control. We can’t await their reply.

Random.blob()

I thought about this or just making sure we call something cheap on another subnet…maybe querying a balance from ICP canister which is guaranteed to be on another subnet. I’d need to find the cheapest way and the minimum number of rounds.

Is this relevant? Ic-barrier: Withhold responses, for testing etc

Old thread, called ic-barrier, it is about externally controlling when a call returns, with some trick.

This looks very interesting. It looks like it uses actually stopping the canister. Unfortunately, this won’t work for us because we need to process other incoming requests.

I thought you’d build in one hop through a proxy canister and stop that one.

Ah…that makes sense. Let me think about it a bit more.