@@ -589,6 +589,10 @@ pub struct Validator {
589
589
repair_quic_endpoints : Option < [ Endpoint ; 3 ] > ,
590
590
repair_quic_endpoints_runtime : Option < TokioRuntime > ,
591
591
repair_quic_endpoints_join_handle : Option < repair:: quic_endpoint:: AsyncTryJoinHandle > ,
592
+ // This runtime is used to run the client owned by SendTransactionService.
593
+ // We don't wait for its JoinHandle here because ownership and shutdown
594
+ // are managed elsewhere. This variable is intentionally unused.
595
+ _tpu_client_next_runtime : Option < TokioRuntime > ,
592
596
}
593
597
594
598
impl Validator {
@@ -1139,6 +1143,22 @@ impl Validator {
1139
1143
) )
1140
1144
} ;
1141
1145
1146
+ // test-validator crate may start the validator in a tokio runtime
1147
+ // context which forces us to use the same runtime because a nested
1148
+ // runtime will cause panic at drop. Outside test-validator crate, we
1149
+ // always need a tokio runtime (and the respective handle) to initialize
1150
+ // the turbine QUIC endpoint.
1151
+ let current_runtime_handle = tokio:: runtime:: Handle :: try_current ( ) ;
1152
+ let tpu_client_next_runtime =
1153
+ ( current_runtime_handle. is_err ( ) && config. use_tpu_client_next ) . then ( || {
1154
+ tokio:: runtime:: Builder :: new_multi_thread ( )
1155
+ . enable_all ( )
1156
+ . worker_threads ( 2 )
1157
+ . thread_name ( "solTpuClientRt" )
1158
+ . build ( )
1159
+ . unwrap ( )
1160
+ } ) ;
1161
+
1142
1162
let rpc_override_health_check =
1143
1163
Arc :: new ( AtomicBool :: new ( config. rpc_config . disable_health_check ) ) ;
1144
1164
let (
@@ -1163,6 +1183,19 @@ impl Validator {
1163
1183
None
1164
1184
} ;
1165
1185
1186
+ let client_option = if config. use_tpu_client_next {
1187
+ let runtime_handle = tpu_client_next_runtime
1188
+ . as_ref ( )
1189
+ . map ( TokioRuntime :: handle)
1190
+ . unwrap_or_else ( || current_runtime_handle. as_ref ( ) . unwrap ( ) ) ;
1191
+ ClientOption :: TpuClientNext (
1192
+ Arc :: as_ref ( & identity_keypair) ,
1193
+ node. sockets . rpc_sts_client ,
1194
+ runtime_handle. clone ( ) ,
1195
+ )
1196
+ } else {
1197
+ ClientOption :: ConnectionCache ( connection_cache. clone ( ) )
1198
+ } ;
1166
1199
let rpc_svc_config = JsonRpcServiceConfig {
1167
1200
rpc_addr,
1168
1201
rpc_config : config. rpc_config . clone ( ) ,
@@ -1185,14 +1218,7 @@ impl Validator {
1185
1218
max_complete_transaction_status_slot,
1186
1219
max_complete_rewards_slot,
1187
1220
prioritization_fee_cache : prioritization_fee_cache. clone ( ) ,
1188
- client_option : if config. use_tpu_client_next {
1189
- ClientOption :: TpuClientNext (
1190
- Arc :: as_ref ( & identity_keypair) ,
1191
- node. sockets . rpc_sts_client ,
1192
- )
1193
- } else {
1194
- ClientOption :: ConnectionCache ( connection_cache. clone ( ) )
1195
- } ,
1221
+ client_option,
1196
1222
} ;
1197
1223
let json_rpc_service =
1198
1224
JsonRpcService :: new_with_config ( rpc_svc_config) . map_err ( ValidatorError :: Other ) ?;
@@ -1363,12 +1389,6 @@ impl Validator {
1363
1389
. as_ref ( )
1364
1390
. map ( |service| service. sender_cloned ( ) ) ;
1365
1391
1366
- // test-validator crate may start the validator in a tokio runtime
1367
- // context which forces us to use the same runtime because a nested
1368
- // runtime will cause panic at drop.
1369
- // Outside test-validator crate, we always need a tokio runtime (and
1370
- // the respective handle) to initialize the turbine QUIC endpoint.
1371
- let current_runtime_handle = tokio:: runtime:: Handle :: try_current ( ) ;
1372
1392
let turbine_quic_endpoint_runtime = ( current_runtime_handle. is_err ( )
1373
1393
&& genesis_config. cluster_type != ClusterType :: MainnetBeta )
1374
1394
. then ( || {
@@ -1686,6 +1706,7 @@ impl Validator {
1686
1706
repair_quic_endpoints,
1687
1707
repair_quic_endpoints_runtime,
1688
1708
repair_quic_endpoints_join_handle,
1709
+ _tpu_client_next_runtime : tpu_client_next_runtime,
1689
1710
} )
1690
1711
}
1691
1712
0 commit comments