Skip to content

Commit 51ea97e

Browse files
riptlripatel-fd
authored andcommitted
bundle: improve test coverage
1 parent cc608ab commit 51ea97e

File tree

11 files changed

+722
-93
lines changed

11 files changed

+722
-93
lines changed

contrib/test/single_test_cov.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ genhtml default.lcov \
3939
--num-spaces 1 \
4040
--legend \
4141
--highlight \
42-
--branch-coverage
42+
--branch-coverage \
43+
--quiet

src/disco/bundle/Local.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ $(call add-hdrs,fd_bundle_crank.h)
33
$(call add-objs,fd_bundle_crank,fd_disco,fd_flamenco)
44
$(call make-unit-test,test_bundle_crank,test_bundle_crank,fd_disco fd_flamenco fd_ballet fd_util)
55
$(call run-unit-test,test_bundle_crank)
6-
endif
76

87
$(call add-hdrs,fd_bundle_tile.h)
98
$(call add-objs,fd_bundle_auth fd_bundle_client,fd_disco)
@@ -17,3 +16,4 @@ endif
1716
ifdef FD_HAS_SSE # implies FD_HAS_DOUBLE
1817
$(call add-objs,fd_bundle_tile,fd_disco)
1918
endif
19+
endif

src/disco/bundle/fd_bundle_client.c

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "../fd_txn_m_t.h"
99
#include "../plugin/fd_plugin.h"
1010
#include "../../waltz/h2/fd_h2_conn.h"
11+
#include "../../waltz/http/fd_url.h" /* fd_url_unescape */
1112
#include "../../ballet/base58/fd_base58.h"
1213
#include "../../ballet/nanopb/pb_decode.h"
1314
#include "../../util/net/fd_ip4.h"
@@ -21,7 +22,7 @@
2122

2223
#define FD_BUNDLE_CLIENT_REQUEST_TIMEOUT ((long)8e9) /* 8 seconds */
2324

