SetNetConnAndInitConn replaces the underlying connection and executes the initialization. This method ensures only one initialization can happen at a time by using atomic state transitions. If another goroutine is currently initializing, this will wait for it to complete.
(ctx context.Context, netConn net.Conn)
| 673 | // This method ensures only one initialization can happen at a time by using atomic state transitions. |
| 674 | // If another goroutine is currently initializing, this will wait for it to complete. |
| 675 | func (cn *Conn) SetNetConnAndInitConn(ctx context.Context, netConn net.Conn) error { |
| 676 | // Wait for and transition to INITIALIZING state - this prevents concurrent initializations |
| 677 | // Valid from states: CREATED (first init), IDLE (reconnect), UNUSABLE (handoff/reauth) |
| 678 | // If another goroutine is initializing, we'll wait for it to finish |
| 679 | // if the context has a deadline, use that, otherwise use the connection read (relaxed) timeout |
| 680 | // which should be set during handoff. If it is not set, use a 5 second default |
| 681 | deadline, ok := ctx.Deadline() |
| 682 | if !ok { |
| 683 | deadline = time.Now().Add(cn.getEffectiveReadTimeout(5 * time.Second)) |
| 684 | } |
| 685 | waitCtx, cancel := context.WithDeadline(ctx, deadline) |
| 686 | defer cancel() |
| 687 | // Use predefined slice to avoid allocation |
| 688 | finalState, err := cn.stateMachine.AwaitAndTransition( |
| 689 | waitCtx, |
| 690 | validFromCreatedIdleOrUnusable, |
| 691 | StateInitializing, |
| 692 | ) |
| 693 | if err != nil { |
| 694 | return fmt.Errorf("cannot initialize connection from state %s: %w", finalState, err) |
| 695 | } |
| 696 | |
| 697 | // Replace the underlying connection |
| 698 | cn.SetNetConn(netConn) |
| 699 | |
| 700 | // Execute initialization |
| 701 | // NOTE: ExecuteInitConn (via baseClient.initConn) will transition to IDLE on success |
| 702 | // or CLOSED on failure. We don't need to do it here. |
| 703 | // NOTE: Initconn returns conn in IDLE state |
| 704 | initErr := cn.ExecuteInitConn(ctx) |
| 705 | if initErr != nil { |
| 706 | // ExecuteInitConn already transitioned to CLOSED, just return the error |
| 707 | return initErr |
| 708 | } |
| 709 | |
| 710 | // ExecuteInitConn already transitioned to IDLE |
| 711 | return nil |
| 712 | } |
| 713 | |
| 714 | // MarkForHandoff marks the connection for handoff due to MOVING notification. |
| 715 | // Returns an error if the connection is already marked for handoff. |
no test coverage detected