MCPcopy
hub / github.com/redis/go-redis / MarkQueuedForHandoff

Method MarkQueuedForHandoff

internal/pool/conn.go:737–782  ·  view source on GitHub ↗

MarkQueuedForHandoff marks the connection as queued for handoff processing. This makes the connection unusable until handoff completes. This is called from OnPut hook, where the connection is typically in IN_USE state. The pool will preserve the UNUSABLE state and not overwrite it with IDLE.

()

Source from the content-addressed store, hash-verified

735// This is called from OnPut hook, where the connection is typically in IN_USE state.
736// The pool will preserve the UNUSABLE state and not overwrite it with IDLE.
737func (cn *Conn) MarkQueuedForHandoff() error {
738 // Get current handoff state
739 currentState := cn.handoffStateAtomic.Load()
740 if currentState == nil {
741 return errNotMarkedForHandoff
742 }
743
744 state := currentState.(*HandoffState)
745 if !state.ShouldHandoff {
746 return errNotMarkedForHandoff
747 }
748
749 // Create new state with ShouldHandoff=false but preserve endpoint and seqID
750 // This prevents the connection from being queued multiple times while still
751 // allowing the worker to access the handoff metadata
752 newState := &HandoffState{
753 ShouldHandoff: false,
754 Endpoint: state.Endpoint, // Preserve endpoint for handoff processing
755 SeqID: state.SeqID, // Preserve seqID for handoff processing
756 }
757
758 // Atomic compare-and-swap to update state
759 if !cn.handoffStateAtomic.CompareAndSwap(currentState, newState) {
760 // State changed between load and CAS - retry or return error
761 return errHandoffStateChanged
762 }
763
764 // Transition to UNUSABLE from IN_USE (normal flow), IDLE (edge cases), or CREATED (tests/uninitialized)
765 // The connection is typically in IN_USE state when OnPut is called (normal Put flow)
766 // But in some edge cases or tests, it might be in IDLE or CREATED state
767 // The pool will detect this state change and preserve it (not overwrite with IDLE)
768 // Use predefined slice to avoid allocation
769 finalState, err := cn.stateMachine.TryTransition(validFromCreatedInUseOrIdle, StateUnusable)
770 if err != nil {
771 // Check if already in UNUSABLE state (race condition or retry)
772 // ShouldHandoff should be false now, but check just in case
773 if finalState == StateUnusable && !cn.ShouldHandoff() {
774 // Already unusable - this is fine, keep the new handoff state
775 return nil
776 }
777 // Restore the original state if transition fails for other reasons
778 cn.handoffStateAtomic.Store(currentState)
779 return fmt.Errorf("failed to mark connection as unusable: %w", err)
780 }
781 return nil
782}
783
784// GetID returns the unique identifier for this connection.
785func (cn *Conn) GetID() uint64 {

Callers 3

TestConnectionHookFunction · 0.95
handleMovingMethod · 0.95
OnPutMethod · 0.80

Calls 3

ShouldHandoffMethod · 0.95
TryTransitionMethod · 0.80
LoadMethod · 0.45

Tested by 1

TestConnectionHookFunction · 0.76