Skip to content

Commit

Permalink
clean up timers!
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmjs committed Jan 17, 2024
1 parent 9352113 commit 8e1d924
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 182 deletions.
2 changes: 1 addition & 1 deletion src/compiler/rust/canister/src/ic/candid_decode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::convert::TryInto;

use wasmedge_quickjs::{Context, JsArrayBuffer, JsFn, JsString, JsValue};
use wasmedge_quickjs::{Context, JsFn, JsValue};

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
31 changes: 14 additions & 17 deletions src/compiler/rust/canister/src/ic/clear_timer.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
use std::convert::TryInto;
use wasmedge_quickjs::{Context, JsFn, JsValue};

use quickjs_wasm_rs::{CallbackArg, JSContextRef, JSValueRef};
pub struct NativeFunction;
impl JsFn for NativeFunction {
fn call(context: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue {
let timer_id_string = if let JsValue::String(js_string) = argv.get(0).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};
let timer_id_u64: u64 = timer_id_string.parse().unwrap();
let timer_id = ic_cdk_timers::TimerId::from(slotmap::KeyData::from_ffi(timer_id_u64));

pub fn native_function<'a>(
context: &'a JSContextRef,
_this: &CallbackArg,
args: &[CallbackArg],
) -> Result<JSValueRef<'a>, anyhow::Error> {
let timer_id_vec_u8: Vec<u8> = args
.get(0)
.expect("clearTimer must have one argument")
.to_js_value()?
.try_into()?;
ic_cdk_timers::clear_timer(timer_id);

let timer_id_u64: u64 = candid::decode_one(&timer_id_vec_u8)?;
let timer_id = ic_cdk_timers::TimerId::from(slotmap::KeyData::from_ffi(timer_id_u64));

ic_cdk_timers::clear_timer(timer_id);
context.undefined_value()
JsValue::UnDefined
}
}
42 changes: 20 additions & 22 deletions src/compiler/rust/canister/src/ic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod candid_encode;
mod canister_balance;
mod canister_balance128;
mod canister_version;
// mod clear_timer;
mod clear_timer;
mod data_certificate;
mod id;
mod instruction_counter;
Expand All @@ -29,8 +29,8 @@ mod reject;
// mod reject_message;
mod reply_raw;
mod set_certified_data;
// mod set_timer;
// mod set_timer_interval;
mod set_timer;
mod set_timer_interval;
mod stable64_grow;
mod stable64_read;
mod stable64_size;
Expand Down Expand Up @@ -133,13 +133,12 @@ pub fn register(context: &mut wasmedge_quickjs::Context) {
.into(),
);

// ic.set_property(
// "clearTimer",
// context
// .wrap_callback2(clear_timer::native_function)
// .unwrap(),
// )
// .unwrap();
ic.set(
"clearTimer",
context
.new_function::<clear_timer::NativeFunction>("")
.into(),
);

ic.set(
"dataCertificate",
Expand Down Expand Up @@ -265,18 +264,17 @@ pub fn register(context: &mut wasmedge_quickjs::Context) {
.into(),
);

// ic.set_property(
// "setTimer",
// context.wrap_callback2(set_timer::native_function).unwrap(),
// )
// .unwrap();
// ic.set_property(
// "setTimerInterval",
// context
// .wrap_callback2(set_timer_interval::native_function)
// .unwrap(),
// )
// .unwrap();
ic.set(
"setTimer",
context.new_function::<set_timer::NativeFunction>("").into(),
);

ic.set(
"setTimerInterval",
context
.new_function::<set_timer_interval::NativeFunction>("")
.into(),
);

ic.set(
"stable64Grow",
Expand Down
108 changes: 49 additions & 59 deletions src/compiler/rust/canister/src/ic/set_timer.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,53 @@
use std::convert::TryInto;

use quickjs_wasm_rs::{to_qjs_value, CallbackArg, JSContextRef, JSValue, JSValueRef};
use slotmap::Key;

use crate::CONTEXT;

pub fn native_function<'a>(
context: &'a JSContextRef,
_this: &CallbackArg,
args: &[CallbackArg],
) -> Result<JSValueRef<'a>, anyhow::Error> {
let candid_encoded_array_buffer: Vec<u8> = args
.get(0)
.expect("performanceCounter must have one argument")
.to_js_value()?
.try_into()?;

let delay_as_u64: u64 = candid::decode_one(&candid_encoded_array_buffer)?;

let delay = core::time::Duration::new(delay_as_u64, 0);

let callback_id: String = args
.get(1)
.expect("An argument for 'callback' was not provided")
.to_js_value()?
.try_into()?;

let closure = move || {
CONTEXT.with(|context| {
let mut context = context.borrow_mut();
let context = context.as_mut().unwrap();

let global = context.global_object().unwrap();

let timer_callback = global
.get_property("_azleTimerCallbacks")
.unwrap()
.get_property(callback_id.as_str())
.unwrap_or_else(|e| ic_cdk::api::trap(e.to_string().as_str()));

// TODO I am not sure what the first parameter to call is supposed to be
let callback_result = timer_callback.call(&timer_callback, &[]);

if let Err(e) = callback_result {
ic_cdk::api::trap(e.to_string().as_str())
}
});
};

let timer_id: ic_cdk_timers::TimerId = ic_cdk_timers::set_timer(delay, closure);
let timer_id_as_u64: u64 = timer_id.data().as_ffi();
let timer_id_candid_encoded_bytes: JSValue = candid::encode_one(timer_id_as_u64)
.unwrap_or_else(|e| {
// If something goes wrong we need to clear the timer before
// throwing to the JS above.
ic_cdk_timers::clear_timer(timer_id);
ic_cdk::api::trap(e.to_string().as_str());
})
.into();

to_qjs_value(&context, &timer_id_candid_encoded_bytes)
use wasmedge_quickjs::{AsObject, Context, JsFn, JsValue};

use crate::RUNTIME;

pub struct NativeFunction;
impl JsFn for NativeFunction {
fn call(context: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue {
let delay_string = if let JsValue::String(js_string) = argv.get(0).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};
let delay_u64: u64 = delay_string.parse().unwrap();
let delay = core::time::Duration::new(delay_u64, 0);

let callback_id = if let JsValue::String(js_string) = argv.get(1).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let closure = move || {
RUNTIME.with(|runtime| {
let mut runtime = runtime.borrow_mut();
let runtime = runtime.as_mut().unwrap();

runtime.run_with_context(|context| {
let global = context.get_global();

let timer_callback = global
.get("_azleTimerCallbacks")
.to_obj()
.unwrap()
.get(callback_id.as_str())
.to_function()
.unwrap();

timer_callback.call(&[]);

// TODO handle errors
});
});
};

let timer_id: ic_cdk_timers::TimerId = ic_cdk_timers::set_timer(delay, closure);
let timer_id_u64: u64 = timer_id.data().as_ffi();

context.new_string(&timer_id_u64.to_string()).into()
}
}
108 changes: 49 additions & 59 deletions src/compiler/rust/canister/src/ic/set_timer_interval.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,53 @@
use std::convert::TryInto;

use quickjs_wasm_rs::{to_qjs_value, CallbackArg, JSContextRef, JSValue, JSValueRef};
use slotmap::Key;

use crate::CONTEXT;

pub fn native_function<'a>(
context: &'a JSContextRef,
_this: &CallbackArg,
args: &[CallbackArg],
) -> Result<JSValueRef<'a>, anyhow::Error> {
let candid_encoded_array_buffer: Vec<u8> = args
.get(0)
.expect("performanceCounter must have one argument")
.to_js_value()?
.try_into()?;

