@@ -124,8 +124,6 @@ public class DefaultKafkaProducerFactory<K, V> extends KafkaResourceFactory
124124
125125 private final ThreadLocal <CloseSafeProducer <K , V >> threadBoundProducers = new ThreadLocal <>();
126126
127- private final ThreadLocal <Integer > threadBoundProducerEpochs = new ThreadLocal <>();
128-
129127 private final AtomicInteger epoch = new AtomicInteger ();
130128
131129 private final AtomicInteger clientIdCounter = new AtomicInteger ();
@@ -543,7 +541,7 @@ private Producer<K, V> doCreateProducer(@Nullable String txIdPrefix) {
543541 }
544542 if (this .producer == null ) {
545543 this .producer = new CloseSafeProducer <>(createKafkaProducer (), this ::removeProducer ,
546- this .physicalCloseTimeout , this .beanName );
544+ this .physicalCloseTimeout , this .beanName , this . epoch . get () );
547545 this .listeners .forEach (listener -> listener .producerAdded (this .producer .clientId , this .producer ));
548546 }
549547 return this .producer ;
@@ -552,22 +550,17 @@ private Producer<K, V> doCreateProducer(@Nullable String txIdPrefix) {
552550
553551 private Producer <K , V > getOrCreateThreadBoundProducer () {
554552 CloseSafeProducer <K , V > tlProducer = this .threadBoundProducers .get ();
555- if (this .threadBoundProducerEpochs .get () == null ) {
556- this .threadBoundProducerEpochs .set (this .epoch .get ());
557- }
558- if (tlProducer != null
559- && (this .epoch .get () != this .threadBoundProducerEpochs .get () || expire (tlProducer ))) {
553+ if (tlProducer != null && (this .epoch .get () != tlProducer .epoch || expire (tlProducer ))) {
560554 closeThreadBoundProducer ();
561555 tlProducer = null ;
562556 }
563557 if (tlProducer == null ) {
564558 tlProducer = new CloseSafeProducer <>(createKafkaProducer (), this ::removeProducer ,
565- this .physicalCloseTimeout , this .beanName );
559+ this .physicalCloseTimeout , this .beanName , this . epoch . get () );
566560 for (Listener <K , V > listener : this .listeners ) {
567561 listener .producerAdded (tlProducer .clientId , tlProducer );
568562 }
569563 this .threadBoundProducers .set (tlProducer );
570- this .threadBoundProducerEpochs .set (this .epoch .get ());
571564 }
572565 return tlProducer ;
573566 }
@@ -699,7 +692,9 @@ boolean cacheReturner(CloseSafeProducer<K, V> producerToRemove, Duration timeout
699692 else {
700693 synchronized (this .cache ) {
701694 BlockingQueue <CloseSafeProducer <K , V >> txIdCache = getCache (producerToRemove .txIdPrefix );
702- if (txIdCache != null && !txIdCache .contains (producerToRemove ) && !txIdCache .offer (producerToRemove )) {
695+ if (producerToRemove .epoch != this .epoch .get ()
696+ || (txIdCache != null && !txIdCache .contains (producerToRemove )
697+ && !txIdCache .offer (producerToRemove ))) {
703698 producerToRemove .closeDelegate (timeout , this .listeners );
704699 return true ;
705700 }
@@ -723,7 +718,8 @@ private CloseSafeProducer<K, V> doCreateTxProducer(String prefix, String suffix,
723718 newProducer = createRawProducer (newProducerConfigs );
724719 newProducer .initTransactions ();
725720 CloseSafeProducer <K , V > closeSafeProducer =
726- new CloseSafeProducer <>(newProducer , remover , prefix , this .physicalCloseTimeout , this .beanName );
721+ new CloseSafeProducer <>(newProducer , remover , prefix , this .physicalCloseTimeout , this .beanName ,
722+ this .epoch .get ());
727723 this .listeners .forEach (listener -> listener .producerAdded (closeSafeProducer .clientId , closeSafeProducer ));
728724 return closeSafeProducer ;
729725 }
@@ -799,20 +795,22 @@ protected static class CloseSafeProducer<K, V> implements Producer<K, V> {
799795
800796 final String clientId ; // NOSONAR
801797
798+ final int epoch ; // NOSONAR
799+
802800 private volatile Exception producerFailed ;
803801
804802 volatile boolean closed ; // NOSONAR
805803
806804 CloseSafeProducer (Producer <K , V > delegate ,
807805 BiPredicate <CloseSafeProducer <K , V >, Duration > removeConsumerProducer , Duration closeTimeout ,
808- String factoryName ) {
806+ String factoryName , int epoch ) {
809807
810- this (delegate , removeConsumerProducer , null , closeTimeout , factoryName );
808+ this (delegate , removeConsumerProducer , null , closeTimeout , factoryName , epoch );
811809 }
812810
813811 CloseSafeProducer (Producer <K , V > delegate ,
814812 BiPredicate <CloseSafeProducer <K , V >, Duration > removeProducer , @ Nullable String txIdPrefix ,
815- Duration closeTimeout , String factoryName ) {
813+ Duration closeTimeout , String factoryName , int epoch ) {
816814
817815 Assert .isTrue (!(delegate instanceof CloseSafeProducer ), "Cannot double-wrap a producer" );
818816 this .delegate = delegate ;
@@ -830,6 +828,7 @@ protected static class CloseSafeProducer<K, V> implements Producer<K, V> {
830828 }
831829 this .clientId = factoryName + "." + id ;
832830 this .created = System .currentTimeMillis ();
831+ this .epoch = epoch ;
833832 LOGGER .debug (() -> "Created new Producer: " + this );
834833 }
835834
0 commit comments