Skip to content
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

feat: provide safe wrapper of global_timer_set in ic-cdk #475

Merged
merged 3 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions e2e-tests/canisters/timers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ fn add_event(event: &'static str) {
EVENTS.with(|events| events.borrow_mut().push(event));
}

#[update]
fn set_global_timer(timestamp: u64) -> u64 {
ic_cdk::api::set_global_timer(timestamp)
}

fn main() {}
33 changes: 33 additions & 0 deletions e2e-tests/tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,39 @@ fn advance_seconds(env: &StateMachine, seconds: u32) {
}
}

#[test]
fn test_set_global_timers() {
// Must be more than the queue limit (500)
let env = env();
let system_time = std::time::SystemTime::now();

env.set_time(system_time);

let wasm = cargo_build_canister("timers");
let canister_id = env.create_canister(None);
env.install_canister(canister_id, wasm, vec![], None);

call_candid::<_, ()>(&env, canister_id, "schedule_long", ())
.expect("Failed to call schedule_long");
let ts0 = system_time
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64
+ 9_000_000_000; // the long event is scheduled 9 seconds from ts0
advance_seconds(&env, 5);

// set the timer to 5 seconds from ts0
let ts1 = ts0 + 5_000_000_000;
let (previous,) = call_candid::<(u64,), (u64,)>(&env, canister_id, "set_global_timer", (ts1,))
.expect("Failed to call set_global_timer");
assert_eq!(previous, ts0);

// deactivate the timer
let (previous,) = call_candid::<(u64,), (u64,)>(&env, canister_id, "set_global_timer", (0,))
.expect("Failed to call set_global_timer");
assert_eq!(previous, ts1);
}

#[test]
fn test_canister_info() {
let env = env();
Expand Down
4 changes: 4 additions & 0 deletions src/ic-cdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

### Added

- Provide safe wrapper of global_timer_set in ic-cdk. (#475)

## [0.13.1] - 2024-03-01

### Changed
Expand Down
17 changes: 17 additions & 0 deletions src/ic-cdk/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,20 @@ pub fn cycles_burn(amount: u128) -> u128 {
}
dst
}

/// Sets global timer.
///
/// The canister can set a global timer to make the system
/// schedule a call to the exported canister_global_timer
/// Wasm method after the specified time.
/// The time must be provided as nanoseconds since 1970-01-01.
///
/// The function returns the previous value of the timer.
/// If no timer is set before invoking the function, then the function returns zero.
///
/// Passing zero as an argument to the function deactivates the timer and thus
/// prevents the system from scheduling calls to the canister's canister_global_timer Wasm method.
pub fn set_global_timer(timestamp: u64) -> u64 {
// SAFETY: ic0.global_timer_set is always safe to call.
unsafe { ic0::global_timer_set(timestamp as i64) as u64 }
}