github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/ensured_state.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  )
     8  
     9  type (
    10  	Prolog func(context.Context) (acquired bool, err error)
    11  	Action func(context.Context) error
    12  )
    13  
    14  // WithEnsuredState calls prolog, and if that was successful, calls act. If epilog is not nil, it is guaranteed
    15  // to be called when prolog returns true.
    16  func WithEnsuredState(ctx context.Context, prolog Prolog, action, epilog Action) error {
    17  	wasAcquired, err := prolog(ctx)
    18  	if err != nil {
    19  		return err
    20  	}
    21  	if wasAcquired && epilog != nil {
    22  		defer func() {
    23  			// The context might have been cancelled, so we use the original context
    24  			// without cancellation, but with a deactivation timeout of 10 seconds.
    25  			ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 10*time.Second)
    26  			defer cancel()
    27  			if cerr := epilog(ctx); cerr != nil {
    28  				if err == nil {
    29  					err = cerr
    30  				} else {
    31  					err = fmt.Errorf("%w\n%v", err, cerr)
    32  				}
    33  			}
    34  		}()
    35  	}
    36  	if action != nil {
    37  		err = action(ctx)
    38  	}
    39  	return err
    40  }