@@ -550,7 +550,10 @@ func (b *broker) loadConnection(ctx context.Context, req kmsg.Request) (*brokerC
550
550
return * pcxn , nil
551
551
}
552
552
553
+ var tries int
553
554
start := time .Now ()
555
+ doConnect:
556
+ tries ++
554
557
conn , err := b .connect (ctx )
555
558
defer func () {
556
559
since := time .Since (start )
@@ -572,7 +575,17 @@ func (b *broker) loadConnection(ctx context.Context, req kmsg.Request) (*brokerC
572
575
conn : conn ,
573
576
deadCh : make (chan struct {}),
574
577
}
575
- if err = cxn .init (isProduceCxn ); err != nil {
578
+ if err = cxn .init (isProduceCxn , tries ); err != nil {
579
+ // EventHubs does not handle v4 and resets the connection. We
580
+ // retry twice. On the first and second attempt, we try our max
581
+ // version possible (as should be allowed). On the third try,
582
+ // we downgrade to v0.
583
+ if er := (* errApiVersionsReset )(nil ); errors .As (err , & er ) {
584
+ if tries < 3 {
585
+ tries ++
586
+ goto doConnect
587
+ }
588
+ }
576
589
b .cl .cfg .logger .Log (LogLevelDebug , "connection initialization failed" , "addr" , b .addr , "broker" , logID (b .meta .NodeID ), "err" , err )
577
590
cxn .closeConn ()
578
591
return nil , err
@@ -719,11 +732,11 @@ type brokerCxn struct {
719
732
deadCh chan struct {}
720
733
}
721
734
722
- func (cxn * brokerCxn ) init (isProduceCxn bool ) error {
735
+ func (cxn * brokerCxn ) init (isProduceCxn bool , tries int ) error {
723
736
hasVersions := cxn .b .loadVersions () != nil
724
737
if ! hasVersions {
725
738
if cxn .b .cl .cfg .maxVersions == nil || cxn .b .cl .cfg .maxVersions .HasKey (18 ) {
726
- if err := cxn .requestAPIVersions (); err != nil {
739
+ if err := cxn .requestAPIVersions (tries ); err != nil {
727
740
if ! errors .Is (err , ErrClientClosed ) && ! isRetryableBrokerErr (err ) {
728
741
cxn .cl .cfg .logger .Log (LogLevelError , "unable to request api versions" , "broker" , logID (cxn .b .meta .NodeID ), "err" , err )
729
742
}
@@ -749,14 +762,15 @@ func (cxn *brokerCxn) init(isProduceCxn bool) error {
749
762
return nil
750
763
}
751
764
752
- func (cxn * brokerCxn ) requestAPIVersions () error {
753
- maxVersion := int16 (3 )
754
-
755
- // If the user configured a max versions, we check that the key exists
756
- // before entering this function. Thus, we expect exists to be true,
757
- // but we still doubly check it for sanity (as well as userMax, which
758
- // can only be non-negative based off of LookupMaxKeyVersion's API).
759
- if cxn .cl .cfg .maxVersions != nil {
765
+ func (cxn * brokerCxn ) requestAPIVersions (tries int ) error {
766
+ maxVersion := int16 (4 )
767
+ if tries >= 3 { // on the third try, we pin to v0; see above in cxn initialization
768
+ maxVersion = 0
769
+ } else if cxn .cl .cfg .maxVersions != nil {
770
+ // If the user configured a max versions, we check that the key exists
771
+ // before entering this function. Thus, we expect exists to be true,
772
+ // but we still doubly check it for sanity (as well as userMax, which
773
+ // can only be non-negative based off of LookupMaxKeyVersion's API).
760
774
userMax , exists := cxn .cl .cfg .maxVersions .LookupMaxKeyVersion (18 ) // 18 == api versions
761
775
if exists && userMax >= 0 {
762
776
maxVersion = userMax
@@ -779,6 +793,9 @@ start:
779
793
// api versions does *not* use flexible response headers; see comment in promisedResp
780
794
rawResp , err := cxn .readResponse (nil , req .Key (), req .GetVersion (), corrID , false , rt , bytesWritten , writeWait , timeToWrite , readEnqueue )
781
795
if err != nil {
796
+ if strings .HasSuffix (err .Error (), "connection reset by peer" ) {
797
+ return & errApiVersionsReset {err }
798
+ }
782
799
return err
783
800
}
784
801
if len (rawResp ) < 2 {
0 commit comments