-
Notifications
You must be signed in to change notification settings - Fork 104
feat: remove ic-cdk dependency from ic-cdk-timers #641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Ready for the security review.
I left a few minor suggestions for cleanup.
TIMERS.with_borrow_mut(|timers| { | ||
let mut to_reschedule = Vec::new(); | ||
// pop every timer that should have been completed by `now`, and get ready to run its task if it exists | ||
loop { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of iterations seems to be only bounded by the number of timers (so we could run out of cycles during looping). I would prefer if we define a reasonable maximum amount of timers we process per invocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be a reasonable maximum? The system will already start interrupting it for us when we hit 500. And is the cycles cost of the loop continuing meaningful in such a case? We already check cost_call - would it be enough to just check that we've got at least 2x that remaining (since I assume the cost of the call would outweigh the rest of the code)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry what I really meant with "run out of cycles during looping" is that we hit the instruction limit of global_timer()
invocation (40B). We should never trap because we scheduled too many inter-canister calls, because if there are not enough cycles to perform a call, call_perform()
should just return an error and the cycles needed to complete execution of global_timer()
should be already reserved before the invocation starts.
One option to define a limit would be that you call A=ic0.performance_counter(0)
after executing the first iteration of the loop and stop processing timers when, e.g., ic0.performance_counter(0)+A*2 > 40B
. The chosen multiplier X should ensure that A*X exceeds the worst case instruction costs of a loop iteration.
ic-cdk-timers/src/lib.rs
Outdated
ic0::debug_print( | ||
b"[ic-cdk-timers] unable to schedule timer: not enough liquid cycles", | ||
); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in this case we need to
- put the timer in
to_reschedule
break
the loop instead of returning in order to execute the code after the loop
2 => { | ||
// Try to execute the timer again later. | ||
TIMERS.with_borrow_mut(|timers| timers.push(timer)); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it guaranteed that the timer is ever run again if update_ic0_timer()
is not called?
No description provided.