Is it possible to have an async heartbeat function?

The use case is that I would like to call async functions from heartbeat.

It is possible to change update (and I presume query) to async and thereby allow async functions to be made from them. Condvar wait not supported

However the heartbeat function appears to be sync. When I try to add async to heartbeat function definition, I get the following error:

The invocation to the wallet call forward method failed with the error: An error happened during the call: 5: Wasm module of canister sbzkb-zqaaa-aaaaa-aaaiq-cai is not valid: Wasm module has an invalid function signature. Expected return type for ā€˜canister_heartbeatā€™, got [I32]

2 Likes

Rust or Motoko?

(This question is too short for the forum)

In rust.

(The answer is too short for forum)

Just based on your error message, is your heartbeat function returning an i32? Try it without a return type.

The heart beat function is not returning a i32

if I have the function without async,

#[export_name = ā€œcanister_heartbeatā€]
fn heartbeat_fn () {
ic_cdk::print(ā€œniceā€);
}

works fine.

However with async, not so.

#[export_name = ā€œcanister_heartbeatā€]
async fn heartbeat_fn () {
ic_cdk::print(ā€œniceā€);
}
ā€¦
Installing code for canister dfx_hello, with canister_id tzq7c-xqaaa-aaaaa-aaamq-cai
The invocation to the wallet call forward method failed with the error: An error happened during the call: 5: Wasm module of canister tzq7c-xqaaa-aaaaa-aaamq-cai is not valid: Wasm module has an invalid function signature. Expected return type for ā€˜canister_heartbeatā€™, got [I32].

1 Like

Did you ever get this sorted? I am trying to get a canister_heartbeat function working right now and Iā€™m hoping to do cross canister calls from it, I hope this works

I was not able to. It would be very useful to have this heartbeat in an async context.

1 Like

You should at least be able to do ic_cdk::spawn

1 Like

At least in Motoko, the heartbeat system function can definitely make and await on calls to other canisters.

See the docs:

As an async function, Alarmā€™s hearbeat function is free to call other asynchronous functions (the inner call to ring() above is an example), as well as shared functions of other c

That would be strange if it worked in Motoko but not in Rustā€¦

1 Like
#[heartbeat]
fn tick() {
  ic_cdk::block_on(async_function());
}

or

#[heartbeat]
fn tick() {
  ic_cdk::block_on(async {
    async_function_1().await;
    async_function_2().await;
  });
}
2 Likes

This definitely works, but you want to use ic_cdk::spawn now as ic_cdk::block_on was a misnomer and is deprecated.

2 Likes