@@ -127,8 +127,6 @@ public class DefaultKafkaProducerFactory<K, V> implements ProducerFactory<K, V>,
127
127
128
128
private final ThreadLocal <CloseSafeProducer <K , V >> threadBoundProducers = new ThreadLocal <>();
129
129
130
- private final ThreadLocal <Integer > threadBoundProducerEpochs = new ThreadLocal <>();
131
-
132
130
private final AtomicInteger epoch = new AtomicInteger ();
133
131
134
132
private final AtomicInteger clientIdCounter = new AtomicInteger ();
@@ -402,25 +400,21 @@ private Producer<K, V> doCreateProducer(@Nullable String txIdPrefix) {
402
400
}
403
401
if (this .producerPerThread ) {
404
402
CloseSafeProducer <K , V > tlProducer = this .threadBoundProducers .get ();
405
- if (this .threadBoundProducerEpochs .get () == null ) {
406
- this .threadBoundProducerEpochs .set (this .epoch .get ());
407
- }
408
- if (tlProducer != null && this .epoch .get () != this .threadBoundProducerEpochs .get ()) {
403
+ if (tlProducer != null && this .epoch .get () != tlProducer .epoch ) {
409
404
closeThreadBoundProducer ();
410
405
tlProducer = null ;
411
406
}
412
407
if (tlProducer == null ) {
413
408
tlProducer = new CloseSafeProducer <>(createKafkaProducer (), this ::removeProducer ,
414
- this .physicalCloseTimeout );
409
+ this .physicalCloseTimeout , this . epoch );
415
410
this .threadBoundProducers .set (tlProducer );
416
- this .threadBoundProducerEpochs .set (this .epoch .get ());
417
411
}
418
412
return tlProducer ;
419
413
}
420
414
synchronized (this ) {
421
415
if (this .producer == null ) {
422
416
this .producer = new CloseSafeProducer <>(createKafkaProducer (), this ::removeProducer ,
423
- this .physicalCloseTimeout );
417
+ this .physicalCloseTimeout , this . epoch );
424
418
}
425
419
return this .producer ;
426
420
}
@@ -527,7 +521,8 @@ private CloseSafeProducer<K, V> doCreateTxProducer(String prefix, String suffix,
527
521
newProducer = createRawProducer (newProducerConfigs );
528
522
newProducer .initTransactions ();
529
523
return new CloseSafeProducer <>(newProducer , getCache (prefix ), remover ,
530
- (String ) newProducerConfigs .get (ProducerConfig .TRANSACTIONAL_ID_CONFIG ), this .physicalCloseTimeout );
524
+ (String ) newProducerConfigs .get (ProducerConfig .TRANSACTIONAL_ID_CONFIG ), this .physicalCloseTimeout ,
525
+ this .epoch );
531
526
}
532
527
533
528
protected Producer <K , V > createRawProducer (Map <String , Object > configs ) {
@@ -596,37 +591,57 @@ protected static class CloseSafeProducer<K, V> implements Producer<K, V> {
596
591
597
592
private final Duration closeTimeout ;
598
593
594
+ final int epoch ; // NOSONAR
595
+
596
+ private final AtomicInteger factoryEpoch ;
597
+
599
598
private volatile Exception producerFailed ;
600
599
601
600
private volatile boolean closed ;
602
601
603
602
CloseSafeProducer (Producer <K , V > delegate , Consumer <CloseSafeProducer <K , V >> removeProducer ,
604
603
Duration closeTimeout ) {
605
604
606
- this (delegate , null , removeProducer , null , closeTimeout );
605
+ this (delegate , null , removeProducer , null , closeTimeout , new AtomicInteger ());
606
+ Assert .isTrue (!(delegate instanceof CloseSafeProducer ), "Cannot double-wrap a producer" );
607
+ }
608
+
609
+ CloseSafeProducer (Producer <K , V > delegate , Consumer <CloseSafeProducer <K , V >> removeProducer ,
610
+ Duration closeTimeout , AtomicInteger epoch ) {
611
+
612
+ this (delegate , null , removeProducer , null , closeTimeout , epoch );
607
613
Assert .isTrue (!(delegate instanceof CloseSafeProducer ), "Cannot double-wrap a producer" );
608
614
}
609
615
610
616
CloseSafeProducer (Producer <K , V > delegate , BlockingQueue <CloseSafeProducer <K , V >> cache ,
611
617
Duration closeTimeout ) {
612
- this (delegate , cache , null , closeTimeout );
618
+ this (delegate , cache , null , null , closeTimeout , new AtomicInteger () );
613
619
}
614
620
615
621
CloseSafeProducer (Producer <K , V > delegate , BlockingQueue <CloseSafeProducer <K , V >> cache ,
616
622
@ Nullable Consumer <CloseSafeProducer <K , V >> removeConsumerProducer , Duration closeTimeout ) {
617
623
618
- this (delegate , cache , removeConsumerProducer , null , closeTimeout );
624
+ this (delegate , cache , removeConsumerProducer , null , closeTimeout , new AtomicInteger () );
619
625
}
620
626
621
627
CloseSafeProducer (Producer <K , V > delegate , BlockingQueue <CloseSafeProducer <K , V >> cache ,
622
628
@ Nullable Consumer <CloseSafeProducer <K , V >> removeProducer , @ Nullable String txId ,
623
629
Duration closeTimeout ) {
624
630
631
+ this (delegate , cache , removeProducer , txId , closeTimeout , new AtomicInteger ());
632
+ }
633
+
634
+ CloseSafeProducer (Producer <K , V > delegate , BlockingQueue <CloseSafeProducer <K , V >> cache ,
635
+ @ Nullable Consumer <CloseSafeProducer <K , V >> removeProducer , @ Nullable String txId ,
636
+ Duration closeTimeout , AtomicInteger epoch ) {
637
+
625
638
this .delegate = delegate ;
626
639
this .cache = cache ;
627
640
this .removeProducer = removeProducer ;
628
641
this .txId = txId ;
629
642
this .closeTimeout = closeTimeout ;
643
+ this .epoch = epoch .get ();
644
+ this .factoryEpoch = epoch ;
630
645
LOGGER .debug (() -> "Created new Producer: " + this );
631
646
}
632
647
@@ -760,8 +775,8 @@ public void close(@Nullable Duration timeout) {
760
775
else {
761
776
if (this .cache != null && this .removeProducer == null ) { // dedicated consumer producers are not cached
762
777
synchronized (this ) {
763
- if (! this .cache . contains ( this )
764
- && !this .cache .offer (this )) {
778
+ if (this . epoch != this .factoryEpoch . get ( )
779
+ || (! this . cache . contains ( this ) && !this .cache .offer (this ) )) {
765
780
this .closed = true ;
766
781
this .delegate .close (timeout );
767
782
}
0 commit comments