github.com/tilt-dev/tilt@v0.36.0/internal/controllers/indexer/requeuer.go (about)

     1  package indexer
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"time"
     8  
     9  	"k8s.io/apimachinery/pkg/types"
    10  	"k8s.io/client-go/util/workqueue"
    11  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    12  	"sigs.k8s.io/controller-runtime/pkg/source"
    13  )
    14  
    15  // Small helper class for triggering a Reconcile() from a goroutine.
    16  type Requeuer struct {
    17  	mu sync.Mutex
    18  	q  workqueue.TypedRateLimitingInterface[reconcile.Request]
    19  }
    20  
    21  var _ source.Source = &Requeuer{}
    22  var _ fmt.Stringer = &Requeuer{}
    23  
    24  func NewRequeuer() *Requeuer {
    25  	return &Requeuer{}
    26  }
    27  
    28  func (s *Requeuer) String() string {
    29  	return "requeuer"
    30  }
    31  
    32  func (s *Requeuer) Start(ctx context.Context, q workqueue.TypedRateLimitingInterface[reconcile.Request]) error {
    33  	s.mu.Lock()
    34  	defer s.mu.Unlock()
    35  	s.q = q
    36  	return nil
    37  }
    38  
    39  func (s *Requeuer) Add(nn types.NamespacedName) {
    40  	s.mu.Lock()
    41  	defer s.mu.Unlock()
    42  	if s.q != nil {
    43  		s.q.Add(reconcile.Request{
    44  			NamespacedName: nn,
    45  		})
    46  	}
    47  }
    48  
    49  type RequeueForTestResult struct {
    50  	ObjName types.NamespacedName
    51  	Error   error
    52  	Result  reconcile.Result
    53  }
    54  
    55  func StartSourceForTesting(
    56  	ctx context.Context,
    57  	s source.Source,
    58  	reconciler reconcile.Reconciler,
    59  	resultChan chan RequeueForTestResult,
    60  ) {
    61  	q := workqueue.NewTypedRateLimitingQueue[reconcile.Request](
    62  		workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](
    63  			time.Millisecond, time.Millisecond))
    64  	_ = s.Start(ctx, q)
    65  
    66  	go func() {
    67  		for ctx.Err() == nil {
    68  			req, shutdown := q.Get()
    69  			if shutdown {
    70  				return
    71  			}
    72  
    73  			res, err := reconciler.Reconcile(ctx, req)
    74  			if resultChan != nil {
    75  				result := RequeueForTestResult{
    76  					ObjName: req.NamespacedName,
    77  					Error:   err,
    78  					Result:  res,
    79  				}
    80  				resultChan <- result
    81  			}
    82  
    83  			q.Done(req)
    84  		}
    85  	}()
    86  }