99
1010package net .consensys .linea .sequencer .txselection ;
1111
12+ import static org .hyperledger .besu .plugin .data .TransactionSelectionResult .PLUGIN_SELECTION_TIMEOUT ;
13+ import static org .hyperledger .besu .plugin .data .TransactionSelectionResult .PLUGIN_SELECTION_TIMEOUT_INVALID_TX ;
14+ import static org .hyperledger .besu .plugin .data .TransactionSelectionResult .SELECTION_CANCELLED ;
15+
1216import java .time .Instant ;
1317import java .util .Map ;
1418import java .util .Optional ;
1519import java .util .Set ;
1620import java .util .concurrent .TimeUnit ;
21+ import java .util .concurrent .atomic .AtomicBoolean ;
1722import java .util .concurrent .atomic .AtomicReference ;
1823import lombok .extern .slf4j .Slf4j ;
1924import net .consensys .linea .bundles .BundlePoolService ;
2934import net .consensys .linea .sequencer .txselection .selectors .TransactionEventFilter ;
3035import org .hyperledger .besu .datatypes .Address ;
3136import org .hyperledger .besu .plugin .data .ProcessableBlockHeader ;
37+ import org .hyperledger .besu .plugin .data .TransactionSelectionResult ;
3238import org .hyperledger .besu .plugin .services .BlockchainService ;
3339import org .hyperledger .besu .plugin .services .txselection .BlockTransactionSelectionService ;
3440import org .hyperledger .besu .plugin .services .txselection .PluginTransactionSelector ;
@@ -56,6 +62,7 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
5662 private final AtomicReference <LineaTransactionSelector > currSelector = new AtomicReference <>();
5763 private final AtomicReference <Map <Address , Set <TransactionEventFilter >>> deniedEvents ;
5864 private final AtomicReference <Map <Address , Set <TransactionEventFilter >>> deniedBundleEvents ;
65+ private final AtomicBoolean isSelectionInterrupted = new AtomicBoolean (false );
5966
6067 public LineaTransactionSelectorFactory (
6168 final BlockchainService blockchainService ,
@@ -109,8 +116,6 @@ public void selectPendingTransactions(
109116 // check and send liveness bundle if any
110117 checkAndSendLivenessBundle (bts , pendingBlockHeader .getNumber ());
111118
112- if (isSelectionInterrupted ()) return ;
113-
114119 final var bundlesByBlockNumber =
115120 bundlePoolService .getBundlesByBlockNumber (pendingBlockHeader .getNumber ());
116121
@@ -121,20 +126,17 @@ public void selectPendingTransactions(
121126 .addArgument (bundlesByBlockNumber ::size )
122127 .log ();
123128
124- if (isSelectionInterrupted ()) return ;
125-
126129 final var selectionStartedAt = System .nanoTime ();
127130
128131 bundlesByBlockNumber .stream ()
129- .takeWhile (unused -> !isSelectionInterrupted ())
132+ .takeWhile (unused -> !isSelectionInterrupted . get ())
130133 .forEach (
131134 bundle -> {
132135 final var bundleStartedAt = System .nanoTime ();
133136 log .trace ("Starting evaluation of bundle {}" , bundle .bundleIdentifier ());
134137
135138 var maybeBadBundleRes =
136139 bundle .pendingTransactions ().stream ()
137- .takeWhile (unused -> !isSelectionInterrupted ())
138140 .map (bts ::evaluatePendingTransaction )
139141 .filter (evalRes -> !evalRes .selected ())
140142 .findFirst ();
@@ -143,45 +145,46 @@ public void selectPendingTransactions(
143145 final var cumulativeBundleSelectionTime = now - selectionStartedAt ;
144146 final var currentBundleSelectionTime = now - bundleStartedAt ;
145147
146- if (isSelectionInterrupted ()) {
147- log .atDebug ()
148- .setMessage (
149- "Bundle selection interrupted while processing bundle {},"
150- + " elapsed time: current bundle {}ms, cumulative {}ms" )
151- .addArgument (bundle ::bundleIdentifier )
152- .addArgument (() -> nanosToMillis (currentBundleSelectionTime ))
153- .addArgument (() -> nanosToMillis (cumulativeBundleSelectionTime ))
154- .log ();
155- rollback (bts );
156- } else {
157- if (maybeBadBundleRes .isPresent ()) {
148+ if (maybeBadBundleRes .isPresent ()) {
149+ final var notSelectedReason = maybeBadBundleRes .get ();
150+
151+ if (isSelectionInterrupted (notSelectedReason )) {
152+ isSelectionInterrupted .set (true );
158153 log .atDebug ()
159154 .setMessage (
160- "Failed bundle {}, reason {}, elapsed time: current bundle {}ms, cumulative {}ms" )
155+ "Bundle selection interrupted while processing bundle {},"
156+ + " elapsed time: current bundle {}ms, cumulative {}ms" )
161157 .addArgument (bundle ::bundleIdentifier )
162- .addArgument (maybeBadBundleRes ::get )
163158 .addArgument (() -> nanosToMillis (currentBundleSelectionTime ))
164159 .addArgument (() -> nanosToMillis (cumulativeBundleSelectionTime ))
165160 .log ();
166- rollback (bts );
167161 } else {
168162 log .atDebug ()
169163 .setMessage (
170- "Selected bundle {}, elapsed time: current bundle {}ms, cumulative {}ms" )
164+ "Failed bundle {}, reason {}, elapsed time: current bundle {}ms, cumulative {}ms" )
171165 .addArgument (bundle ::bundleIdentifier )
166+ .addArgument (notSelectedReason )
172167 .addArgument (() -> nanosToMillis (currentBundleSelectionTime ))
173168 .addArgument (() -> nanosToMillis (cumulativeBundleSelectionTime ))
174169 .log ();
175- commit (bts );
176170 }
171+
172+ rollback (bts );
173+ } else {
174+ log .atDebug ()
175+ .setMessage (
176+ "Selected bundle {}, elapsed time: current bundle {}ms, cumulative {}ms" )
177+ .addArgument (bundle ::bundleIdentifier )
178+ .addArgument (() -> nanosToMillis (currentBundleSelectionTime ))
179+ .addArgument (() -> nanosToMillis (cumulativeBundleSelectionTime ))
180+ .log ();
181+
182+ commit (bts );
177183 }
178184 });
179185 } finally {
180186 currSelector .set (null );
181- if (isSelectionInterrupted ()) {
182- // finally consume the interrupt
183- Thread .currentThread ().interrupt ();
184- }
187+ isSelectionInterrupted .set (false );
185188 }
186189 }
187190
@@ -206,7 +209,18 @@ private void checkAndSendLivenessBundle(
206209 .findFirst ();
207210
208211 if (badBundleRes .isPresent ()) {
209- log .debug ("Failed liveness bundle {}, reason {}" , livenessBundle .get (), badBundleRes );
212+ final var notSelectedReason = badBundleRes .get ();
213+
214+ if (isSelectionInterrupted (notSelectedReason )) {
215+ isSelectionInterrupted .set (true );
216+ log .debug (
217+ "Bundle selection interrupted while processing liveness bundle {}, reason {}" ,
218+ livenessBundle .get (),
219+ notSelectedReason );
220+ } else {
221+ log .debug (
222+ "Failed liveness bundle {}, reason {}" , livenessBundle .get (), notSelectedReason );
223+ }
210224 livenessService .get ().updateUptimeMetrics (false , headBlockTimestamp );
211225 rollback (bts );
212226 } else {
@@ -231,9 +245,9 @@ private long nanosToMillis(final long nanos) {
231245 return TimeUnit .NANOSECONDS .toMillis (nanos );
232246 }
233247
234- private boolean isSelectionInterrupted () {
235- // returns if the thread is interrupted without resetting the state
236- // so it can be called many times without changing the interrupt state
237- return Thread . currentThread (). isInterrupted ( );
248+ private boolean isSelectionInterrupted (final TransactionSelectionResult selectionResult ) {
249+ return selectionResult . equals ( PLUGIN_SELECTION_TIMEOUT )
250+ || selectionResult . equals ( PLUGIN_SELECTION_TIMEOUT_INVALID_TX )
251+ || selectionResult . equals ( SELECTION_CANCELLED );
238252 }
239253}
0 commit comments