24-
static void
25+
void
2526
fd_bundle_client_reset( fd_bundle_tile_t * ctx ) {
2627
if( FD_UNLIKELY( ctx->tcp_sock >= 0 ) ) {
2728
if( FD_UNLIKELY( 0!=close( ctx->tcp_sock ) ) ) {
@@ -50,7 +51,8 @@ fd_bundle_client_reset( fd_bundle_tile_t * ctx ) {
5051

5152
fd_bundle_tile_backoff( ctx, fd_tickcount() );
5253

53-
fd_bundle_auther_handle_request_fail( &ctx->auther );
54+
fd_bundle_auther_reset( &ctx->auther );
55+
fd_grpc_client_reset( ctx->grpc_client );
5456
}
5557

5658
static int
@@ -152,6 +154,8 @@ fd_bundle_client_create_conn( fd_bundle_tile_t * ctx ) {
152154
# endif /* FD_HAS_OPENSSL */
153155

154156
fd_grpc_client_reset( ctx->grpc_client );
157+
ctx->last_ping_tx_ticks = fd_tickcount();
158+
ctx->last_ping_tx_nanos = fd_log_wallclock();
155159
}
156160

157161
static int
@@ -232,7 +236,7 @@ fd_bundle_client_subscribe_bundles( fd_bundle_tile_t * ctx ) {
232236
ctx->bundle_subscription_wait = 1;
233237
}
234238

235-
static void
239+
void
236240
fd_bundle_client_send_ping( fd_bundle_tile_t * ctx ) {
237241
if( FD_UNLIKELY( !ctx->grpc_client ) ) return; /* no client */
238242
fd_h2_conn_t * conn = fd_grpc_client_h2_conn( ctx->grpc_client );
@@ -247,9 +251,9 @@ fd_bundle_client_send_ping( fd_bundle_tile_t * ctx ) {
247251
}
248252
}
249253

250-
FD_FN_PURE static int
251-
fd_bundle_client_keepalive_due( fd_bundle_tile_t const * ctx,
252-
long now_ticks ) {
254+
FD_FN_PURE int
255+
fd_bundle_client_ping_is_due( fd_bundle_tile_t const * ctx,
256+
long now_ticks ) {
253257
ulong delay_min = ctx->ping_threshold_ticks>>1;
254258
ulong delay_rng = ctx->ping_threshold_ticks & ctx->ping_randomize;
255259
ulong delay = delay_min + delay_rng;
@@ -289,7 +293,7 @@ fd_bundle_client_step_reconnect( fd_bundle_tile_t * ctx,
289293
}
290294

291295
/* Send a PING */
292-
if( FD_UNLIKELY( fd_bundle_client_keepalive_due( ctx, io_ticks ) ) ) {
296+
if( FD_UNLIKELY( fd_bundle_client_ping_is_due( ctx, io_ticks ) ) ) {
293297
fd_bundle_client_send_ping( ctx );
294298
return 1;
295299
}
@@ -342,6 +346,16 @@ fd_bundle_client_step1( fd_bundle_tile_t * ctx,
342346
return;
343347
}
344348

349+
/* Did a HTTP/2 PING time out */
350+
long check_ts = fd_tickcount();
351+
if( FD_UNLIKELY( fd_bundle_client_ping_is_timeout( ctx, check_ts ) ) ) {
352+
FD_LOG_WARNING(( "Bundle gRPC timed out (HTTP/2 PING went unanswered for %.2f seconds)",
353+
( (double)ctx->ping_deadline_ticks / fd_tempo_tick_per_ns( NULL ) )*1e-9 ));
354+
ctx->defer_reset = 1;
355+
*charge_busy = 1;
356+
return;
357+
}
358+
345359
/* Drive I/O, SSL handshake, and any inflight requests */
346360
if( FD_UNLIKELY( !fd_bundle_client_drive_io( ctx, charge_busy ) ||
347361
ctx->defer_reset /* new error? */ ) ) {
@@ -713,7 +727,7 @@ fd_bundle_client_grpc_tx_complete(
713727
(void)app_ctx; (void)request_ctx;
714728
}
715729

716-
static void
730+
void
717731
fd_bundle_client_grpc_rx_start(
718732
void * app_ctx,
719733
ulong request_ctx
@@ -779,51 +793,6 @@ fd_bundle_client_request_failed( fd_bundle_tile_t * ctx,
779793
}
780794
}
781795

782-
static inline int
783-
fd_hex_unhex( int c ) {
784-
if( c>='0' && c<='9' ) return c-'0';
785-
if( c>='a' && c<='f' ) return c-'a'+0xa;
786-
if( c>='A' && c<='F' ) return c-'A'+0xa;
787-
return -1;
788-
}
789-
790-
static ulong
791-
fd_url_unescape( char * const msg,
792-
ulong const len ) {
793-
char * end = msg+len;
794-
int state = 0;
795-
char * dst = msg;
796-
for( char * src=msg; src<end; src++ ) {
797-
/* invariant: p<=msg */
798-
switch( state ) {
799-
case 0:
800-
if( FD_LIKELY( (*src)!='%' ) ) {
801-
*dst = *src;
802-
dst++;
803-
} else {
804-
state = 1;
805-
}
806-
break;
807-
case 1:
808-
if( FD_LIKELY( (*src)!='%' ) ) {
809-
*dst = (char)( ( fd_hex_unhex( *src )&0xf )<<4 );
810-
state = 2;
811-
} else {
812-
/* FIXME is 'aa%%aa' a valid escape? */
813-
*(dst++) = '%';
814-
state = 0;
815-
}
816-
break;
817-
case 2:
818-
*dst = (char)( (*dst) | ( fd_hex_unhex( *src )&0xf ) );
819-
dst++;
820-
state = 0;
821-
break;
822-
}
823-
}
824-
return (ulong)( dst-msg );
825-
}
826-
827796
void
828797
fd_bundle_client_grpc_rx_end(
829798
void * app_ctx,
@@ -860,6 +829,9 @@ fd_bundle_client_grpc_rx_end(
860829
FD_LOG_INFO(( "SubscribeBundles stream failed (gRPC status %u-%s). Reconnecting ...",
861830
resp->grpc_status, fd_grpc_status_cstr( resp->grpc_status ) ));
862831
return;
832+
case FD_BUNDLE_CLIENT_REQ_Bundle_GetBlockBuilderFeeInfo:
833+
ctx->builder_info_wait = 0;
834+
break;
863835
default:
864836
break;
865837
}
@@ -892,7 +864,7 @@ fd_bundle_client_grpc_rx_timeout(
892864
static void
893865
fd_bundle_client_grpc_ping_ack( void * app_ctx ) {
894866
fd_bundle_tile_t * ctx = app_ctx;
895-
ctx->last_ping_rx_ts = fd_tickcount();
867+
ctx->last_ping_rx_ticks = fd_tickcount();
896868
ctx->metrics.ping_ack_cnt++;
897869
long rtt_sample = fd_log_wallclock() - ctx->last_ping_tx_nanos;
898870
fd_rtt_sample( ctx->rtt, (float)rtt_sample, 0 );
@@ -949,13 +921,12 @@ fd_bundle_client_status( fd_bundle_tile_t const * ctx ) {
949921
return CONNECTING; /* not fully connected */
950922
}
951923

952-
long ping_timeout = (long)( 3UL * ctx->ping_threshold_ticks );
953-
if( FD_UNLIKELY( fd_tickcount() > ctx->last_ping_rx_ts + ping_timeout ) ) {
924+
if( FD_UNLIKELY( fd_bundle_client_ping_is_timeout( ctx, fd_tickcount() ) ) ) {
954925
return DISCONNECTED; /* possible timeout */
955926
}
956927

957928
if( FD_UNLIKELY( !fd_grpc_client_is_connected( ctx->grpc_client ) ) ) {
958-
return DISCONNECTED;
929+
return CONNECTING;
959930
}
960931

961932
/* As far as we know, the bundle connection is alive and well. */
@@ -983,3 +954,12 @@ fd_bundle_request_ctx_cstr( ulong request_ctx ) {
983954
return "unknown";
984955
}
985956
}
957+
958+
void
959+
fd_bundle_client_set_ping_interval( fd_bundle_tile_t * ctx,
960+
long ping_interval_ns ) {
961+
ctx->ping_threshold_ticks = fd_ulong_pow2_up( (ulong)
962+
( (double)ping_interval_ns * fd_tempo_tick_per_ns( NULL ) ) );
963+
ctx->ping_randomize = fd_rng_ulong( ctx->rng );
964+
ctx->ping_deadline_ticks = 4UL * ctx->ping_threshold_ticks;
965+
}

src/disco/bundle/fd_bundle_tile.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,7 @@ unprivileged_init( fd_topo_t * topo,
546546
ctx->so_rcvbuf = (int)so_rcvbuf;
547547

548548
/* Set idle ping timer */
549-
ctx->ping_threshold_ticks = fd_ulong_pow2_up( (ulong)
550-
( (double)tile->bundle.keepalive_interval_nanos * fd_tempo_tick_per_ns( NULL ) ) );
551-
ctx->ping_randomize = fd_rng_ulong( ctx->rng );
549+
fd_bundle_client_set_ping_interval( ctx, (long)tile->bundle.keepalive_interval_nanos );
552550

553551
ctx->bundle_status_plugin = 127;
554552
ctx->bundle_status_recent = FD_PLUGIN_MSG_BLOCK_ENGINE_UPDATE_STATUS_DISCONNECTED;

src/disco/bundle/fd_bundle_tile_private.h

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ struct fd_bundle_tile {
8080
/* Keepalive via HTTP/2 PINGs (randomized) */
8181
long last_ping_tx_ticks; /* last TX tickcount */
8282
long last_ping_tx_nanos;
83-
long last_ping_rx_ts; /* last RX tickcount */
83+
long last_ping_rx_ticks; /* last RX tickcount */
8484
ulong ping_randomize; /* random 64 bits */
8585
ulong ping_threshold_ticks; /* avg keepalive timeout in ticks, 2^n-1 */
86+
ulong ping_deadline_ticks; /* enforced keepalive timeout in ticks */
8687
fd_rtt_estimate_t rtt[1];
8788

8889
/* gRPC client */
@@ -187,6 +188,14 @@ fd_bundle_tile_should_stall( fd_bundle_tile_t const * ctx,
187188
void
188189
fd_bundle_tile_housekeeping( fd_bundle_tile_t * ctx );
189190

191+
/* fd_bundle_client_grpc_rx_start is the first RX callback of a stream. */
192+
193+
void
194+
fd_bundle_client_grpc_rx_start(
195+
void * app_ctx,
196+
ulong request_ctx
197+
) ;
198+
190199
/* fd_bundle_client_grpc_rx_msg is called by grpc_client when a gRPC
191200
message arrives (unary or server-streaming response). */
192201

@@ -244,6 +253,44 @@ fd_bundle_client_status( fd_bundle_tile_t const * ctx );
244253
FD_FN_CONST char const *
245254
fd_bundle_request_ctx_cstr( ulong request_ctx );
246255

256+
/* fd_bundle_client_reset frees all connection-related resources. */
257+
258+
void
259+
fd_bundle_client_reset( fd_bundle_tile_t * ctx );
260+
261+
/* Keepalive **********************************************************/
262+
263+
/* fd_bundle_client_set_ping_interval configures the approx HTTP/2 PING
264+
interval. ping_interval_ns is a rough hint, the effective ping
265+
interval will be more aggressive. */
266+
267+
void
268+
fd_bundle_client_set_ping_interval( fd_bundle_tile_t * ctx,
269+
long ping_interval_ns );
270+
271+
/* fd_bundle_client_ping_is_due returns 1 if a ping is due for sending,
272+
0 otherwise. */
273+
274+
FD_FN_PURE int
275+
fd_bundle_client_ping_is_due( fd_bundle_tile_t const * ctx,
276+
long now_ticks );
277+
278+
/* fd_bundle_client_ping_is_timeout returns 1 if a ping timeout was
279+
detected, 0 otherwise. */
280+
281+
FD_FN_PURE static inline int
282+
fd_bundle_client_ping_is_timeout( fd_bundle_tile_t const * ctx,
283+
long now_ticks ) {
284+
if( !ctx->ping_deadline_ticks ) return 0; /* timeout disabled */
285+
return now_ticks > ctx->last_ping_rx_ticks + (long)ctx->ping_deadline_ticks;
286+
}
287+
288+
/* fd_bundle_client_ping_tx enqueues a PING frame for sending. Returns
289+
1 on success and 0 on failure (occurs when frame_tx buf is full). */
290+
291+
void
292+
fd_bundle_client_send_ping( fd_bundle_tile_t * ctx );
293+
247294
FD_PROTOTYPES_END
248295

249296
#endif /* HEADER_fd_src_disco_bundle_fd_bundle_tile_private_h */

0 commit comments

Comments
 (0)