@@ -440,7 +440,7 @@ func (w *WriterReconnector) connectionLoop(ctx context.Context) {
440440 attempt ,
441441 )
442442
443- writer , err := w .startWriteStream (ctx , streamCtx )
443+ writer , err := w .startWriteStream (streamCtx )
444444 w .onWriterChange (writer )
445445 onStreamError := onWriterStarted (err )
446446 if err == nil {
@@ -485,18 +485,26 @@ func (w *WriterReconnector) handleReconnectRetry(
485485 return false
486486}
487487
488- func (w * WriterReconnector ) startWriteStream (ctx , streamCtx context.Context ) (
489- writer * SingleStreamWriter ,
490- err error ,
491- ) {
492- stream , err := w .connectWithTimeout (streamCtx )
488+ func (w * WriterReconnector ) startWriteStream (ctx context.Context ) (writer * SingleStreamWriter , err error ) {
489+ // connectCtx with timeout applies only to the connection phase,
490+ // allowing the main stream context to remain active after exiting this method
491+ connectCtx , stopConnectCtx := xcontext .WithStoppableTimeoutCause (ctx , w .cfg .connectTimeout , errConnTimeout )
492+ defer func () {
493+ // If the context was cancelled during connection (the stream was cancelled),
494+ // we should return a timeout error
495+ if ! stopConnectCtx () && err == nil {
496+ err = context .Cause (connectCtx )
497+ }
498+ }()
499+
500+ stream , err := w .connectWithTimeout (connectCtx )
493501 if err != nil {
494502 return nil , err
495503 }
496504
497505 w .queue .ResetSentProgress ()
498506
499- return NewSingleStreamWriter (ctx , w .createWriterStreamConfig (stream ))
507+ return NewSingleStreamWriter (connectCtx , w .createWriterStreamConfig (stream ))
500508}
501509
502510func (w * WriterReconnector ) needReceiveLastSeqNo () bool {
@@ -505,45 +513,16 @@ func (w *WriterReconnector) needReceiveLastSeqNo() bool {
505513 return res
506514}
507515
508- func (w * WriterReconnector ) connectWithTimeout (streamLifetimeContext context.Context ) (RawTopicWriterStream , error ) {
509- connectCtx , connectCancel := xcontext .WithCancel (streamLifetimeContext )
510-
511- type resT struct {
512- stream RawTopicWriterStream
513- err error
514- }
515- resCh := make (chan resT , 1 )
516-
517- go func () {
518- defer func () {
519- p := recover ()
520- if p != nil {
521- resCh <- resT {
522- stream : nil ,
523- err : xerrors .WithStackTrace (xerrors .Wrap (fmt .Errorf ("ydb: panic while connect to topic writer: %+v" , p ))),
524- }
525- }
526- }()
527-
528- stream , err := w .cfg .Connect (connectCtx , w .cfg .Tracer )
529- resCh <- resT {stream : stream , err : err }
516+ func (w * WriterReconnector ) connectWithTimeout (ctx context.Context ) (stream RawTopicWriterStream , err error ) {
517+ defer func () {
518+ p := recover ()
519+ if p != nil {
520+ stream = nil
521+ err = xerrors .WithStackTrace (xerrors .Wrap (fmt .Errorf ("ydb: panic while connect to topic writer: %+v" , p )))
522+ }
530523 }()
531524
532- timer := time .NewTimer (w .cfg .connectTimeout )
533- defer timer .Stop ()
534-
535- select {
536- case <- timer .C :
537- connectCancel ()
538-
539- return nil , xerrors .WithStackTrace (errConnTimeout )
540- case res := <- resCh :
541- // force no cancel connect context - because it will break stream
542- // context will cancel by cancel streamLifetimeContext while reconnect or stop connection
543- _ = connectCancel
544-
545- return res .stream , res .err
546- }
525+ return w .cfg .Connect (ctx , w .cfg .Tracer )
547526}
548527
549528func (w * WriterReconnector ) onAckReceived (count int ) {
0 commit comments