Skip to content

Commit d823cb5

Browse files
authored
feat: simplify Call implementation and enable retry logic (#551)
* with_arg takes ref * SendableCall methods take &self * empty bytes * fix doctests * upgrade candid to 0.10.13 * Simplify Call implementation Get rid of the ConfigurableCall trait and the CallWithArg, CallWithArgs, and CallWithRawArgs structs. Instead, we now have a single Call struct that can be configured and executed using chainable methods. * fix lint * remove prelude mod
1 parent 7349253 commit d823cb5

15 files changed

Lines changed: 447 additions & 520 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ ic-cdk-timers = { path = "ic-cdk-timers", version = "0.12.0-alpha.1" }
3737
ic-response-codes = { path = "ic-response-codes", version = "0.1.0" }
3838
ic-management-canister-types = { path = "ic-management-canister-types", version = "0.1.0" }
3939

40-
candid = "0.10.12"
40+
candid = "0.10.13"
4141
candid_parser = "0.1.4"
4242
futures = "0.3"
4343
hex = "0.4"

e2e-tests/src/bin/api.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! The [`inspect_message`] function defined below mandates that all the update/query entrypoints must start with "call_".
33
44
use candid::Principal;
5-
use ic_cdk::{api::*, call::ConfigurableCall};
5+
use ic_cdk::api::*;
66

77
#[export_name = "canister_update call_msg_arg_data"]
88
fn call_msg_arg_data() {
@@ -19,7 +19,7 @@ fn call_msg_caller() {
1919
/// This entrypoint will call [`call_msg_deadline`] with both best-effort and guaranteed responses.
2020
#[ic_cdk::update]
2121
async fn call_msg_deadline_caller() {
22-
use ic_cdk::call::{Call, SendableCall};
22+
use ic_cdk::call::Call;
2323
// Call with best-effort responses.
2424
let reply1 = Call::new(canister_self(), "call_msg_deadline")
2525
.call_raw()

e2e-tests/src/bin/async.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use candid::Principal;
2-
use ic_cdk::call::{Call, CallError, CallResult, SendableCall};
2+
use ic_cdk::call::{Call, CallError, CallResult};
33
use ic_cdk::{query, update};
44
use lazy_static::lazy_static;
55
use std::sync::RwLock;

e2e-tests/src/bin/call.rs

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use candid::Encode;
22
use ic_cdk::api::canister_self;
3-
use ic_cdk::call::{Call, ConfigurableCall, SendableCall};
3+
use ic_cdk::call::Call;
44
use ic_cdk::update;
55

66
/// A simple endpoint that takes empty arguments.
@@ -111,44 +111,44 @@ async fn call_echo_with_args() {
111111
let bytes = Encode!(&n).unwrap();
112112
// call*
113113
let res: u32 = Call::new(canister_self(), "echo")
114-
.with_args((n,))
114+
.with_args(&(n,))
115115
.call()
116116
.await
117117
.unwrap();
118118
assert_eq!(res, n);
119119
let res: (u32,) = Call::new(canister_self(), "echo")
120-
.with_args((n,))
120+
.with_args(&(n,))
121121
.call_tuple()
122122
.await
123123
.unwrap();
124124
assert_eq!(res.0, n);
125125
let res = Call::new(canister_self(), "echo")
126-
.with_args((n,))
126+
.with_args(&(n,))
127127
.call_raw()
128128
.await
129129
.unwrap();
130130
assert_eq!(res, bytes);
131131
Call::new(canister_self(), "echo")
132-
.with_args((n,))
132+
.with_args(&(n,))
133133
.call_oneway()
134134
.unwrap();
135135
// with*
136136
let res: (u32,) = Call::new(canister_self(), "echo")
137-
.with_args((n,))
137+
.with_args(&(n,))
138138
.with_guaranteed_response()
139139
.call_tuple()
140140
.await
141141
.unwrap();
142142
assert_eq!(res.0, n);
143143
let res: (u32,) = Call::new(canister_self(), "echo")
144-
.with_args((n,))
144+
.with_args(&(n,))
145145
.change_timeout(5)
146146
.call_tuple()
147147
.await
148148
.unwrap();
149149
assert_eq!(res.0, n);
150150
let res: (u32,) = Call::new(canister_self(), "echo")
151-
.with_args((n,))
151+
.with_args(&(n,))
152152
.with_cycles(1000)
153153
.call_tuple()
154154
.await
@@ -208,4 +208,35 @@ async fn call_echo_with_raw_args() {
208208
assert_eq!(res.0, n);
209209
}
210210

211+
/// Retries the call until it succeeds.
212+
///
213+
/// Returns the number of retries.
214+
async fn retry(call_to_retry: Call<'_, '_>) -> u32 {
215+
let mut retry = 0;
216+
loop {
217+
match call_to_retry.call_raw().await {
218+
Ok(_) => break,
219+
Err(_) => {
220+
retry += 1;
221+
continue;
222+
}
223+
}
224+
}
225+
retry
226+
}
227+
228+
#[update]
229+
async fn retry_calls() {
230+
let n: u32 = 1u32;
231+
let call = Call::new(canister_self(), "foo");
232+
assert_eq!(retry(call).await, 0);
233+
let call_with_arg = Call::new(canister_self(), "echo").with_arg(n);
234+
assert_eq!(retry(call_with_arg).await, 0);
235+
let args = (n,);
236+
let call_with_args = Call::new(canister_self(), "echo").with_args(&args);
237+
assert_eq!(retry(call_with_args).await, 0);
238+
let raw_args = Encode!(&n).unwrap();
239+
let call_with_raw_args = Call::new(canister_self(), "echo").with_raw_args(&raw_args);
240+
assert_eq!(retry(call_with_raw_args).await, 0);
241+
}
211242
fn main() {}

e2e-tests/src/bin/canister_info.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,51 @@ async fn info(canister_id: Principal) -> CanisterInfoResult {
1212
canister_id,
1313
num_requested_changes: Some(20),
1414
};
15-
canister_info(request).await.unwrap()
15+
canister_info(&request).await.unwrap()
1616
}
1717

1818
#[ic_cdk::update]
1919
async fn canister_lifecycle() -> Principal {
20-
let canister_id = create_canister(CreateCanisterArgs { settings: None }, 1_000_000_000_000)
20+
let canister_id = create_canister(&CreateCanisterArgs { settings: None }, 1_000_000_000_000)
2121
.await
2222
.unwrap()
2323
.canister_id;
24-
install_code(InstallCodeArgs {
24+
install_code(&InstallCodeArgs {
2525
mode: Install,
2626
arg: vec![],
2727
wasm_module: vec![0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00],
2828
canister_id,
2929
})
3030
.await
3131
.unwrap();
32-
uninstall_code(UninstallCodeArgs { canister_id })
32+
uninstall_code(&UninstallCodeArgs { canister_id })
3333
.await
3434
.unwrap();
35-
install_code(InstallCodeArgs {
35+
install_code(&InstallCodeArgs {
3636
mode: Install,
3737
arg: vec![],
3838
wasm_module: vec![0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00],
3939
canister_id,
4040
})
4141
.await
4242
.unwrap();
43-
install_code(InstallCodeArgs {
43+
install_code(&InstallCodeArgs {
4444
mode: Reinstall,
4545
arg: vec![],
4646
wasm_module: vec![0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00],
4747
canister_id,
4848
})
4949
.await
5050
.unwrap();
51-
install_code(InstallCodeArgs {
51+
install_code(&InstallCodeArgs {
5252
mode: Upgrade(None),
5353
arg: vec![],
5454
wasm_module: vec![0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00],
5555
canister_id,
5656
})
5757
.await
5858
.unwrap();
59-
update_settings(UpdateSettingsArgs {
59+
update_settings(&UpdateSettingsArgs {
6060
settings: CanisterSettings {
6161
controllers: Some(vec![
6262
ic_cdk::api::canister_self(),

e2e-tests/src/bin/chunk.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ic_cdk::update;
1010
async fn call_create_canister() -> Principal {
1111
let arg = CreateCanisterArgs::default();
1212

13-
create_canister(arg, 1_000_000_000_000u128)
13+
create_canister(&arg, 1_000_000_000_000u128)
1414
.await
1515
.unwrap()
1616
.canister_id
@@ -23,20 +23,20 @@ async fn call_upload_chunk(canister_id: Principal, chunk: Vec<u8>) -> Vec<u8> {
2323
chunk: chunk.to_vec(),
2424
};
2525

26-
upload_chunk(arg).await.unwrap().hash
26+
upload_chunk(&arg).await.unwrap().hash
2727
}
2828

2929
#[update]
3030
async fn call_stored_chunks(canister_id: Principal) -> Vec<Vec<u8>> {
3131
let arg = StoredChunksArgs { canister_id };
32-
let hashes = stored_chunks(arg).await.unwrap();
32+
let hashes = stored_chunks(&arg).await.unwrap();
3333
hashes.into_iter().map(|v| v.hash).collect()
3434
}
3535

3636
#[update]
3737
async fn call_clear_chunk_store(canister_id: Principal) {
3838
let arg = ClearChunkStoreArgs { canister_id };
39-
clear_chunk_store(arg).await.unwrap();
39+
clear_chunk_store(&arg).await.unwrap();
4040
}
4141

4242
#[update]
@@ -57,7 +57,7 @@ async fn call_install_chunked_code(
5757
wasm_module_hash,
5858
arg: vec![],
5959
};
60-
install_chunked_code(arg).await.unwrap();
60+
install_chunked_code(&arg).await.unwrap();
6161
}
6262

6363
fn main() {}

e2e-tests/src/bin/http_request.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async fn get_without_transform() {
3838
transform: None,
3939
};
4040
let cycles = cycles_cost(&args);
41-
let res = http_request(args, cycles).await.unwrap();
41+
let res = http_request(&args, cycles).await.unwrap();
4242
assert_eq!(res.status, 200u32);
4343
assert_eq!(
4444
res.headers,
@@ -59,7 +59,7 @@ async fn post() {
5959
..Default::default()
6060
};
6161
let cycles = cycles_cost(&args);
62-
http_request(args, cycles).await.unwrap();
62+
http_request(&args, cycles).await.unwrap();
6363
}
6464

6565
/// Method is HEAD.
@@ -71,7 +71,7 @@ async fn head() {
7171
..Default::default()
7272
};
7373
let cycles = cycles_cost(&args);
74-
http_request(args, cycles).await.unwrap();
74+
http_request(&args, cycles).await.unwrap();
7575
}
7676

7777
/// The standard way to define a transform function.
@@ -101,7 +101,7 @@ async fn get_with_transform() {
101101
..Default::default()
102102
};
103103
let cycles = cycles_cost(&args);
104-
let res = http_request(args, cycles).await.unwrap();
104+
let res = http_request(&args, cycles).await.unwrap();
105105
assert_eq!(res.status, 200u32);
106106
assert_eq!(
107107
res.headers,
@@ -134,7 +134,7 @@ async fn get_with_transform_closure() {
134134
};
135135
// The transform closure takes 40 bytes.
136136
let cycles = cycles_cost(&args) + 40 * 400 * 13;
137-
let res = http_request_with_closure(args.clone(), cycles, transform)
137+
let res = http_request_with_closure(&args, cycles, transform)
138138
.await
139139
.unwrap();
140140
assert_eq!(res.status, 200u32);

0 commit comments

Comments
 (0)