Skip to content

Commit c0e3edd

Browse files
authored
Speed up SDK read polling (#24434)
## Description Waiting for 2s after the 1st failure to poll transaction can be too long. ## Test plan CI `python ./scripts/simtest/seed-search.py per_epoch_config_stress_test --test per_epoch_config_stress_tests --num-seeds 10`
1 parent 656d969 commit c0e3edd

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/sui-e2e-tests/tests/per_epoch_config_stress_tests.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder;
1616
use sui_types::transaction::{CallArg, ObjectArg, SharedObjectMutability, TransactionData};
1717
use sui_types::{SUI_DENY_LIST_OBJECT_ID, SUI_FRAMEWORK_PACKAGE_ID};
1818
use test_cluster::{TestCluster, TestClusterBuilder};
19+
use tracing::info;
1920

2021
const DENY_ADDRESS: SuiAddress = SuiAddress::ZERO;
2122

@@ -34,13 +35,13 @@ async fn per_epoch_config_stress_test() {
3435
let handle1 = {
3536
let test_env = test_env.clone();
3637
tokio::spawn(async move {
37-
run_thread(test_env, target_epoch, gas1.0, create_transfer_tx, true).await
38+
run_thread(1, test_env, target_epoch, gas1.0, create_transfer_tx, true).await
3839
})
3940
};
4041
let handle2 = {
4142
let test_env = test_env.clone();
4243
tokio::spawn(async move {
43-
run_thread(test_env, target_epoch, gas2.0, create_deny_tx, false).await
44+
run_thread(2, test_env, target_epoch, gas2.0, create_deny_tx, false).await
4445
})
4546
};
4647
tokio::time::timeout(Duration::from_secs(600), async {
@@ -52,6 +53,7 @@ async fn per_epoch_config_stress_test() {
5253
}
5354

5455
async fn run_thread<F, Fut>(
56+
thread_id: u64,
5557
test_env: Arc<TestEnv>,
5658
target_epoch: EpochId,
5759
gas_id: ObjectID,
@@ -61,12 +63,15 @@ async fn run_thread<F, Fut>(
6163
F: Fn(Arc<TestEnv>, ObjectRef) -> Fut,
6264
Fut: Future<Output = TransactionData>,
6365
{
66+
info!(?thread_id, "Thread started");
6467
let mut num_tx_succeeded = 0;
6568
let mut num_tx_failed = 0;
6669
loop {
6770
let gas = test_env.get_latest_object_ref(&gas_id).await;
6871
let tx_data = tx_creation_func(test_env.clone(), gas).await;
6972
let tx = test_env.test_cluster.sign_transaction(&tx_data).await;
73+
let tx_digest = *tx.digest();
74+
info!(?thread_id, ?tx_digest, "Sending transaction");
7075
let Ok(effects) = test_env
7176
.test_cluster
7277
.wallet
@@ -79,19 +84,32 @@ async fn run_thread<F, Fut>(
7984
continue;
8085
};
8186
if effects.status().is_ok() {
87+
info!(?thread_id, ?tx_digest, "Transaction succeeded");
8288
num_tx_succeeded += 1;
8389
} else {
90+
info!(?thread_id, ?tx_digest, "Transaction failed");
8491
num_tx_failed += 1;
8592
}
8693
let executed_epoch = effects.executed_epoch();
8794
if executed_epoch >= target_epoch {
95+
info!(
96+
?thread_id,
97+
"Reached target epoch {target_epoch}. Current {executed_epoch}."
98+
);
8899
break;
89100
}
90101
}
91102
if !tx_may_fail {
92103
assert_eq!(num_tx_failed, 0);
93104
}
94-
assert!(num_tx_succeeded + num_tx_failed > 5);
105+
assert!(
106+
num_tx_succeeded + num_tx_failed > 5,
107+
"Thread {thread_id} succeeded {num_tx_succeeded} transactions and failed {num_tx_failed} transactions"
108+
);
109+
info!(
110+
?thread_id,
111+
"Thread {thread_id} finished. Succeeded {num_tx_succeeded} transactions and failed {num_tx_failed} transactions."
112+
);
95113
}
96114

97115
async fn create_deny_tx(test_env: Arc<TestEnv>, gas: ObjectRef) -> TransactionData {

crates/sui-sdk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ bcs.workspace = true
3131
thiserror.workspace = true
3232
reqwest.workspace = true
3333

34+
mysten-common.workspace = true
3435
sui-json-rpc-api.workspace = true
3536
sui-transaction-builder.workspace = true
3637
sui-json-rpc-types.workspace = true

crates/sui-sdk/src/apis.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ use sui_types::sui_serde::BigInt;
4242
use sui_types::sui_system_state::sui_system_state_summary::SuiSystemStateSummary;
4343
use sui_types::transaction::{Transaction, TransactionData, TransactionKind};
4444

45-
const WAIT_FOR_LOCAL_EXECUTION_DELAY: Duration = Duration::from_millis(200);
46-
47-
const WAIT_FOR_LOCAL_EXECUTION_INTERVAL: Duration = Duration::from_secs(2);
45+
const WAIT_FOR_LOCAL_EXECUTION_MIN_INTERVAL: Duration = Duration::from_millis(100);
46+
const WAIT_FOR_LOCAL_EXECUTION_MAX_INTERVAL: Duration = Duration::from_secs(2);
4847

4948
/// The main read API structure with functions for retrieving data about different objects and transactions
5049
#[derive(Debug)]
@@ -1180,12 +1179,15 @@ impl QuorumDriverApi {
11801179
Duration::from_secs(60)
11811180
};
11821181
let mut poll_response = tokio::time::timeout(wait_for_local_execution_timeout, async {
1183-
// Apply a short delay to give the full node a chance to catch up.
1184-
tokio::time::sleep(WAIT_FOR_LOCAL_EXECUTION_DELAY).await;
1185-
1186-
let mut interval = tokio::time::interval(WAIT_FOR_LOCAL_EXECUTION_INTERVAL);
1182+
let mut backoff = mysten_common::backoff::ExponentialBackoff::new(
1183+
WAIT_FOR_LOCAL_EXECUTION_MIN_INTERVAL,
1184+
WAIT_FOR_LOCAL_EXECUTION_MAX_INTERVAL,
1185+
);
11871186
loop {
1188-
interval.tick().await;
1187+
// Intentionally waiting for a short delay (MIN_INTERVAL) before the 1st iteration,
1188+
// to leave time for the checkpoint containing the transaction to be certified, propagate
1189+
// to the full node, and get executed.
1190+
tokio::time::sleep(backoff.next().unwrap()).await;
11891191

11901192
if let Ok(poll_response) = self
11911193
.api

0 commit comments

Comments
 (0)