github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/compute/bidstrategy/chained_strategy.go (about)

     1  package bidstrategy
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"reflect"
     7  
     8  	"github.com/filecoin-project/bacalhau/pkg/model"
     9  	"github.com/rs/zerolog/log"
    10  )
    11  
    12  type ChainedBidStrategy struct {
    13  	Strategies []BidStrategy
    14  }
    15  
    16  func NewChainedBidStrategy(strategies ...BidStrategy) *ChainedBidStrategy {
    17  	return &ChainedBidStrategy{Strategies: strategies}
    18  }
    19  
    20  // AddStrategy Add new strategy to the end of the chain
    21  func (c *ChainedBidStrategy) AddStrategy(strategy BidStrategy) {
    22  	c.Strategies = append(c.Strategies, strategy)
    23  }
    24  
    25  // ShouldBid Iterate over all strategies, and return shouldBid if no error is thrown
    26  // and none of the strategies return should not bid.
    27  func (c *ChainedBidStrategy) ShouldBid(ctx context.Context, request BidStrategyRequest) (BidStrategyResponse, error) {
    28  	return c.delegate(ctx, func(strategy BidStrategy) (BidStrategyResponse, error) {
    29  		return strategy.ShouldBid(ctx, request)
    30  	})
    31  }
    32  
    33  // ShouldBidBasedOnUsage Iterate over all strategies, and return shouldBid if no error is thrown
    34  // and none of the strategies return should not bid.
    35  func (c *ChainedBidStrategy) ShouldBidBasedOnUsage(
    36  	ctx context.Context, request BidStrategyRequest, usage model.ResourceUsageData) (BidStrategyResponse, error) {
    37  	return c.delegate(ctx, func(strategy BidStrategy) (BidStrategyResponse, error) {
    38  		return strategy.ShouldBidBasedOnUsage(ctx, request, usage)
    39  	})
    40  }
    41  
    42  func (c *ChainedBidStrategy) delegate(
    43  	ctx context.Context, f func(strategy BidStrategy) (BidStrategyResponse, error)) (BidStrategyResponse, error) {
    44  	if c.Strategies == nil {
    45  		return BidStrategyResponse{}, errors.New("no strategies registered")
    46  	}
    47  	for _, strategy := range c.Strategies {
    48  		response, err := f(strategy)
    49  		if err != nil {
    50  			log.Ctx(ctx).Error().Err(err).Msgf("error asking bidding strategy %s if we should bid",
    51  				reflect.TypeOf(strategy).String())
    52  			return BidStrategyResponse{}, err
    53  		}
    54  		if !response.ShouldBid {
    55  			log.Ctx(ctx).Debug().Msgf("bidding strategy %s returned should not bid due to: %s",
    56  				reflect.TypeOf(strategy).String(), response.Reason)
    57  			return response, nil
    58  		}
    59  	}
    60  
    61  	return newShouldBidResponse(), nil
    62  }
    63  
    64  // Compile-time check to ensure ChainedBidStrategy implements the BidStrategy interface.
    65  var _ BidStrategy = (*ChainedBidStrategy)(nil)