@@ -71,6 +71,9 @@ const MSP = {
7171 cli_output : [ ] ,
7272 cli_callback : null ,
7373
74+ // Add retry configuration
75+ MAX_RETRIES : 10 ,
76+
7477 read ( readInfo ) {
7578 if ( CONFIGURATOR . virtualMode ) {
7679 return ;
@@ -390,12 +393,14 @@ const MSP = {
390393 callback : callback_msp ,
391394 callbackOnError : doCallbackOnError ,
392395 start : performance . now ( ) ,
396+ attempts : 0 , // Initialize retry counter
393397 } ;
394398
395- // Always set up timeout for all requests to ensure cleanup
396- this . _setupTimeout ( requestObj , bufferOut ) ;
397-
398- this . callbacks . push ( requestObj ) ;
399+ // Track only the first outstanding request for a given code
400+ if ( ! isDuplicateRequest ) {
401+ this . _setupTimeout ( requestObj , bufferOut ) ;
402+ this . callbacks . push ( requestObj ) ;
403+ }
399404
400405 // Send message if it has data or is a new request
401406 if ( data || ! isDuplicateRequest ) {
@@ -421,15 +426,37 @@ const MSP = {
421426 } ,
422427
423428 _handleTimeout ( requestObj , bufferOut ) {
429+ // Increment retry attempts
430+ requestObj . attempts ++ ;
431+
424432 console . warn (
425433 `MSP: data request timed-out: ${ requestObj . code } ID: ${ serial . connectionId } ` +
426434 `TAB: ${ GUI . active_tab } TIMEOUT: ${ this . timeout } ` +
427- `QUEUE: ${ this . callbacks . length } (${ this . callbacks . map ( ( e ) => e . code ) } )` ,
435+ `QUEUE: ${ this . callbacks . length } (${ this . callbacks . map ( ( e ) => e . code ) } ) ` +
436+ `ATTEMPTS: ${ requestObj . attempts } /${ this . MAX_RETRIES } ` ,
428437 ) ;
429438
439+ // Check if max retries exceeded
440+ if ( requestObj . attempts >= this . MAX_RETRIES ) {
441+ console . error ( `MSP: Request ${ requestObj . code } exceeded max retries (${ this . MAX_RETRIES } ), giving up` ) ;
442+
443+ // Remove from callbacks to prevent memory leak
444+ this . _removeRequestFromCallbacks ( requestObj ) ;
445+
446+ // Call error callback if available
447+ if ( requestObj . callbackOnError && requestObj . callback ) {
448+ requestObj . callback ( ) ;
449+ }
450+
451+ return ; // Stop retrying
452+ }
453+
430454 // Clear the existing timer before retry
431455 clearTimeout ( requestObj . timer ) ;
432456
457+ // Reset start time for this retry attempt
458+ requestObj . start = performance . now ( ) ;
459+
433460 serial . send ( bufferOut , ( sendInfo ) => {
434461 if ( sendInfo . bytesSent === bufferOut . byteLength ) {
435462 // Successfully sent retry
0 commit comments