@@ -339,21 +339,18 @@ impl SafeRedisTransaction for CleanSubmittedTransactions<'_> {
339339 continue ;
340340 }
341341
342- // Process each unique transaction_id once
343- if processed_ids. insert ( tx. transaction_id ( ) ) {
342+ // Do business logic only once per unique transaction_id
343+ let is_first_occurrence = processed_ids. insert ( tx. transaction_id ( ) ) ;
344+
345+ if is_first_occurrence {
344346 match ( tx. transaction_id ( ) , confirmed_ids. get ( tx. transaction_id ( ) ) ) {
345347 // if the transaction id is noop, we don't do anything but still clean up
346348 ( NO_OP_TRANSACTION_ID , _) => {
347- // Clean up noop transaction from Redis
348- self . remove_transaction_from_redis_submitted_zset ( pipeline, tx) ;
349349 report. noop_count += 1 ;
350350 }
351351
352- // in case of a valid ID, we check if it's in the confirmed transactions
353- // if it is confirmed, we succeed it and queue success jobs
352+ // SCENARIO 1: Transaction ID was confirmed - do confirmed business logic
354353 ( id, Some ( confirmed_tx) ) => {
355- // Clean up confirmed transaction from Redis
356- self . remove_transaction_from_redis_submitted_zset ( pipeline, tx) ;
357354 let data_key_name = self . keys . transaction_data_key_name ( id) ;
358355 pipeline. hset ( & data_key_name, "status" , "confirmed" ) ;
359356 pipeline. hset ( & data_key_name, "completed_at" , now) ;
@@ -392,26 +389,20 @@ impl SafeRedisTransaction for CleanSubmittedTransactions<'_> {
392389 & mut tx_context,
393390 self . webhook_queue . clone ( ) ,
394391 ) {
395- tracing:: error!( "Failed to queue webhook for fail : {}" , e) ;
392+ tracing:: error!( "Failed to queue webhook for confirmed transaction : {}" , e) ;
396393 }
397394 }
398395 }
399396
400397 report. moved_to_success += 1 ;
401398 }
402399
403- // if the ID is not in the confirmed transactions, we queue it for pending
400+ // SCENARIO 2: Transaction ID was NOT confirmed - check if we should replace it
404401 _ => {
405402 if let SubmittedTransactionHydrated :: Real ( tx) = tx {
406403 // Only move to pending (replaced) if it's within the latest transaction count range
407404 // This prevents false replacements due to flashblocks propagation delays
408405 if tx_nonce <= self . transaction_counts . latest {
409- // Clean up replaced transaction from Redis
410- self . remove_transaction_from_redis_submitted_zset (
411- pipeline,
412- & SubmittedTransactionHydrated :: Real ( tx. clone ( ) ) ,
413- ) ;
414-
415406 // zadd_multiple expects (score, member)
416407 replaced_transactions
417408 . push ( ( tx. queued_at , tx. transaction_id . clone ( ) ) ) ;
@@ -434,7 +425,7 @@ impl SafeRedisTransaction for CleanSubmittedTransactions<'_> {
434425 & mut tx_context,
435426 self . webhook_queue . clone ( ) ,
436427 ) {
437- tracing:: error!( "Failed to queue webhook for fail : {}" , e) ;
428+ tracing:: error!( "Failed to queue webhook for replaced transaction : {}" , e) ;
438429 }
439430 }
440431
@@ -451,11 +442,33 @@ impl SafeRedisTransaction for CleanSubmittedTransactions<'_> {
451442 "Keeping transaction in submitted state due to potential flashblocks propagation delay"
452443 ) ;
453444 // Don't increment any counter - transaction stays in submitted state
445+ // Note: We still need to check if we should clean up this hash below
454446 }
455447 }
456448 }
457449 }
458450 }
451+
452+ // Redis cleanup logic: Clean up hashes based on transaction-level decisions
453+ match ( tx. transaction_id ( ) , confirmed_ids. get ( tx. transaction_id ( ) ) ) {
454+ // SCENARIO 1: Transaction ID was confirmed - remove ALL hashes (even if beyond latest due to flashblocks)
455+ ( _, Some ( _) ) => {
456+ self . remove_transaction_from_redis_submitted_zset ( pipeline, tx) ;
457+ }
458+ // NOOP transactions: always clean up
459+ ( NO_OP_TRANSACTION_ID , _) => {
460+ self . remove_transaction_from_redis_submitted_zset ( pipeline, tx) ;
461+ }
462+ // SCENARIO 2: Transaction ID was NOT confirmed - only clean up if within latest confirmed nonce range
463+ _ => {
464+ if let SubmittedTransactionHydrated :: Real ( _) = tx {
465+ if tx_nonce <= self . transaction_counts . latest {
466+ self . remove_transaction_from_redis_submitted_zset ( pipeline, tx) ;
467+ }
468+ // If beyond latest confirmed nonce, keep in submitted state (don't clean up)
469+ }
470+ }
471+ }
459472 }
460473
461474 if !replaced_transactions. is_empty ( ) {
0 commit comments