It definitely takes some work, but the proportions just seem off.
0.5 TC a day works out to almost $0.70 per day, which is roughly $21 per month or $252 per year.
That means heartbeat (a simple version) is 50x more expensive than storing 1 GB of data for a year on the IC.
I definitely agree that a public heartbeat canister that anyone can subscribe to and whose cycle costs are split among its subscribers would be very useful, but I don’t think the community will be able to organize around such a service in the near future…
Yeah also thought of this, but issue is that my implementation is for a self-scaling storage solution, so for example;
there is a storage canister, once it reaches a certain memory threshold it locks up for any further update calls and spins up a “brother” canister. So eventually the update calls will stop once the canister is full.
I think the only way your solution would work is to make every query call an update call, or can a query call internally call an update call?
Since inter-canister update calls take awhile, I wonder if there’s a hacky solution in here where you can set up a canister to recursively call other canisters, and only repeat the inter-canister call once the calling canister has received a response (2+ sec).
This “heartbeat” wouldn’t be as predictable in terms of timing, but would most likely be less expensive.
It’s way cheaper to do this instead of using heartbeat. I moved to running a script on a server that calls an upgrade method on my canister every 2 seconds because of costs. It would be nice if we could reduce heartbeat costs to make it as cheap as calling the canister from the “outside”.
It’s sounds like what you really want is a hook into when a canister reaches the freezing threshold so that you can provide a method that will get called where you could top up the cycles.
I wish there was an analogous inspect_message for heartbeats, where a canister can choose to accept or reject a heartbeat call and not pay any cycles if it chooses to reject it… I don’t think this exists though.
Honestly I think a way to create custom heartbeats should be provided by default by the ICP, its a feature needed for many use cases and in my opinion we shouldn’t rely on a 3rd party service that has to be trusted and somehow funded to do something so basic.
Because in my opinion having to pay to use a basic feature like custom heartbeats is just stupid, the fact its not offered by the “framework” by default and we as a community have to gather and discuss how and who will implement it even more, it looks really bad from an outside perspective. Like imagine if you were introduce a friend of your to ICP:
-“Hey how can I define a custom heartbeat?”
-“Well you can’t, the community has been discussing it but still no ETA and you’ll have to pay for it, if you don’t want to wait you can do it yourself and spend lot of cycles everyday”
Most would laugh, I welcome the nature of web3 but we should be building new stuff not a web3 version of setTimeout.
What’s the difference between that and any other feature of the IC? You pay to compute. It costs X cycles to store a value in stable64 memory, it costs Y cycles to call the management canister, it costs Z cycles to call the (community provided) cron canister. Computation as a service is the entire model.
I’m not saying that a custom-length heartbeat would be bad - there is a line between stuff the IC should provide and stuff it shouldn’t, and I’m not sure which side I think this falls on - but scheduled execution and consensus every second for potentially every canister on a subnet does have a computational cost, and the cycle cost is meant to represent that.
The difference is you pay cycles for what you actually use be it computation or storage, if I want to run a function once every 24 hours and I have to pay for useless calls every second, that is stupid. If it were a very niche use case then I’d agree with you, but this is something lots of dApps need. I want to use the IC to build new stuff not reinvent the wheel.