github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/controllers/indexer/requeuer.go (about)

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