let interval_as_u64: u64 = candid::decode_one(&candid_encoded_array_buffer)?;

let interval = core::time::Duration::new(interval_as_u64, 0);

let callback_id: String = args
.get(1)
.expect("An argument for 'callback' was not provided")
.to_js_value()?
.try_into()?;

let closure = move || {
CONTEXT.with(|context| {
let mut context = context.borrow_mut();
let context = context.as_mut().unwrap();

let global = context.global_object().unwrap();

let timer_callback = global
.get_property("_azleTimerCallbacks")
.unwrap()
.get_property(callback_id.as_str())
.unwrap_or_else(|e| ic_cdk::api::trap(e.to_string().as_str()));

// TODO I am not sure what the first parameter to call is supposed to be
let callback_result = timer_callback.call(&timer_callback, &[]);

if let Err(e) = callback_result {
ic_cdk::api::trap(e.to_string().as_str())
}
});
};

let timer_id: ic_cdk_timers::TimerId = ic_cdk_timers::set_timer_interval(interval, closure);
let timer_id_as_u64: u64 = timer_id.data().as_ffi();
let timer_id_candid_encoded_bytes: JSValue = candid::encode_one(timer_id_as_u64)
.unwrap_or_else(|e| {
// If something goes wrong we need to clear the timer before
// throwing to the JS above.
ic_cdk_timers::clear_timer(timer_id);
ic_cdk::api::trap(e.to_string().as_str());
})
.into();

to_qjs_value(&context, &timer_id_candid_encoded_bytes)
use wasmedge_quickjs::{AsObject, Context, JsFn, JsValue};

use crate::RUNTIME;

pub struct NativeFunction;
impl JsFn for NativeFunction {
fn call(context: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue {
let interval_string = if let JsValue::String(js_string) = argv.get(0).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};
let interval_u64: u64 = interval_string.parse().unwrap();
let interval = core::time::Duration::new(interval_u64, 0);

let callback_id = if let JsValue::String(js_string) = argv.get(1).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let closure = move || {
RUNTIME.with(|runtime| {
let mut runtime = runtime.borrow_mut();
let runtime = runtime.as_mut().unwrap();

runtime.run_with_context(|context| {
let global = context.get_global();

let timer_callback = global
.get("_azleTimerCallbacks")
.to_obj()
.unwrap()
.get(callback_id.as_str())
.to_function()
.unwrap();

timer_callback.call(&[]);

// TODO handle errors
});
});
};

let timer_id: ic_cdk_timers::TimerId = ic_cdk_timers::set_timer_interval(interval, closure);
let timer_id_u64: u64 = timer_id.data().as_ffi();

context.new_string(&timer_id_u64.to_string()).into()
}
}
2 changes: 1 addition & 1 deletion src/lib/ic/clear_timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function clearTimer(timerId: TimerId): Void {
return undefined as any;
}

globalThis._azleIc.clearTimer(encode(TimerId, timerId).buffer);
globalThis._azleIc.clearTimer(timerId.toString());

const timerCallbackId = globalThis._azleIcTimers[timerId.toString()];

Expand Down
13 changes: 5 additions & 8 deletions src/lib/ic/set_timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@ export function setTimer(

const timerCallbackId = `_timer_${v4()}`;

const timerId = decode(
nat64,
globalThis._azleIc.setTimer(
encode(nat64, delay).buffer,
timerCallbackId
)
const timerId = globalThis._azleIc.setTimer(
delay.toString(),
timerCallbackId
);

globalThis._azleIcTimers[timerId.toString()] = timerCallbackId;
globalThis._azleIcTimers[timerId] = timerCallbackId;

globalThis._azleTimerCallbacks[timerCallbackId] = () => {
try {
Expand All @@ -43,5 +40,5 @@ export function setTimer(
}
};

return timerId;
return BigInt(timerId);
}
Loading

0 comments on commit 8e1d924

Please sign in to comment.